ardhi
2 years ago
11 changed files with 2006 additions and 500 deletions
@ -0,0 +1,30 @@
|
||||
.bottommodal-window-button-container { |
||||
float: right; |
||||
right: 10px; |
||||
text-align: right; |
||||
} |
||||
|
||||
.bottommodal-close, |
||||
.bottommodal-maximize, |
||||
.bottommodal-minimize { |
||||
cursor: pointer; |
||||
padding: 4px; |
||||
} |
||||
|
||||
.bottommodal-header { |
||||
margin-bottom: -10px; |
||||
} |
||||
|
||||
.bottommodal-title { |
||||
font-size: 16px; |
||||
font-weight: 750; |
||||
text-align: left; |
||||
margin-left: 20px; |
||||
color: #FFFFFF; |
||||
} |
||||
|
||||
.bottommodal-close:hover, |
||||
.bottommodal-maximize:hover, |
||||
.bottommodal-minimize:hover { |
||||
color: #20a8d8; |
||||
} |
@ -0,0 +1,173 @@
|
||||
import React, { useMemo, useState } from 'react' |
||||
import { Resizable } from 're-resizable' |
||||
import './BottomModal.css' |
||||
import { Card, CardBody, CardHeader, Col, Row, Table } from 'reactstrap' |
||||
import Icon from '@iconify/react' |
||||
import closeCircleOutline from '@iconify/icons-ion/close-circle-outline'; |
||||
import removeCircleOutline from '@iconify/icons-ion/remove-circle-outline'; |
||||
import windowMaximaze from '@iconify/icons-mdi/window-maximize'; |
||||
|
||||
const BottomModal = ({title, tableHeader, tableData, closeModal}) => { |
||||
const [tableHeight, setTableHeight] = useState(150) |
||||
const [resizableWidth, setResizableWidth] = useState("100%") |
||||
const [resizableHeight, setResizableHeight] = useState(300) |
||||
const [maximizeTitle, setMaximizeTitle] = useState("maximize") |
||||
|
||||
const setBottomTableWindow = (type) => { |
||||
if (type === 'min') { |
||||
// minimize
|
||||
setResizableHeight(55); |
||||
setTableHeight(150) |
||||
} |
||||
else if (type === 'max') { |
||||
if (resizableHeight === '100vh') { |
||||
// restore
|
||||
setResizableHeight(300) |
||||
setTableHeight(150) |
||||
setMaximizeTitle("maximize"); |
||||
} |
||||
else { |
||||
// maximize
|
||||
// setResizableHeight(600)
|
||||
// setTableHeight(950)
|
||||
setResizableHeight('100vh'); |
||||
setTableHeight('90vh'); |
||||
setMaximizeTitle("restore"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
const renderTableRow = (item) => { |
||||
let row = []; |
||||
// looping through its object keys (item is an object)
|
||||
Object.keys(item).map(key => { |
||||
// if (key !== 'id') {
|
||||
row.push(<td>{item[key]}</td>) |
||||
// }
|
||||
}) |
||||
return row; |
||||
} |
||||
|
||||
const RenderTable = useMemo(() => { |
||||
if (tableData && tableData.length > 0) { |
||||
return ( |
||||
<Table size='sm'> |
||||
<thead style={{margin: 0, backgroundColor: '#888888', color: '#FFFFFF', fontSize: 12}}> |
||||
<tr> |
||||
<th>#</th> |
||||
{tableHeader && tableHeader.length > 0 && |
||||
tableHeader.map((item, idx) => ( |
||||
<th key={idx}>{item.title}</th> |
||||
)) |
||||
} |
||||
</tr> |
||||
</thead> |
||||
<tbody style={{backgroundColor: '#EEEEEE'}}> |
||||
{tableData && tableData.length > 0 && |
||||
tableData.map((item, index) => { |
||||
return (<tr key={index}> |
||||
{renderTableRow(item, tableHeader)} |
||||
</tr>) |
||||
}) |
||||
} |
||||
</tbody> |
||||
</Table> |
||||
) |
||||
} |
||||
|
||||
return ( |
||||
// <Table>
|
||||
// <tr>
|
||||
// <td style={{ fontWeight: "bold" }} colSpan="4" align="center">No Data Available</td>
|
||||
// </tr>
|
||||
// </Table>
|
||||
<div style={{justifyContent: 'center', textAlign: 'center', color: 'red', marginTop: 50, marginBottom: 50}}> |
||||
No Data Available |
||||
</div> |
||||
) |
||||
}, [tableData]) |
||||
|
||||
return ( |
||||
<Resizable |
||||
style={{ |
||||
position: "fixed", |
||||
width: "100%", |
||||
bottom: 0, |
||||
left: 0, |
||||
right: 0, |
||||
background: "#222222", |
||||
borderTopLeftRadius: 10, |
||||
borderTopRightRadius: 10, |
||||
zIndex: 9999 |
||||
}} |
||||
size={{ |
||||
width: resizableWidth, |
||||
height: resizableHeight |
||||
}} |
||||
maxHeight="100vh" |
||||
minWidth="100%" |
||||
enable={{ top: true, right: false, bottom: false, left: false, topRight: false, bottomRight: false, bottomLeft: false, topLeft: false }} |
||||
onResizeStop={(e, direction, ref, d) => { |
||||
setResizableWidth("100%"); |
||||
setResizableHeight(resizableHeight + d.height); |
||||
if (e.screenY < 100) { // max
|
||||
setResizableHeight('100vh'); |
||||
setTableHeight(450) |
||||
} |
||||
else if (e.screenY < 150) { |
||||
setTableHeight(400) |
||||
} |
||||
else if (e.screenY < 200) { |
||||
setTableHeight(350) |
||||
} |
||||
else if (e.screenY < 250) { |
||||
setTableHeight(300) |
||||
} |
||||
else if (e.screenY < 300) { |
||||
setTableHeight(250) |
||||
} |
||||
else if (e.screenY < 400) { |
||||
setTableHeight(200) |
||||
} |
||||
else if (e.screenY < 600) { |
||||
setTableHeight(150) // default
|
||||
} |
||||
else if (e.screenY >= 600) { |
||||
setBottomTableWindow('min'); |
||||
} |
||||
}} |
||||
> |
||||
<div style={{ paddingTop: 10, position: "relative", height: "100%" }}> |
||||
<Row className="bottommodal-header"> |
||||
<Col md={8}> |
||||
<p className="bottommodal-title">{title}</p> |
||||
</Col> |
||||
<Col md={4} className="bottommodal-window-button-container"> |
||||
<span className="bottommodal-minimize" title="minimize" |
||||
onClick={() => setBottomTableWindow("min")} |
||||
> |
||||
<Icon icon={removeCircleOutline} width={30} height={30} color="#FFFFFF" /> |
||||
</span> |
||||
<span className="bottommodal-maximize" title={maximizeTitle} |
||||
onClick={() => setBottomTableWindow("max")} |
||||
> |
||||
<Icon icon={windowMaximaze} width={30} height={30} color="#FFFFFF" /> |
||||
</span> |
||||
<span className="bottommodal-close" title="close" |
||||
onClick={closeModal} |
||||
> |
||||
<Icon icon={closeCircleOutline} width={30} height={30} color="#FFFFFF" /> |
||||
</span> |
||||
</Col> |
||||
</Row> |
||||
<Card style={{ margin: 10 }}> |
||||
<CardBody style={{ margin: 0, padding: 0, borderRadius: 5, backgroundColor: '#EEEEEE', overflowY: 'auto', height: resizableHeight === 300 ? 240 : 540 }}> |
||||
{RenderTable} |
||||
</CardBody> |
||||
</Card> |
||||
</div> |
||||
</Resizable> |
||||
) |
||||
} |
||||
|
||||
export default BottomModal; |
@ -0,0 +1,7 @@
|
||||
{ |
||||
"name": "BottomModal", |
||||
"version": "0.0.0", |
||||
"private": true, |
||||
"main": "./BottomModal.js" |
||||
} |
||||
|
@ -0,0 +1,361 @@
|
||||
import React, { useEffect, useState } from 'react'; |
||||
import { |
||||
Chart as ChartJS, |
||||
CategoryScale, |
||||
LineController, |
||||
LineElement, |
||||
LinearScale, |
||||
BarController, |
||||
BarElement, |
||||
PieController, |
||||
Title, |
||||
Tooltip, |
||||
Legend, |
||||
ArcElement |
||||
} from 'chart.js'; |
||||
// import Chart from 'chart.js/auto';
|
||||
import { Chart, Bar, Line, Pie } from 'react-chartjs-2'; |
||||
import ChartDataLabels from 'chartjs-plugin-datalabels'; |
||||
import ContentLoader from 'react-content-loader'; |
||||
|
||||
ChartJS.register( |
||||
CategoryScale, |
||||
LineController, |
||||
LineElement, |
||||
LinearScale, |
||||
BarController, |
||||
BarElement, |
||||
PieController, |
||||
Title, |
||||
Tooltip, |
||||
Legend, |
||||
ArcElement, |
||||
ChartDataLabels |
||||
); |
||||
|
||||
const styles = { |
||||
cardContainer: { backgroundColor: '#F8F8F8', margin: 2, paddingLeft: 20, paddingRight: 20, paddingTop: 10, height: '30vh' }, |
||||
cardHeaderContainer: { display: 'flex', flexDirection: 'row', marginBottom: 10 }, |
||||
cardChartContainer: { position: 'relative', height: '20vh', margin: 'auto', paddingBottom: 10, justifyContent: 'center' }, |
||||
cardTitle: { color: '#444444', fontSize: 14, fontWeight: 'bold' }, |
||||
cardSubtitle: { color: '#888888', fontSize: 12 } |
||||
} |
||||
|
||||
const verticalBarChartOption = { |
||||
elements: { |
||||
bar: { |
||||
borderWidth: 2, |
||||
}, |
||||
}, |
||||
indexAxis: 'x', |
||||
responsive: true, |
||||
maintainAspectRatio: false, |
||||
plugins: { |
||||
legend: { |
||||
display: true, |
||||
position: 'right', |
||||
labels: { |
||||
boxWidth: 10 |
||||
} |
||||
}, |
||||
datalabels: { |
||||
color: '#FFFFFF' |
||||
} |
||||
}, |
||||
// scales: {
|
||||
// yAxes: [{
|
||||
// afterFit: function(scaleInstance) {
|
||||
// scaleInstance.width = 100; // sets the width to 100px
|
||||
// }
|
||||
// }]
|
||||
// }
|
||||
} |
||||
|
||||
const horizontalBarChartOption = { |
||||
indexAxis: 'y', |
||||
elements: { |
||||
bar: { |
||||
borderWidth: 2, |
||||
}, |
||||
}, |
||||
responsive: true, |
||||
maintainAspectRatio: false, |
||||
plugins: { |
||||
legend: { |
||||
display: false, |
||||
}, |
||||
datalabels: { |
||||
color: '#FFFFFF' |
||||
} |
||||
} |
||||
} |
||||
|
||||
const pieChartOption = { |
||||
elements: { |
||||
pie: { |
||||
borderWidth: 2, |
||||
}, |
||||
}, |
||||
responsive: true, |
||||
maintainAspectRatio: false, |
||||
plugins: { |
||||
legend: { |
||||
display: true, |
||||
position: 'right', |
||||
labels: { |
||||
boxWidth: 10 |
||||
} |
||||
}, |
||||
datalabels: { |
||||
color: '#FFFFFF' |
||||
} |
||||
} |
||||
} |
||||
|
||||
const lineChartOption = { |
||||
elements: { |
||||
line: { |
||||
borderWidth: 2, |
||||
}, |
||||
}, |
||||
responsive: false, |
||||
plugins: { |
||||
datalabels: { |
||||
color: '#FFFFFF' |
||||
} |
||||
} |
||||
} |
||||
|
||||
const optionsExpenditure = { |
||||
indexAxis: 'y', |
||||
elements: { |
||||
bar: { |
||||
borderWidth: 2, |
||||
}, |
||||
}, |
||||
responsive: true, |
||||
maintainAspectRatio: false, |
||||
plugins: { |
||||
legend: { |
||||
display: false, |
||||
position: 'right', |
||||
labels: { |
||||
boxWidth: 10 |
||||
} |
||||
}, |
||||
datalabels: { |
||||
color: '#FFFFFF' |
||||
} |
||||
}, |
||||
}; |
||||
|
||||
const optionsScheduleHealthPerDivision = { |
||||
elements: { |
||||
bar: { |
||||
borderWidth: 2, |
||||
}, |
||||
}, |
||||
indexAxis: 'x', |
||||
responsive: true, |
||||
maintainAspectRatio: false, |
||||
plugins: { |
||||
legend: { |
||||
display: true, |
||||
position: 'top', |
||||
labels: { |
||||
boxWidth: 10, |
||||
font: { |
||||
size: 10 |
||||
} |
||||
} |
||||
}, |
||||
datalabels: { |
||||
color: '#FFFFFF' |
||||
} |
||||
} |
||||
} |
||||
|
||||
export const ContentLoaderChart = ({type}) => { |
||||
if (type === 'vertical-bar') { |
||||
return ( |
||||
<ContentLoader |
||||
speed={2} |
||||
width="100%" |
||||
height="100%" |
||||
viewBox="0 0 500 200" |
||||
backgroundColor="#f3f3f3" |
||||
foregroundColor="#ecebeb" |
||||
> |
||||
{/* <rect x="6" y="88" rx="4" ry="4" width="18" height="105" />
|
||||
<rect x="36" y="64" rx="4" ry="4" width="18" height="129" />
|
||||
<rect x="64" y="130" rx="4" ry="4" width="18" height="62" />
|
||||
<rect x="91" y="87" rx="4" ry="4" width="18" height="105" />
|
||||
<rect x="118" y="107" rx="4" ry="4" width="18" height="85" />
|
||||
<rect x="147" y="92" rx="4" ry="4" width="18" height="100" />
|
||||
<rect x="176" y="120" rx="4" ry="4" width="18" height="72" />
|
||||
<rect x="207" y="54" rx="4" ry="4" width="18" height="138" />
|
||||
<rect x="267" y="94" rx="4" ry="4" width="18" height="98" />
|
||||
<rect x="235" y="56" rx="4" ry="4" width="18" height="136" />
|
||||
<rect x="298" y="68" rx="4" ry="4" width="18" height="124" />
|
||||
<rect x="330" y="77" rx="4" ry="4" width="18" height="114" />
|
||||
<rect x="360" y="106" rx="4" ry="4" width="18" height="84" />
|
||||
<rect x="388" y="155" rx="4" ry="4" width="18" height="35" />
|
||||
<rect x="417" y="108" rx="4" ry="4" width="18" height="81" />
|
||||
<rect x="450" y="82" rx="4" ry="4" width="18" height="107" /> */} |
||||
{/* <rect x="13" y="47" rx="4" ry="4" width="39" height="140" />
|
||||
<rect x="61" y="9" rx="4" ry="4" width="39" height="178" />
|
||||
<rect x="112" y="28" rx="4" ry="4" width="39" height="160" />
|
||||
<rect x="186" y="45" rx="4" ry="4" width="39" height="140" />
|
||||
<rect x="234" y="7" rx="4" ry="4" width="39" height="178" />
|
||||
<rect x="284" y="27" rx="4" ry="4" width="39" height="160" />
|
||||
<rect x="358" y="45" rx="4" ry="4" width="39" height="140" />
|
||||
<rect x="406" y="7" rx="4" ry="4" width="39" height="178" />
|
||||
<rect x="456" y="27" rx="4" ry="4" width="39" height="160" /> */} |
||||
<rect x="13" y="87" rx="4" ry="4" width="39" height="106" />
|
||||
<rect x="61" y="21" rx="4" ry="4" width="39" height="171" />
|
||||
<rect x="112" y="61" rx="4" ry="4" width="39" height="131" />
|
||||
<rect x="185" y="87" rx="4" ry="4" width="39" height="106" />
|
||||
<rect x="233" y="21" rx="4" ry="4" width="39" height="171" />
|
||||
<rect x="284" y="61" rx="4" ry="4" width="39" height="131" />
|
||||
<rect x="354" y="88" rx="4" ry="4" width="39" height="106" />
|
||||
<rect x="402" y="22" rx="4" ry="4" width="39" height="171" />
|
||||
<rect x="453" y="62" rx="4" ry="4" width="39" height="131" /> |
||||
</ContentLoader> |
||||
) |
||||
} |
||||
else if (type === 'pie') { |
||||
return ( |
||||
<ContentLoader |
||||
speed={2} |
||||
width="100%" |
||||
height="100%" |
||||
viewBox="0 0 200 100" |
||||
backgroundColor="#f3f3f3" |
||||
foregroundColor="#ecebeb" |
||||
> |
||||
<circle cx="45" cy="41" r="39" />
|
||||
<rect x="98" y="15" rx="8" ry="8" width="82" height="13" /> |
||||
<rect x="98" y="35" rx="8" ry="8" width="82" height="13" />
|
||||
<rect x="98" y="56" rx="8" ry="8" width="82" height="13" /> |
||||
</ContentLoader> |
||||
) |
||||
} |
||||
else { |
||||
return ( |
||||
<ContentLoader |
||||
speed={2} |
||||
width="100%" |
||||
height="100%" |
||||
viewBox="0 0 200 100" |
||||
backgroundColor="#f3f3f3" |
||||
foregroundColor="#ecebeb" |
||||
> |
||||
<rect x="0" y="0" rx="10" ry="10" width="25%" height="20" /> |
||||
<rect x="0" y="25" rx="10" ry="10" width="75%" height="20" /> |
||||
<rect x="0" y="50" rx="10" ry="10" width="100%" height="20" /> |
||||
<rect x="0" y="75" rx="10" ry="10" width="45%" height="20" /> |
||||
</ContentLoader> |
||||
) |
||||
} |
||||
} |
||||
|
||||
// export const FullCard =
|
||||
|
||||
export const CardDashboard = ({ title, subtitle, chartType, chartData, chartOption, isReady }) => { |
||||
let chart = null; |
||||
if (chartType === 'vertical-bar') { |
||||
chart = <Bar |
||||
options={chartOption ? chartOption : verticalBarChartOption} |
||||
data={chartData ? chartData : null} |
||||
/> |
||||
} |
||||
else if (chartType === 'horizontal-bar') { |
||||
chart = <Bar |
||||
options={chartOption ? chartOption : horizontalBarChartOption} |
||||
data={chartData ? chartData : null} |
||||
/> |
||||
} |
||||
else if (chartType === 'pie') { |
||||
chart = <Pie |
||||
options={chartOption ? chartOption : pieChartOption} |
||||
data={chartData ? chartData : null} |
||||
/> |
||||
} |
||||
else if (chartType === 'line') { |
||||
chart = <Line |
||||
options={chartOption ? chartOption : lineChartOption} |
||||
data={chartData ? chartData : null} |
||||
/> |
||||
} |
||||
|
||||
return ( |
||||
<div style={styles.cardContainer}> |
||||
<div style={styles.cardHeaderContainer}> |
||||
<div style={{ flex: 20, display: 'flex', flexDirection: 'column' }}> |
||||
<div style={styles.cardTitle}>{title}</div> |
||||
<div style={styles.cardSubtitle}>{subtitle}</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div style={styles.cardChartContainer}> |
||||
{ isReady ?
|
||||
chartData ? chart : <NoDataChart />
|
||||
: |
||||
<ContentLoaderChart type={chartType}/> |
||||
} |
||||
</div> |
||||
|
||||
</div> |
||||
) |
||||
} |
||||
|
||||
// export const CardExpenditure = ({ title, subtitle, chartData, chartOption }) => {
|
||||
// return (
|
||||
// <div style={styles.cardContainer}>
|
||||
// <div style={styles.cardHeaderContainer}>
|
||||
// <div style={{ flex: 20, display: 'flex', flexDirection: 'column' }}>
|
||||
// <div style={styles.cardTitle}>{title}</div>
|
||||
// <div style={styles.cardSubtitle}>{subtitle}</div>
|
||||
// </div>
|
||||
// <div style={{ flex: 6, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||
// <div style={{ backgroundColor: '#DDDDDD', color: '#4C4747', borderRadius: 5, padding: 4, fontWeight: 500, cursor: 'pointer', fontSize: 12, textAlign: 'center', lineHeight: 'normal' }}>Detailed View</div>
|
||||
// </div>
|
||||
// </div>
|
||||
|
||||
// <div style={styles.cardChartContainer}>
|
||||
// <Bar options={chartOption ? chartOption : optionsExpenditure} data={chartData ? chartData : null} />
|
||||
// </div>
|
||||
|
||||
// </div>
|
||||
// )
|
||||
// }
|
||||
|
||||
export const CardScheduleHealthPerDivision = ({ isReady, title, subtitle, mode, changeMode, chartData, chartOption, chartType }) => { |
||||
return ( |
||||
<div style={{ backgroundColor: '#F8F8F8', margin: 2, paddingLeft: 20, paddingRight: 20, paddingTop: 10, height: '30vh' }}> |
||||
<div style={{ display: 'flex', flexDirection: 'row', marginBottom: 10 }}> |
||||
<div style={{ flex: 20, display: 'flex', flexDirection: 'column' }}> |
||||
<div style={styles.cardTitle}>{title}</div> |
||||
<div style={styles.cardSubtitle}>{subtitle}</div> |
||||
</div> |
||||
<div style={{ flex: 6, display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center' }}> |
||||
<div style={{ width: '100%', textAlign: 'center', height: 24, fontSize: 12, verticalAlign: 'middle', cursor: 'pointer', color: '#FFFFFF', backgroundColor: mode === 'budget' ? '#52AC0B' : '#777777' }} onClick={() => changeMode('budget')}>Budget</div> |
||||
<div style={{ width: '100%', textAlign: 'center', height: 24, fontSize: 12, verticalAlign: 'middle', cursor: 'pointer', color: '#FFFFFF', backgroundColor: mode === 'schedule' ? '#52AC0B' : '#777777' }} onClick={() => changeMode('schedule')}>Schedule</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div style={{ position: 'relative', height: '20vh', margin: 'auto', paddingBottom: 10, justifyContent: 'center' }}> |
||||
{isReady ? chartData ? <Bar options={chartOption ? chartOption : optionsScheduleHealthPerDivision} data={chartData ? chartData : null} /> : <NoDataChart /> : <ContentLoaderChart type={chartType}/> } |
||||
</div> |
||||
|
||||
</div> |
||||
) |
||||
} |
||||
|
||||
export const NoDataChart = ({message}) => { |
||||
return ( |
||||
<div style={{textAlign: 'center', marginTop: 50, alignSelf: 'center', alignItems: 'center', justifyContent: 'center', color: 'red'}}> |
||||
{message ? message : "No Data Available"} |
||||
</div> |
||||
) |
||||
} |
@ -0,0 +1,7 @@
|
||||
{ |
||||
"name": "CardDashboard", |
||||
"version": "0.0.0", |
||||
"private": true, |
||||
"main": "./CardDashboard.js" |
||||
} |
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,244 @@
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'; |
||||
import axios from 'axios' |
||||
import { Row, Col } from 'antd'; |
||||
import { CardDashboard, CardExpenditure, CardScheduleHealthPerDivision } from '../../components/CardDashboard/CardDashboard'; |
||||
import L from 'leaflet'; |
||||
import { useParams } from 'react-router-dom'; |
||||
import '../../assets/css/customscroll.css' |
||||
import moment from 'moment'; |
||||
import { BASE_OSPRO } from '../../const/ApiConst'; |
||||
|
||||
const styles = { |
||||
cardContainer: { backgroundColor: '#F8F8F8', margin: 2, paddingLeft: 20, paddingRight: 20, paddingTop: 10 }, |
||||
cardHeaderContainer: { display: 'flex', flexDirection: 'row', marginBottom: 10 }, |
||||
cardChartContainer: { position: 'relative', height: '21vh', margin: 'auto', paddingBottom: 10, justifyContent: 'center' }, |
||||
cardTitle: { color: '#444444', fontSize: 16, fontWeight: 'bold' }, |
||||
cardSubtitle: { color: '#888888', fontSize: 12 } |
||||
} |
||||
|
||||
const center = { |
||||
lat: -6.200000, |
||||
lng: 106.816666 |
||||
} |
||||
|
||||
const DashboardCustomer = () => { |
||||
const token = localStorage.getItem("token") |
||||
const HEADER = { |
||||
headers: { |
||||
"Content-Type": "application/json", |
||||
"Authorization": `Bearer ${token}` |
||||
} |
||||
} |
||||
const { PROJECT_ID, GANTT_ID } = useParams(); |
||||
// const URL_GANTT = `http://103.73.125.81:8446/index.html?base_url=http://103.73.125.81:8444/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1`;
|
||||
const URL_GANTT = `http://103.73.125.81:8446/index.html?base_url=${BASE_OSPRO}/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1`; |
||||
const mapRef = useRef() |
||||
const [projectName, setProjectName] = useState("Project Tower ABC"); |
||||
const [customerName, setCustomerName] = useState("Jaya Gedung Group"); |
||||
const [plannedStart, setPlannedStart] = useState("2019-03-04") |
||||
const [plannedFinish, setPlannedFinish] = useState("2020-05-28") |
||||
const [actualStart, setActualStart] = useState("2019-03-04") |
||||
const [actualFinish, setActualFinish] = useState("2020-05-28") |
||||
const [estimatedFinish, setEstimatedFinish] = useState("2020-05-28") |
||||
const [mymap, setMymap] = useState(null); |
||||
const [activeTabIdx, setActiveTabIdx] = useState(0); |
||||
const [activeTabCommentIdx, setActiveTabCommentIdx] = useState(0); |
||||
const [planningProgress, setPlanningProgress] = useState(79); |
||||
const [actualProgress, setActualProgress] = useState(50); |
||||
|
||||
|
||||
|
||||
useEffect(() => { |
||||
console.log('URL_GANTT', URL_GANTT); |
||||
return () => { |
||||
console.log('unmount RenderMap'); |
||||
} |
||||
}, []) |
||||
|
||||
useEffect(() => { |
||||
if (activeTabIdx === 1) { |
||||
initMap(); |
||||
} |
||||
}, [activeTabIdx]); |
||||
|
||||
const initMap = () => { |
||||
let mymap = L.map('map-area', { |
||||
center: center, |
||||
zoom: 13 |
||||
}) |
||||
|
||||
setMymap(mymap); |
||||
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'}).addTo(mymap); |
||||
} |
||||
|
||||
const RenderGantt = useMemo(() => ( |
||||
<iframe |
||||
id="frame-gantt" |
||||
src={URL_GANTT} |
||||
style={{ |
||||
width: '100%', |
||||
height: '100%', |
||||
}} |
||||
scrolling="no" |
||||
frameBorder="0" |
||||
allow="fullscreen" |
||||
></iframe> |
||||
), [activeTabIdx]) |
||||
|
||||
const Comment = ({name, division, message}) => ( |
||||
<div style={{backgroundColor: '#EEEEEE', border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', padding: 5, marginBottom: 5, marginRight: 2, marginLeft: 2}}> |
||||
<div style={{fontWeight: 'bold'}}>{name}</div> |
||||
<div>{division}</div> |
||||
<div style={{color: '#E80053', textAlign: 'right', fontWeight: 500, fontSize: 12}}>{message}</div> |
||||
</div> |
||||
) |
||||
|
||||
return ( |
||||
<div style={{ marginLeft: -25, marginRight: -25 }}> |
||||
<Row> |
||||
<Col span={18}> |
||||
<Row> |
||||
<Col span={12}> |
||||
{/* <div style={styles.cardContainer}> |
||||
<div style={styles.cardHeaderContainer}> |
||||
<div style={{ flex: 20, display: 'flex', flexDirection: 'column' }}> |
||||
<div style={styles.cardTitle}>Project</div> |
||||
<div style={styles.cardSubtitle}>Project Tower ABC</div> |
||||
</div> |
||||
<div style={{ flex: 6, display: 'flex', justifyContent: 'center', alignItems: 'center' }}> |
||||
<i className="fa fa-check-square" style={{fontSize: 28}}></i> |
||||
</div> |
||||
</div> |
||||
</div> */} |
||||
<div style={{border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', padding: 10, margin: 2}}> |
||||
<div style={{ display: 'flex', flexDirection: 'row', marginBottom: 10 }}> |
||||
<div style={{ flex: 20, display: 'flex', flexDirection: 'column' }}> |
||||
<div style={{fontSize: 16, fontWeight: 'bold', marginBottom: 10}}>Project</div> |
||||
<div style={{fontSize: 14}}>{projectName}</div> |
||||
</div> |
||||
<div> |
||||
<i className="fa fa-check-square" style={{fontSize: 28}}></i> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
</Col> |
||||
<Col span={12}> |
||||
<div style={{border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', padding: 10, margin: 2}}> |
||||
<div style={{ display: 'flex', flexDirection: 'row', marginBottom: 10 }}> |
||||
<div style={{ flex: 20, display: 'flex', flexDirection: 'column' }}> |
||||
<div style={{fontSize: 16, fontWeight: 'bold', marginBottom: 10}}>Customer</div> |
||||
<div style={{fontSize: 14}}>{customerName}</div> |
||||
</div> |
||||
<div> |
||||
<i className="fa fa-home" style={{fontSize: 28}}></i> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={24}> |
||||
<div style={{border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', padding: 10, margin: 2}}> |
||||
<div style={{ display: 'flex', flexDirection: 'column', marginBottom: 10 }}> |
||||
<div> |
||||
<div style={{fontSize: 16, fontWeight: 'bold', marginBottom: 10}}>Schedule</div> |
||||
</div> |
||||
<div> |
||||
<Row> |
||||
<Col span={4} style={{fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Planned Start</Col> |
||||
<Col span={4}>{plannedStart ? moment(plannedStart).format('D MMMM YYYY') : '-'}</Col> |
||||
<Col span={4} style={{fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Planned Finish</Col> |
||||
<Col span={4}>{plannedFinish ? moment(plannedFinish).format('D MMMM YYYY') : '-'}</Col> |
||||
<Col span={4} style={{fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Actual Finish</Col> |
||||
<Col span={4}>{actualFinish ? moment(actualFinish).format('D MMMM YYYY') : '-'}</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={4} style={{fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Actual Start</Col> |
||||
<Col span={4}>{actualStart ? moment(actualStart).format('D MMMM YYYY') : '-'}</Col> |
||||
<Col span={4} style={{fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Estimated Finish</Col> |
||||
<Col span={4}>{estimatedFinish ? moment(estimatedFinish).format('D MMMM YYYY') : '-'}</Col> |
||||
</Row> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
<div style={{margin: 2, border: 'solid', borderWidth: 1, borderColor: '#DDDDDD'}}> |
||||
<Row> |
||||
<Col span={12}> |
||||
<div style={{backgroundColor: activeTabIdx === 0 ? '#FFFFFF' : '#D9D9D9', padding: 8, fontWeight: 'bold', cursor: 'pointer', color: activeTabIdx === 0 ? '#000000' : '#4E4C4C'}} onClick={() => setActiveTabIdx(0)}>S Curve</div> |
||||
</Col> |
||||
<Col span={12}> |
||||
<div style={{backgroundColor: activeTabIdx === 1 ? '#FFFFFF' : '#D9D9D9', padding: 8, fontWeight: 'bold', cursor: 'pointer', color: activeTabIdx === 1 ? '#000000' : '#4E4C4C'}} onClick={() => setActiveTabIdx(1)}>Maps</div> |
||||
</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={24}> |
||||
<div style={{maxHeight: '57vh'}}> |
||||
{ activeTabIdx === 0 && <div style={{height: '56vh', width: '100%'}}>{RenderGantt}</div> } |
||||
{ activeTabIdx === 1 && <div id="map-area" style={{height: '56vh'}} ref={mapRef}></div> } |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</Col> |
||||
<Col span={6}> |
||||
<div style={{margin: 2}}> |
||||
<Row> |
||||
<Col span={24}> |
||||
<div style={{backgroundColor: '#222222', padding: 10, marginBottom: 5}}> |
||||
<div style={{color: '#FFFFFF', textAlign: 'center', marginBottom: 10, fontWeight: 'bold'}}>Progress</div> |
||||
<div style={{backgroundColor: '#DDDDDD', color: '#FFFFFF', borderRadius: 10, marginBottom: 10}}> |
||||
<div style={{backgroundColor: '#7209B7', width: `${planningProgress}%`, padding: 5, borderTopLeftRadius: 10, borderBottomLeftRadius: 10, borderTopRightRadius: planningProgress < 100 ? 0 : 10, borderBottomRightRadius: planningProgress < 100 ? 0 : 10, textAlign: 'center', fontWeight: 500}}>Planning : {planningProgress}%</div> |
||||
</div> |
||||
<div style={{backgroundColor: '#DDDDDD', color: '#FFFFFF', borderRadius: 10, marginBottom: 10}}> |
||||
<div style={{backgroundColor: '#0059C9', width: `${actualProgress}%`, padding: 5, borderTopLeftRadius: 10, borderBottomLeftRadius: 10, borderTopRightRadius: actualProgress < 100 ? 0 : 10, borderBottomRightRadius: actualProgress < 100 ? 0 : 10, textAlign: 'center', fontWeight: 500}}>{actualProgress && actualProgress < 50 ? `${actualProgress}%` : `Actual : ${actualProgress}%` }</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={24}> |
||||
<div style={{backgroundColor: '#FFFFFF', padding: 10, border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', marginBottom: 5}}> |
||||
<div style={{color: '#000000', textAlign: 'center', marginBottom: 10, fontWeight: 'bold'}}>Health By Schedule</div> |
||||
<div style={{backgroundColor: '#E80053', color: '#FFFFFF', padding: 5, borderRadius: 10, marginBottom: 10}}> |
||||
<div style={{textAlign: 'center', fontWeight: 500}}>Behind Schedule</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={24}> |
||||
<div style={{border: 'solid', borderWidth: 1, borderColor: '#DDDDDD'}}> |
||||
{/* <div style={{display: 'flex', alignItems: 'center'}}> |
||||
<div style={{flex: 1, margin: 'auto', cursor: 'pointer', textAlign: 'center', backgroundColor: activeTabCommentIdx === 0 ? '#FFFFFF' : '#D9D9D9', color: activeTabCommentIdx === 0 ? '#000000' : '#FFFFFF', fontWeight: 500, padding: 2}} onClick={() => setActiveTabCommentIdx(0)}>Behind Task</div> |
||||
<div style={{flex: 1, margin: 'auto', cursor: 'pointer', textAlign: 'center', backgroundColor: activeTabCommentIdx === 1 ? '#FFFFFF' : '#D9D9D9', color: activeTabCommentIdx === 1 ? '#000000' : '#FFFFFF', fontWeight: 500, padding: 2, fontSize: 12}} onClick={() => setActiveTabCommentIdx(1)}>Comment From Customer</div> |
||||
</div> */} |
||||
<Row style={{alignItems: 'center', marginBottom: 5}}> |
||||
<Col span={12}> |
||||
<div style={{backgroundColor: activeTabCommentIdx === 0 ? '#FFFFFF' : '#D9D9D9', fontWeight: 500, textAlign: 'center', fontSize: 12, padding: 2, cursor: 'pointer', color: activeTabCommentIdx === 0 ? '#000000' : '#4E4C4C'}} onClick={() => setActiveTabCommentIdx(0)}>Behind Task</div> |
||||
</Col> |
||||
<Col span={12}> |
||||
<div style={{backgroundColor: activeTabCommentIdx === 1 ? '#FFFFFF' : '#D9D9D9', fontWeight: 500, textAlign: 'center', fontSize: 12, padding: 2, cursor: 'pointer', color: activeTabCommentIdx === 1 ? '#000000' : '#4E4C4C'}} onClick={() => setActiveTabCommentIdx(1)}>Comment From Customer</div> |
||||
</Col> |
||||
</Row> |
||||
<div className='custom-scroll' style={{maxHeight: '52vh', overflow: 'auto'}}> |
||||
<Comment name="Dani" division="Interior Office" message="Overdue by 3 days"/> |
||||
<Comment name="Roland" division="Interior Office" message="Overdue by 3 days"/> |
||||
<Comment name="John" division="Interior Office" message="Overdue by 3 days"/> |
||||
<Comment name="Logan" division="Interior Office" message="Overdue by 3 days"/> |
||||
<Comment name="Doe" division="Interior Office" message="Overdue by 3 days"/> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default DashboardCustomer; |
@ -0,0 +1,323 @@
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'; |
||||
import axios from 'axios' |
||||
import { Row, Col } from 'antd'; |
||||
import { CardDashboard, CardExpenditure, CardScheduleHealthPerDivision } from '../../components/CardDashboard/CardDashboard'; |
||||
import L from 'leaflet'; |
||||
import { useParams } from 'react-router-dom'; |
||||
import '../../assets/css/customscroll.css' |
||||
import moment from 'moment'; |
||||
import { renderFormatRupiah } from '../../const/CustomFunc'; |
||||
|
||||
const styles = { |
||||
cardContainer: { backgroundColor: '#F8F8F8', margin: 2, paddingLeft: 20, paddingRight: 20, paddingTop: 10 }, |
||||
cardHeaderContainer: { display: 'flex', flexDirection: 'row', marginBottom: 10 }, |
||||
cardChartContainer: { position: 'relative', height: '21vh', margin: 'auto', paddingBottom: 10, justifyContent: 'center' }, |
||||
cardTitle: { color: '#444444', fontSize: 16, fontWeight: 'bold' }, |
||||
cardSubtitle: { color: '#888888', fontSize: 12 } |
||||
} |
||||
|
||||
const center = { |
||||
lat: -6.200000, |
||||
lng: 106.816666 |
||||
} |
||||
|
||||
const DashboardProject = () => { |
||||
const token = localStorage.getItem("token") |
||||
const HEADER = { |
||||
headers: { |
||||
"Content-Type": "application/json", |
||||
"Authorization": `Bearer ${token}` |
||||
} |
||||
} |
||||
const { PROJECT_ID, GANTT_ID } = useParams(); |
||||
const URL_GANTT = `http://103.73.125.81:8446/index.html?base_url=http://103.73.125.81:8444/api&gantt_id=${GANTT_ID}&proyek_id=${PROJECT_ID}&token=${token}&ro=1`; |
||||
const mapRef = useRef() |
||||
const [projectName, setProjectName] = useState("Project Tower ABC"); |
||||
const [projectManagerName, setProjectManagerName] = useState("John Doe"); |
||||
const [customerName, setCustomerName] = useState("Jaya Gedung Group"); |
||||
const [plannedStart, setPlannedStart] = useState("2019-03-04") |
||||
const [plannedFinish, setPlannedFinish] = useState("2020-05-28") |
||||
const [actualStart, setActualStart] = useState("2019-03-04") |
||||
const [actualFinish, setActualFinish] = useState("2020-05-28") |
||||
const [estimatedFinish, setEstimatedFinish] = useState("2020-05-28") |
||||
const [mymap, setMymap] = useState(null); |
||||
const [activeTabIdx, setActiveTabIdx] = useState(0); |
||||
const [activeTabCommentIdx, setActiveTabCommentIdx] = useState(0); |
||||
const [planningProgress, setPlanningProgress] = useState(79); |
||||
const [actualProgress, setActualProgress] = useState(43); |
||||
const [currentBudget, setCurrentBudget] = useState("168011727772"); |
||||
const [addCostToComplete, setAddCostToComplete] = useState("0"); |
||||
const [actualToDate, setactualToDate] = useState("43256751714");
|
||||
const [estAtCompletion, setEstAtCompletion] = useState("168011727772"); |
||||
const [bcwp, setBcwp] = useState("26658794618"); |
||||
const [costDeviation, setCostDeviation] = useState("0"); |
||||
const [remToComplete, setRemToComplete] = useState("124754976058"); |
||||
const [totalInvoice, setTotalInvoice] = useState("10000000000"); |
||||
const [cashIn, setCashIn] = useState("8000000000"); |
||||
const [outstandingBalance, setOutstandingBalance] = useState("2000000000"); |
||||
|
||||
|
||||
|
||||
useEffect(() => { |
||||
console.log('URL_GANTT', URL_GANTT); |
||||
return () => { |
||||
console.log('unmount RenderMap'); |
||||
} |
||||
}, []) |
||||
|
||||
useEffect(() => { |
||||
if (activeTabIdx === 1) { |
||||
initMap(); |
||||
} |
||||
}, [activeTabIdx]); |
||||
|
||||
const initMap = () => { |
||||
let mymap = L.map('map-area', { |
||||
center: center, |
||||
zoom: 13 |
||||
}) |
||||
|
||||
setMymap(mymap); |
||||
|
||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'}).addTo(mymap); |
||||
} |
||||
|
||||
const RenderGantt = useMemo(() => ( |
||||
<iframe |
||||
id="frame-gantt" |
||||
src={URL_GANTT} |
||||
style={{ |
||||
width: '100%', |
||||
height: '100%', |
||||
}} |
||||
scrolling="no" |
||||
frameBorder="0" |
||||
allow="fullscreen" |
||||
></iframe> |
||||
), [activeTabIdx]) |
||||
|
||||
const Comment = ({name, division, message}) => ( |
||||
<div style={{backgroundColor: '#EEEEEE', border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', padding: 5, marginBottom: 5, marginRight: 2, marginLeft: 2}}> |
||||
<div style={{fontWeight: 'bold'}}>{name}</div> |
||||
<div>{division}</div> |
||||
<div style={{color: '#E80053', textAlign: 'right', fontWeight: 500, fontSize: 12}}>{message}</div> |
||||
</div> |
||||
) |
||||
|
||||
return ( |
||||
<div style={{ marginLeft: -25, marginRight: -25 }}> |
||||
<Row> |
||||
<Col span={18}> |
||||
<Row> |
||||
<Col span={8}> |
||||
<div style={{border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', padding: 10, margin: 2}}> |
||||
<div style={{ display: 'flex', flexDirection: 'row', marginBottom: 10 }}> |
||||
<div style={{ flex: 20, display: 'flex', flexDirection: 'column' }}> |
||||
<div style={{fontSize: 16, fontWeight: 'bold', marginBottom: 10}}>Project</div> |
||||
<div style={{fontSize: 14}}>{projectName}</div> |
||||
</div> |
||||
<div> |
||||
<i className="fa fa-check-square" style={{fontSize: 28}}></i> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
<Col span={8}> |
||||
<div style={{border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', padding: 10, margin: 2}}> |
||||
<div style={{ display: 'flex', flexDirection: 'row', marginBottom: 10 }}> |
||||
<div style={{ flex: 20, display: 'flex', flexDirection: 'column' }}> |
||||
<div style={{fontSize: 16, fontWeight: 'bold', marginBottom: 10}}>Project Manager</div> |
||||
<div style={{fontSize: 14}}>{projectManagerName}</div> |
||||
</div> |
||||
<div> |
||||
<i className="fa fa-user" style={{fontSize: 28}}></i> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
<Col span={8}> |
||||
<div style={{border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', padding: 10, margin: 2}}> |
||||
<div style={{ display: 'flex', flexDirection: 'row', marginBottom: 10 }}> |
||||
<div style={{ flex: 20, display: 'flex', flexDirection: 'column' }}> |
||||
<div style={{fontSize: 16, fontWeight: 'bold', marginBottom: 10}}>Customer</div> |
||||
<div style={{fontSize: 14}}>{customerName}</div> |
||||
</div> |
||||
<div> |
||||
<i className="fa fa-home" style={{fontSize: 28}}></i> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={8}> |
||||
<div style={{border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', padding: 10, margin: 2}}> |
||||
<div style={{ display: 'flex', flexDirection: 'column', marginBottom: 10 }}> |
||||
<div> |
||||
<div style={{fontSize: 16, fontWeight: 'bold', marginBottom: 10}}>Schedule</div> |
||||
</div> |
||||
<div> |
||||
<Row> |
||||
<Col span={12} style={{fontSize: 11, fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Planned Start</Col> |
||||
<Col span={12} style={{fontSize: 11}}>{plannedStart ? moment(plannedStart).format('D MMMM YYYY') : '-'}</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={12} style={{fontSize: 11, fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Acutal Start</Col> |
||||
<Col span={12} style={{fontSize: 11}}>{plannedStart ? moment(actualStart).format('D MMMM YYYY') : '-'}</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={12} style={{fontSize: 11, fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Planned Finish</Col> |
||||
<Col span={12} style={{fontSize: 11}}>{plannedStart ? moment(plannedFinish).format('D MMMM YYYY') : '-'}</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={12} style={{fontSize: 11, fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Estimated Finish</Col> |
||||
<Col span={12} style={{fontSize: 11}}>{plannedStart ? moment(estimatedFinish).format('D MMMM YYYY') : '-'}</Col> |
||||
</Row> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
<Col span={16}> |
||||
<div style={{border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', padding: 10, margin: 2}}> |
||||
<div style={{ display: 'flex', flexDirection: 'column', marginBottom: 10 }}> |
||||
<div> |
||||
<div style={{fontSize: 16, fontWeight: 'bold', marginBottom: 10}}>Financials</div> |
||||
</div> |
||||
<div> |
||||
<Row> |
||||
<Col span={7} style={{fontSize: 11, fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Current Budget</Col> |
||||
<Col span={5} style={{fontSize: 11}}>{currentBudget ? renderFormatRupiah(currentBudget, 'Rp.') : '-' }</Col> |
||||
<Col span={7} style={{fontSize: 11, fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Add Cost to Complete</Col> |
||||
<Col span={5} style={{fontSize: 11}}>{addCostToComplete ? renderFormatRupiah(addCostToComplete, 'Rp.') : '-' }</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={7} style={{fontSize: 11, fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Actual to Date</Col> |
||||
<Col span={5} style={{fontSize: 11}}>{actualToDate ? renderFormatRupiah(actualToDate, 'Rp.') : '-' }</Col> |
||||
<Col span={7} style={{fontSize: 11, fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Est. at Completion</Col> |
||||
<Col span={5} style={{fontSize: 11}}>{estAtCompletion ? renderFormatRupiah(estAtCompletion, 'Rp.') : '-' }</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={7} style={{fontSize: 11, fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>BCWP (cost vs perform)</Col> |
||||
<Col span={5} style={{fontSize: 11}}>{bcwp ? renderFormatRupiah(bcwp, 'Rp.') : '-' }</Col> |
||||
<Col span={7} style={{fontSize: 11, fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Cost Deviation</Col> |
||||
<Col span={5} style={{fontSize: 11}}>{costDeviation ? renderFormatRupiah(costDeviation, 'Rp.') : '-' }</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={7} style={{fontSize: 11, fontWeight: 'bold'}}><i className="fa fa-calendar" style={{marginRight:8}}></i>Rem. to Complete</Col> |
||||
<Col span={5} style={{fontSize: 11}}>{remToComplete ? renderFormatRupiah(remToComplete, 'Rp.') : '-' }</Col> |
||||
</Row> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
<div style={{margin: 2, border: 'solid', borderWidth: 1, borderColor: '#DDDDDD'}}> |
||||
<Row> |
||||
<Col span={12}> |
||||
<div style={{backgroundColor: activeTabIdx === 0 ? '#FFFFFF' : '#D9D9D9', padding: 8, fontWeight: 'bold', cursor: 'pointer', color: activeTabIdx === 0 ? '#000000' : '#4E4C4C'}} onClick={() => setActiveTabIdx(0)}>S Curve</div> |
||||
</Col> |
||||
<Col span={12}> |
||||
<div style={{backgroundColor: activeTabIdx === 1 ? '#FFFFFF' : '#D9D9D9', padding: 8, fontWeight: 'bold', cursor: 'pointer', color: activeTabIdx === 1 ? '#000000' : '#4E4C4C'}} onClick={() => setActiveTabIdx(1)}>Maps</div> |
||||
</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={24}> |
||||
<div style={{maxHeight: '55vh'}}> |
||||
{ activeTabIdx === 0 && <div style={{height: '52vh', width: '100%'}}>{RenderGantt}</div> } |
||||
{ activeTabIdx === 1 && <div id="map-area" style={{height: '52vh'}} ref={mapRef}></div> } |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</Col> |
||||
<Col span={6}> |
||||
<div style={{margin: 2}}> |
||||
<Row> |
||||
<Col span={24}> |
||||
<div style={{backgroundColor: '#222222', padding: 10, marginBottom: 5}}> |
||||
<div style={{color: '#FFFFFF', textAlign: 'center', marginBottom: 10, fontWeight: 'bold'}}>Progress</div> |
||||
<div style={{backgroundColor: '#DDDDDD', color: '#FFFFFF', borderRadius: 10, marginBottom: 10}}> |
||||
<div style={{backgroundColor: '#7209B7', width: `${planningProgress}%`, padding: 5, borderTopLeftRadius: 10, borderBottomLeftRadius: 10, borderTopRightRadius: planningProgress < 100 ? 0 : 10, borderBottomRightRadius: planningProgress < 100 ? 0 : 10, textAlign: 'center', fontWeight: 500}}>Planning : {planningProgress}%</div> |
||||
</div> |
||||
<div style={{backgroundColor: '#DDDDDD', color: '#FFFFFF', borderRadius: 10, marginBottom: 10}}> |
||||
<div style={{backgroundColor: '#0059C9', width: `${actualProgress}%`, padding: 5, borderTopLeftRadius: 10, borderBottomLeftRadius: 10, borderTopRightRadius: actualProgress < 100 ? 0 : 10, borderBottomRightRadius: actualProgress < 100 ? 0 : 10, textAlign: 'center', fontWeight: 500}}>Actual : {actualProgress}%</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={12}> |
||||
<div style={{backgroundColor: '#FFFFFF', padding: 10, border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', marginBottom: 5, marginRight: 2}}> |
||||
<div style={{color: '#000000', textAlign: 'center', marginBottom: 10, fontWeight: 'bold', fontSize: 12}}>Health By Schedule</div> |
||||
<div style={{backgroundColor: '#52AC0B', color: '#FFFFFF', padding: 5, borderRadius: 10, marginBottom: 10}}> |
||||
<div style={{textAlign: 'center', fontWeight: 500, fontSize: 12}}>On Budget</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
<Col span={12}> |
||||
<div style={{backgroundColor: '#FFFFFF', padding: 10, border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', marginBottom: 5, marginLeft: 2}}> |
||||
<div style={{color: '#000000', textAlign: 'center', marginBottom: 10, fontWeight: 'bold', fontSize: 12}}>Health By Schedule</div> |
||||
<div style={{backgroundColor: '#E80053', color: '#FFFFFF', padding: 5, borderRadius: 10, marginBottom: 10}}> |
||||
<div style={{textAlign: 'center', fontWeight: 500, fontSize: 12}}>Behind Schedule</div> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={24}> |
||||
<div style={{backgroundColor: '#FFFFFF', padding: 10, border: 'solid', borderWidth: 1, borderColor: '#DDDDDD', marginBottom: 5, marginRight: 2}}> |
||||
{/* <div style={{color: '#000000', textAlign: 'center', marginBottom: 10, fontWeight: 'bold', fontSize: 12}}>Health By Schedule</div> |
||||
<div style={{backgroundColor: '#52AC0B', color: '#FFFFFF', padding: 5, borderRadius: 10, marginBottom: 10}}> |
||||
<div style={{textAlign: 'center', fontWeight: 500, fontSize: 12}}>On Budget</div> |
||||
</div> */} |
||||
<Row> |
||||
<Col span={12}>Total Invoice</Col> |
||||
<Col span={12} style={{textAlign: 'right'}}>{totalInvoice ? renderFormatRupiah(totalInvoice, 'Rp.') : '-' }</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={12}>Cash In</Col> |
||||
<Col span={12} style={{textAlign: 'right'}}>{cashIn ? renderFormatRupiah(cashIn, 'Rp.') : '-' }</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={24}><hr style={{margin: 2}}/></Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={12}>Outstanding Balance</Col> |
||||
<Col span={12} style={{textAlign: 'right', color: '#E80053', fontWeight: 500}}>{outstandingBalance ? renderFormatRupiah(outstandingBalance, 'Rp.') : '-' }</Col> |
||||
</Row> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
<Row> |
||||
<Col span={24}> |
||||
<div style={{border: 'solid', borderWidth: 1, borderColor: '#DDDDDD'}}> |
||||
{/* <div style={{display: 'flex', alignItems: 'center'}}> |
||||
<div style={{flex: 1, margin: 'auto', cursor: 'pointer', textAlign: 'center', backgroundColor: activeTabCommentIdx === 0 ? '#FFFFFF' : '#D9D9D9', color: activeTabCommentIdx === 0 ? '#000000' : '#FFFFFF', fontWeight: 500, padding: 2}} onClick={() => setActiveTabCommentIdx(0)}>Behind Task</div> |
||||
<div style={{flex: 1, margin: 'auto', cursor: 'pointer', textAlign: 'center', backgroundColor: activeTabCommentIdx === 1 ? '#FFFFFF' : '#D9D9D9', color: activeTabCommentIdx === 1 ? '#000000' : '#FFFFFF', fontWeight: 500, padding: 2, fontSize: 12}} onClick={() => setActiveTabCommentIdx(1)}>Comment From Customer</div> |
||||
</div> */} |
||||
<Row style={{alignItems: 'center', marginBottom: 5}}> |
||||
<Col span={12}> |
||||
<div style={{backgroundColor: activeTabCommentIdx === 0 ? '#FFFFFF' : '#D9D9D9', fontWeight: 500, textAlign: 'center', fontSize: 12, padding: 2, cursor: 'pointer', color: activeTabCommentIdx === 0 ? '#000000' : '#4E4C4C'}} onClick={() => setActiveTabCommentIdx(0)}>Behind Task</div> |
||||
</Col> |
||||
<Col span={12}> |
||||
<div style={{backgroundColor: activeTabCommentIdx === 1 ? '#FFFFFF' : '#D9D9D9', fontWeight: 500, textAlign: 'center', fontSize: 12, padding: 2, cursor: 'pointer', color: activeTabCommentIdx === 1 ? '#000000' : '#4E4C4C'}} onClick={() => setActiveTabCommentIdx(1)}>Comment From Customer</div> |
||||
</Col> |
||||
</Row> |
||||
<div className='custom-scroll' style={{maxHeight: '37vh', overflow: 'auto'}}> |
||||
<Comment name="Dani" division="Interior Office" message="Overdue by 3 days"/> |
||||
<Comment name="Roland" division="Interior Office" message="Overdue by 3 days"/> |
||||
<Comment name="John" division="Interior Office" message="Overdue by 3 days"/> |
||||
<Comment name="Logan" division="Interior Office" message="Overdue by 3 days"/> |
||||
<Comment name="Doe" division="Interior Office" message="Overdue by 3 days"/> |
||||
</div> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export default DashboardProject; |
Loading…
Reference in new issue