Muhammad Sulaiman Yusuf
3 years ago
5 changed files with 35 additions and 641 deletions
@ -1,531 +0,0 @@
|
||||
import { DatePicker } from 'antd'; |
||||
import Chart from 'chart.js'; |
||||
import ChartDataLabels from 'chartjs-plugin-datalabels'; |
||||
import moment from 'moment'; |
||||
import React, { useEffect, useState } from 'react'; |
||||
import { |
||||
Card, Modal, ModalHeader, ModalBody, ModalFooter, Button, |
||||
CardBody, CardHeader, Col, Dropdown, DropdownItem, DropdownMenu, DropdownToggle, Row |
||||
} from 'reactstrap'; |
||||
import { Pagination, Tooltip, Tree, List, Checkbox } from 'antd'; |
||||
import '../../../node_modules/react-grid-layout/css/styles.css'; |
||||
import '../../../node_modules/react-resizable/css/styles.css'; |
||||
import { |
||||
DONE_COLOR, IZIN_COLOR, NOT_YET_COLOR, |
||||
PRESENT_COLOR, TOTAL_COLOR, |
||||
RED_COLOR, |
||||
ORANGE_COLOR, |
||||
GREEN_COLOR, |
||||
DARK_GREY_COLOR, |
||||
BLUE_COLOR, |
||||
PURPLE_COLOR |
||||
} from '../../const/AppConst.js'; |
||||
import '../Map/CustomScroll.css'; |
||||
import './Dashboard.css'; |
||||
import { BASE_SIMPRO } from '../../const/ApiConst'; |
||||
import { NotificationContainer, NotificationManager } from 'react-notifications'; |
||||
import axios from 'axios' |
||||
import numeral from 'numeral'; |
||||
import ContentLoader from "react-content-loader" |
||||
import LineChart from './LineChart'; |
||||
import PieChart from './PieChart'; |
||||
import { projectTreeConst } from '../../const/LayerTreeConst.js'; |
||||
import { PLANNING_REALISASI_SEARCH, PLANNING_SEARCH, PROYEK_SEARCH_DETAIL, PROYEK_EDIT } from '../../const/ApiConst.js'; |
||||
import { getChildrenTree, formatRupiah, DATE_TIME_FORMAT } from '../../const/CustomFunc.js'; |
||||
|
||||
const id_org = window.localStorage.getItem('id_org'); |
||||
const roleName = window.localStorage.getItem('role_name'); |
||||
|
||||
Chart.plugins.register(ChartDataLabels); |
||||
const { RangePicker } = DatePicker; |
||||
|
||||
let menu = [ |
||||
// {
|
||||
// "id": 1,
|
||||
// "title": "PLANNING",
|
||||
// "key": "total karyawan",
|
||||
// // "total": this.state.sumEmployee,
|
||||
// "color": TOTAL_COLOR
|
||||
// },
|
||||
// {
|
||||
// "id": 2,
|
||||
// "title": "REALISASI",
|
||||
// "key": "presensi",
|
||||
// // "total": this.state.sumPresensi,
|
||||
// "color": PRESENT_COLOR
|
||||
// },
|
||||
{ |
||||
"id": 3, |
||||
"title": "PANIC BUTTON", |
||||
"key": "absent", |
||||
// "total": this.state.sumAbsensi,
|
||||
"color": IZIN_COLOR |
||||
}, |
||||
{ |
||||
"id": 4, |
||||
"title": "WASPANG ACTIVE", |
||||
"key": "karyawan telat", |
||||
// "total": this.state.sumTelat,
|
||||
"color": GREEN_COLOR |
||||
}, |
||||
{ |
||||
"id": 5, |
||||
"title": "WASPANG ABSENT", |
||||
"key": "karyawan tanpa keterangan", |
||||
// "total": this.state.sumTanpaKet,
|
||||
"color": ORANGE_COLOR |
||||
} |
||||
// {
|
||||
// "id": 6,
|
||||
// "title": "PANIK BUTTON",
|
||||
// "key": "panic button",
|
||||
// "total": this.state.sumPanicBtn,
|
||||
// "color": ABSENT_COLOR
|
||||
// }
|
||||
] |
||||
|
||||
const defaultPersentaseProyek = { |
||||
labels: [], |
||||
datasets: [ |
||||
{ |
||||
label: 'Progress', |
||||
data: [], |
||||
fill: false, |
||||
backgroundColor: 'rgb(54, 162, 235)', |
||||
borderColor: 'rgba(54, 162, 235, 0.2)', |
||||
yAxisID: 'y-axis-1', |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
const defaultCostProyek = { |
||||
labels: [], |
||||
datasets: [ |
||||
{ |
||||
label: 'Perencanaan', |
||||
data: [], |
||||
fill: false, |
||||
backgroundColor: 'rgb(255, 99, 132)', |
||||
borderColor: 'rgba(255, 99, 132, 0.2)', |
||||
yAxisID: 'y-axis-1', |
||||
}, |
||||
{ |
||||
label: 'Realisasi', |
||||
data: [], |
||||
fill: false, |
||||
backgroundColor: 'rgb(54, 162, 235)', |
||||
borderColor: 'rgba(54, 162, 235, 0.2)', |
||||
yAxisID: 'y-axis-1', |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
const defaultStatusProyek = { |
||||
labels: ['Aman', 'Alert', 'Critical'], |
||||
datasets: [ |
||||
{ |
||||
label: '# of Votes', |
||||
data: [], |
||||
backgroundColor: [ |
||||
'rgba(54, 162, 235, 0.2)', |
||||
'rgba(255, 206, 86, 0.2)', |
||||
'rgba(255, 99, 132, 0.2)', |
||||
], |
||||
borderColor: [ |
||||
'rgba(54, 162, 235, 1)', |
||||
'rgba(255, 206, 86, 1)', |
||||
'rgba(255, 99, 132, 1)', |
||||
], |
||||
borderWidth: 1, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
const DashboardSimpro = () => { |
||||
const token = localStorage.getItem("token") |
||||
const HEADER = { |
||||
headers: { |
||||
"Content-Type": "application/json", |
||||
"Authorization": `Bearer ${token}` |
||||
} |
||||
} |
||||
const [openPlanRealisasi, setopenPlanRealisasi] = useState(false); |
||||
const [openCostPlanRealisasi, setopenCostPlanRealisasi] = useState(false); |
||||
const [dataChart, setDataChart] = useState([]); |
||||
const [projectTree, setProjectTree] = useState([]); |
||||
const [allProyek, setAllProyek] = useState(true); |
||||
const [dataStatusProyek, setDataStatusProyek] = useState(null); |
||||
const [dataPersentaseProyek, setDataPersentaseProyek] = useState(null); |
||||
const [dataCostProyek, setdataCostProyek] = useState(null); |
||||
const [projectTreeVisible, setProjectTreeVisible] = useState(false); |
||||
const [checkedKeysProjectTree, setCheckedKeysProjectTree] = useState([]); |
||||
const [openModalTable, setOpenModalTable] = useState(false); |
||||
const [dataDashboard, setDataDashboard] = useState(null); |
||||
|
||||
const handleGetDataDashboard = async () => { |
||||
const URL = `${BASE_SIMPRO}/dashboard-proyek/search` |
||||
const payload = { |
||||
"columns": [ |
||||
{ "name": "created_at", "logic_operator": "range", "value": "2021-11-06 00:00:00", "value1": "2021-11-06 23:59:59", "operator": "AND" } |
||||
], |
||||
"paging": { "start": 0, "length": -1 } |
||||
} |
||||
// console.log(payload)
|
||||
const result = await axios.post(URL, payload, HEADER).then(res => res).catch(err => err.response) |
||||
if (result.data.code === 200) { |
||||
setDataDashboard(result.data.data); |
||||
} else { |
||||
NotificationManager.error('Gaga Menambah Data!!', 'Failed'); |
||||
} |
||||
|
||||
} |
||||
|
||||
const handleGetDataDashboardChart = async () => { |
||||
const URL = `${BASE_SIMPRO}/dashboard-status/search` |
||||
let str = '' |
||||
checkedKeysProjectTree.map((res, idx) => { |
||||
if (idx == 0) str += `${res}` |
||||
if (idx != 0) str += `,${res}` |
||||
}) |
||||
console.log(str) |
||||
const payload = { |
||||
"columns": [ |
||||
{ "name": "id", "logic_operator": "in", "value": str ? str : "0", "operator": "AND" } |
||||
], |
||||
"orders": { "columns": ["nama"], "ascending": true } |
||||
} |
||||
// console.log(payload)
|
||||
const result = await axios.post(URL, payload, HEADER).then(res => res).catch(err => err.response) |
||||
if (result.data.code === 200) { |
||||
|
||||
const { persentase_progress, progress_cost_planning, progress_cost_realisasi, status_proyek } = result.data.data |
||||
|
||||
const labelPersentaseProyek = persentase_progress ? persentase_progress.map(res => res.label) : [] |
||||
const valuePersentaseProyek = persentase_progress ? persentase_progress.map(res => res.total) : [] |
||||
const persentaseProyek = { |
||||
labels: labelPersentaseProyek, |
||||
datasets: [ |
||||
{ |
||||
label: 'Progress', |
||||
data: valuePersentaseProyek, |
||||
fill: false, |
||||
backgroundColor: 'rgb(54, 162, 235)', |
||||
borderColor: 'rgba(54, 162, 235, 0.2)', |
||||
yAxisID: 'y-axis-1', |
||||
}, |
||||
], |
||||
}; |
||||
setDataPersentaseProyek(persentaseProyek) |
||||
const labelCostPlaning = progress_cost_planning ? progress_cost_planning.map(res => res.label) : [] |
||||
const valueCostPlaning = progress_cost_planning ? progress_cost_planning.map(res => res.total) : [] |
||||
const valueCostRealisasi = progress_cost_realisasi ? progress_cost_realisasi.map(res => res.total) : [] |
||||
|
||||
const costProyek = { |
||||
labels: labelCostPlaning, |
||||
datasets: [ |
||||
{ |
||||
label: 'Perencanaan', |
||||
data: valueCostPlaning, |
||||
fill: false, |
||||
backgroundColor: 'rgb(255, 99, 132)', |
||||
borderColor: 'rgba(255, 99, 132, 0.2)', |
||||
yAxisID: 'y-axis-1', |
||||
}, |
||||
{ |
||||
label: 'Realisasi', |
||||
data: valueCostRealisasi, |
||||
fill: false, |
||||
backgroundColor: 'rgb(54, 162, 235)', |
||||
borderColor: 'rgba(54, 162, 235, 0.2)', |
||||
yAxisID: 'y-axis-1', |
||||
}, |
||||
], |
||||
}; |
||||
setdataCostProyek(costProyek) |
||||
|
||||
const valueStatusProyek = status_proyek ? status_proyek.map(res => res.total) : [] |
||||
|
||||
const statusProyek = { |
||||
labels: ['Aman', 'Alert', 'Critical'], |
||||
datasets: [ |
||||
{ |
||||
label: '# of Votes', |
||||
data: valueStatusProyek, |
||||
backgroundColor: [ |
||||
'rgba(54, 162, 235, 0.2)', |
||||
'rgba(255, 206, 86, 0.2)', |
||||
'rgba(255, 99, 132, 0.2)', |
||||
], |
||||
borderColor: [ |
||||
'rgba(54, 162, 235, 1)', |
||||
'rgba(255, 206, 86, 1)', |
||||
'rgba(255, 99, 132, 1)', |
||||
], |
||||
borderWidth: 1, |
||||
}, |
||||
], |
||||
}; |
||||
|
||||
setDataStatusProyek(statusProyek) |
||||
|
||||
} else { |
||||
NotificationManager.error('Gaga Menambah Data!!', 'Failed'); |
||||
} |
||||
|
||||
} |
||||
|
||||
const getProyek = async () => { |
||||
const URL = `${BASE_SIMPRO}/proyek/list?start=0&length=-1&orderby=nama&asc=true` |
||||
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response) |
||||
if (result.data.code === 200) { |
||||
setProjectTree(result.data.data); |
||||
const arr = result.data.data.map(res => res.id) |
||||
// console.log("checked all", data)
|
||||
setCheckedKeysProjectTree(arr) |
||||
} else { |
||||
NotificationManager.error('Gaga Menambah Data!!', 'Failed'); |
||||
} |
||||
} |
||||
useEffect(() => { |
||||
handleGetDataDashboardChart() |
||||
// console.log(checkedKeysProjectTree)
|
||||
}, [checkedKeysProjectTree]); |
||||
|
||||
useEffect(() => { |
||||
if (allProyek) { |
||||
const data = projectTree.map(res => res.id) |
||||
console.log("checked all", data) |
||||
setCheckedKeysProjectTree(data) |
||||
} |
||||
}, [allProyek]); |
||||
|
||||
useEffect(() => { |
||||
handleGetDataDashboard() |
||||
getProyek() |
||||
// return () => {
|
||||
// cleanup
|
||||
// };
|
||||
}, []); |
||||
|
||||
const renderDailyInfo = () => { |
||||
|
||||
return ( |
||||
<> |
||||
{/* <div className="daily-info-card" style={{ backgroundColor: TOTAL_COLOR, cursor: 'pointer' }} > |
||||
<p className="number-style1">{dataDashboard ? dataDashboard.planning : 0}</p> |
||||
<p style={{ color: "#FFFFFF", fontWeight: "bold" }}>PLANNING</p> |
||||
</div> |
||||
<div className="daily-info-card" style={{ backgroundColor: PRESENT_COLOR, cursor: 'pointer' }} > |
||||
<p className="number-style1">{dataDashboard ? dataDashboard.realisasi : 0}</p> |
||||
<p style={{ color: "#FFFFFF", fontWeight: "bold" }}>REALISASI</p> |
||||
</div> */} |
||||
<div className="daily-info-card" style={{ backgroundColor: IZIN_COLOR, cursor: 'pointer' }} > |
||||
<p className="number-style1">{dataDashboard ? dataDashboard.panic_button : 0}</p> |
||||
<p style={{ color: "#FFFFFF", fontWeight: "bold" }}>PANIC BUTTON</p> |
||||
</div> |
||||
<div className="daily-info-card" style={{ backgroundColor: GREEN_COLOR, cursor: 'pointer' }} > |
||||
<p className="number-style1">{dataDashboard ? dataDashboard.waspang_status.presensi : 0}</p> |
||||
<p style={{ color: "#FFFFFF", fontWeight: "bold" }}>WASPANG ACTIVE</p> |
||||
</div> |
||||
<div className="daily-info-card" style={{ backgroundColor: ORANGE_COLOR, cursor: 'pointer' }} > |
||||
<p className="number-style1">{dataDashboard ? dataDashboard.waspang_status.absensi : 0}</p> |
||||
<p style={{ color: "#FFFFFF", fontWeight: "bold" }}>WASPANG ABSENT</p> |
||||
</div> |
||||
</> |
||||
) |
||||
} |
||||
|
||||
const handleClickChart = param => { |
||||
if (!param.length) return; |
||||
console.log(param) |
||||
const { _datasetIndex, _index } = param[0]; |
||||
const data = dataPersentaseProyek.datasets[_datasetIndex].label |
||||
console.log(data) |
||||
setOpenModalTable(true) |
||||
} |
||||
|
||||
const handleClickProyek = id => { |
||||
const arr = [...checkedKeysProjectTree] |
||||
const idx = arr.indexOf(id) |
||||
if (idx == -1) { |
||||
arr.push(id) |
||||
} else { |
||||
arr.splice(idx, 1) |
||||
} |
||||
setCheckedKeysProjectTree(arr) |
||||
} |
||||
|
||||
return ( |
||||
<div> |
||||
<Modal |
||||
fullscreen |
||||
size="xl" |
||||
isOpen={openModalTable} |
||||
toggle={() => setOpenModalTable(!openModalTable)} |
||||
> |
||||
<ModalHeader toggle={() => setOpenModalTable(!openModalTable)}> |
||||
Modal title |
||||
</ModalHeader> |
||||
<ModalBody> |
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. |
||||
</ModalBody> |
||||
<ModalFooter> |
||||
<Button |
||||
color="primary" |
||||
onClick={() => setOpenModalTable(!openModalTable)} |
||||
> |
||||
Do Something |
||||
</Button> |
||||
{' '} |
||||
<Button onClick={() => setOpenModalTable(!openModalTable)}> |
||||
Cancel |
||||
</Button> |
||||
</ModalFooter> |
||||
</Modal> |
||||
<NotificationContainer /> |
||||
<div style={{ marginTop: "10px" }}> |
||||
<Row> |
||||
<Col md={3}> |
||||
<Card> |
||||
<CardHeader> |
||||
<Row> |
||||
<Col md={8}><h5>Proyek</h5></Col> |
||||
{/* <Col md={4}> |
||||
<div style={{ float: 'right' }}> |
||||
<Tooltip title={projectTreeVisible ? 'Hide Proyek Tree' : 'Show Proyek Tree'}> |
||||
<Button size="sm" color="primary" onClick={() => setProjectTree(!projectTreeVisible)}><i className={`fa fa-chevron-${projectTreeVisible ? 'left' : 'right'}`}></i></Button> |
||||
</Tooltip> |
||||
</div> |
||||
</Col> */} |
||||
</Row> |
||||
</CardHeader> |
||||
<CardBody> |
||||
<div className="custom-scroll" style={{ overflow: 'auto', height: 150 }}> |
||||
<Checkbox checked={allProyek} onChange={() => setAllProyek(!allProyek)}>Semua</Checkbox> |
||||
<List |
||||
// header={<div>Header</div>}
|
||||
// footer={<div>Footer</div>}
|
||||
// bordered
|
||||
dataSource={projectTree} |
||||
renderItem={item => ( |
||||
<List.Item> |
||||
<Checkbox checked={checkedKeysProjectTree.indexOf(item.id) !== -1} onChange={() => handleClickProyek(item.id)}>{item.nama}</Checkbox> |
||||
</List.Item> |
||||
)} |
||||
/> |
||||
</div> |
||||
</CardBody> |
||||
</Card> |
||||
</Col> |
||||
|
||||
<Col md={5}> |
||||
{/* <Card style={{ height: "100%" }}> |
||||
<CardHeader> |
||||
<b>Waspang Status</b> |
||||
</CardHeader> |
||||
<CardBody> */} |
||||
<div style={{ paddingTop: 40 }} className="view-rectangle"> |
||||
{renderDailyInfo()} |
||||
</div> |
||||
{/* </CardBody> |
||||
</Card> */} |
||||
</Col> |
||||
<Col md={4}> |
||||
<div style={{ height: 200 }}> |
||||
<PieChart data={dataStatusProyek || defaultStatusProyek} /> |
||||
</div> |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
|
||||
<div style={{ marginTop: "30px", marginBottom: 20 }}> |
||||
<Row> |
||||
<Col md={6}> |
||||
{/* <div style={{ |
||||
padding: 10, |
||||
boxShadow: '1px 1px 11px 1px rgba(221,211,211,0.75)' |
||||
}}> */} |
||||
<LineChart |
||||
optionsAdded={{ |
||||
title: { |
||||
display: true, |
||||
text: 'Persentase Progress Proyek' |
||||
}, |
||||
tooltips: { |
||||
callbacks: { |
||||
label: function (tooltipItem, data) { |
||||
const label = data.datasets[tooltipItem.datasetIndex].label || ''; |
||||
return `${label}: ${tooltipItem.value}%`; |
||||
} |
||||
} |
||||
}, |
||||
scales: { |
||||
yAxes: [ |
||||
{ |
||||
type: 'linear', |
||||
display: true, |
||||
position: 'left', |
||||
id: 'y-axis-1', |
||||
|
||||
ticks: { |
||||
max: 100, |
||||
min: 1, |
||||
callback: function (value, index, values) { |
||||
return `${value}%`; |
||||
} |
||||
}, |
||||
} |
||||
], |
||||
} |
||||
}} |
||||
data={dataPersentaseProyek || defaultPersentaseProyek} |
||||
handleClickChart={handleClickChart} |
||||
/> |
||||
{/* </div> */} |
||||
</Col> |
||||
<Col md={6}> |
||||
{/* <div style={{ |
||||
padding: 10, |
||||
boxShadow: '1px 1px 11px 1px rgba(221,211,211,0.75)' |
||||
}}> */} |
||||
<LineChart |
||||
optionsAdded={ |
||||
{ |
||||
title: { |
||||
display: true, |
||||
text: 'Progress Cost Perencanaan dan Realisasi' |
||||
}, |
||||
tooltips: { |
||||
callbacks: { |
||||
label: function (tooltipItem, data) { |
||||
const label = data.datasets[tooltipItem.datasetIndex].label || ''; |
||||
return `${label}: ${numeral(tooltipItem.value).format('0,0')}`; |
||||
} |
||||
} |
||||
}, |
||||
scales: { |
||||
yAxes: [ |
||||
{ |
||||
type: 'linear', |
||||
display: true, |
||||
position: 'left', |
||||
id: 'y-axis-1', |
||||
ticks: { |
||||
callback: function (value, index, values) { |
||||
return numeral(value).format('0,0'); |
||||
} |
||||
}, |
||||
} |
||||
], |
||||
}, |
||||
}} data={dataCostProyek || defaultCostProyek} /> |
||||
{/* </div> */} |
||||
</Col> |
||||
</Row> |
||||
</div> |
||||
</div> |
||||
|
||||
); |
||||
} |
||||
|
||||
export default DashboardSimpro; |
Loading…
Reference in new issue