Browse Source

WIP: Dashboard all project summary

pull/2/head
Yusuf 2 years ago
parent
commit
27fd6ee8dd
  1. 2
      package.json
  2. 198
      src/routes.js
  3. 128
      src/views/DashboardPMO/Dashboard.css
  4. 41
      src/views/DashboardPMO/PieChart.js
  5. 152
      src/views/DashboardPMO/index.js

2
package.json

@ -12,6 +12,7 @@
"url": "https://git.oslog.id/iu/simpro-website.git" "url": "https://git.oslog.id/iu/simpro-website.git"
}, },
"dependencies": { "dependencies": {
"@ant-design/plots": "^1.1.1",
"@coreui/coreui": "^2.1.12", "@coreui/coreui": "^2.1.12",
"@coreui/icons": "0.3.0", "@coreui/icons": "0.3.0",
"@coreui/react": "^2.5.1", "@coreui/react": "^2.5.1",
@ -25,6 +26,7 @@
"@iconify/icons-uil": "^1.0.6", "@iconify/icons-uil": "^1.0.6",
"@iconify/react": "^1.1.1", "@iconify/react": "^1.1.1",
"@nicholasadamou/react-iframe": "^1.0.3", "@nicholasadamou/react-iframe": "^1.0.3",
"@terrestris/ol-util": "^7.2.0",
"@terrestris/react-geo": "^12.0.0", "@terrestris/react-geo": "^12.0.0",
"alasql": "^1.7.3", "alasql": "^1.7.3",
"antd": "^4.16.13", "antd": "^4.16.13",

198
src/routes.js

@ -1,98 +1,100 @@
import React from 'react'; import React from 'react';
const Absensi = React.lazy(() => import('./views/Master/MasterAbsensi')); const Absensi = React.lazy(() => import('./views/Master/MasterAbsensi'));
const BaseLayers = React.lazy(() => import('./views/BaseLayers')); const BaseLayers = React.lazy(() => import('./views/BaseLayers'));
const Broadcast = React.lazy(() => import('./views/Master/MasterBroadcast')); const Broadcast = React.lazy(() => import('./views/Master/MasterBroadcast'));
const ChecklistK3 = React.lazy(() => import('./views/SimproV2/ChecklistK3')); const ChecklistK3 = React.lazy(() => import('./views/SimproV2/ChecklistK3'));
const Closing = React.lazy(() => import('./views/SimproV2/Closing')); const Closing = React.lazy(() => import('./views/SimproV2/Closing'));
const ConfigAlert = React.lazy(() => import('./views/Master/ConfigAlert')); const ConfigAlert = React.lazy(() => import('./views/Master/ConfigAlert'));
const ControlMonitoring = React.lazy(() => import('./views/Report/ControlMonitoring')); const ControlMonitoring = React.lazy(() => import('./views/Report/ControlMonitoring'));
const ControlMonitoringGantt = React.lazy(() => import('./views/ControlMonitoringGantt')); const ControlMonitoringGantt = React.lazy(() => import('./views/ControlMonitoringGantt'));
const CreatedProyek = React.lazy(() => import('./views/SimproV2/CreatedProyek')); const CreatedProyek = React.lazy(() => import('./views/SimproV2/CreatedProyek'));
const DashboardSimpro = React.lazy(() => import('./views/DashboardSimpro')); const DashboardSimpro = React.lazy(() => import('./views/DashboardSimpro'));
const Divisi = React.lazy(() => import('./views/SimproV2/Divisi')); const DashboardPMO = React.lazy(() => import('./views/DashboardPMO'));
const DivisiKaryawan = React.lazy(() => import('./views/Master/MasterTipeKaryawan')); const Divisi = React.lazy(() => import('./views/SimproV2/Divisi'));
const Gantt = React.lazy(() => import('./views/SimproV2/Gantt')); const DivisiKaryawan = React.lazy(() => import('./views/Master/MasterTipeKaryawan'));
const Izin = React.lazy(() => import('./views/Master/MasterCuti')); const Gantt = React.lazy(() => import('./views/SimproV2/Gantt'));
const K3 = React.lazy(() => import('./views/Report/k3')); const Izin = React.lazy(() => import('./views/Master/MasterCuti'));
const LaporanAlert = React.lazy(() => import('./views/Report/alert')); const K3 = React.lazy(() => import('./views/Report/k3'));
const LaporanTugas = React.lazy(() => import('./views/Master/MasterTask')); const LaporanAlert = React.lazy(() => import('./views/Report/alert'));
const Layer = React.lazy(() => import('./views/Layers/Layer')); const LaporanTugas = React.lazy(() => import('./views/Master/MasterTask'));
const Layers = React.lazy(() => import('./views/Layers/Layers')); const Layer = React.lazy(() => import('./views/Layers/Layer'));
const Lembur = React.lazy(() => import('./views/Master/MasterLembur')); const Layers = React.lazy(() => import('./views/Layers/Layers'));
const MapConfig = React.lazy(() => import('./views/MapConfig')); const Lembur = React.lazy(() => import('./views/Master/MasterLembur'));
const Menu = React.lazy(() => import('./views/Master/MasterMenu')); const MapConfig = React.lazy(() => import('./views/MapConfig'));
const OfficeHours = React.lazy(() => import('./views/Master/MasterOfficeHours')); const Menu = React.lazy(() => import('./views/Master/MasterMenu'));
const Organization = React.lazy(() => import('./views/Master/MasterOrganization')); const OfficeHours = React.lazy(() => import('./views/Master/MasterOfficeHours'));
const PanicButton = React.lazy(() => import('./views/SimproV2/PanicButton')); const Organization = React.lazy(() => import('./views/Master/MasterOrganization'));
const PlanningHarian = React.lazy(() => import('./views/SimproV2/PlanningHarian')); const PanicButton = React.lazy(() => import('./views/SimproV2/PanicButton'));
const Presensi = React.lazy(() => import('./views/SimproV2/Presence')); const PlanningHarian = React.lazy(() => import('./views/SimproV2/PlanningHarian'));
const ProjectRole = React.lazy(() => import('./views/Master/RoleProject')); const Presensi = React.lazy(() => import('./views/SimproV2/Presence'));
const ProjectType = React.lazy(() => import('./views/SimproV2/ProjectType')); const ProjectRole = React.lazy(() => import('./views/Master/RoleProject'));
const Proyek = React.lazy(() => import('./views/Master/Proyek')); const ProjectType = React.lazy(() => import('./views/SimproV2/ProjectType'));
const RateCost = React.lazy(() => import('./views/SimproV2/RateCost')); const Proyek = React.lazy(() => import('./views/Master/Proyek'));
const ResourceMaterial = React.lazy(() => import('./views/SimproV2/ResourceMaterial')); const RateCost = React.lazy(() => import('./views/SimproV2/RateCost'));
const ResourceTools = React.lazy(() => import('./views/SimproV2/ResourceTools')); const ResourceMaterial = React.lazy(() => import('./views/SimproV2/ResourceMaterial'));
const ResourceWorker = React.lazy(() => import('./views/SimproV2/ResourceWorker')); const ResourceTools = React.lazy(() => import('./views/SimproV2/ResourceTools'));
const Roles = React.lazy(() => import('./views/Master/MasterRoles')); const ResourceWorker = React.lazy(() => import('./views/SimproV2/ResourceWorker'));
const Satuan = React.lazy(() => import('./views/SimproV2/Satuan')); const Roles = React.lazy(() => import('./views/Master/MasterRoles'));
const ScheduleShift = React.lazy(() => import('./views/SimproV2/ScheduleShift')); const Satuan = React.lazy(() => import('./views/SimproV2/Satuan'));
const Shift = React.lazy(() => import('./views/SimproV2/Shift')); const ScheduleShift = React.lazy(() => import('./views/SimproV2/ScheduleShift'));
const TestGantt = React.lazy(() => import('./views/testgantt')); const Shift = React.lazy(() => import('./views/SimproV2/Shift'));
const UserAdmin = React.lazy(() => import('./views/Master/UserAdmin')); const TestGantt = React.lazy(() => import('./views/testgantt'));
const UserShift = React.lazy(() => import('./views/SimproV2/UserShift')); const UserAdmin = React.lazy(() => import('./views/Master/UserAdmin'));
const UserShift = React.lazy(() => import('./views/SimproV2/UserShift'));
const routes = [
{ path: '/', exact: true, name: 'Home' }, const routes = [
{ path: '/dashboard', name: 'Dashboard', component: DashboardSimpro }, { path: '/', exact: true, name: 'Home' },
{ path: '/dashboard', name: 'Dashboard', component: DashboardSimpro },
{ path: '/projects', exact: true, name: 'Projects', component: CreatedProyek }, { path: '/dashboardpmo', name: 'Dashboard', component: DashboardPMO },
{ path: '/projects/:id/:project/gantt', exact: true, name: 'Gantt', component: Gantt },
{ path: '/human-resource', exact: true, name: 'Human Resource', component: ResourceWorker }, { path: '/projects', exact: true, name: 'Projects', component: CreatedProyek },
{ path: '/material-resource', exact: true, name: 'Material Resource', component: ResourceMaterial }, { path: '/projects/:id/:project/gantt', exact: true, name: 'Gantt', component: Gantt },
{ path: '/tools-resource', exact: true, name: 'Tools Resource', component: ResourceTools }, { path: '/human-resource', exact: true, name: 'Human Resource', component: ResourceWorker },
{ path: '/material-resource', exact: true, name: 'Material Resource', component: ResourceMaterial },
{ path: '/control-monitoring', exact: true, name: 'Control Monitoring', component: ControlMonitoring }, { path: '/tools-resource', exact: true, name: 'Tools Resource', component: ResourceTools },
{ path: '/control-monitoring-gantt', exact: true, name: 'Control Monitoring Gantt', component: ControlMonitoringGantt },
{ path: '/presensi-resource', exact: true, name: 'Presensi Resource', component: Presensi }, { path: '/control-monitoring', exact: true, name: 'Control Monitoring', component: ControlMonitoring },
{ path: '/absensi-resource', exact: true, name: 'Absensi Resource', component: Absensi }, { path: '/control-monitoring-gantt', exact: true, name: 'Control Monitoring Gantt', component: ControlMonitoringGantt },
{ path: '/laporan-k3', exact: true, name: 'Laporan K3', component: K3 }, { path: '/presensi-resource', exact: true, name: 'Presensi Resource', component: Presensi },
{ path: '/broadcast', exact: true, name: 'Broadcast', component: Broadcast }, { path: '/absensi-resource', exact: true, name: 'Absensi Resource', component: Absensi },
{ path: '/panic-button', exact: true, name: 'Tombol Darurat', component: PanicButton }, { path: '/laporan-k3', exact: true, name: 'Laporan K3', component: K3 },
{ path: '/broadcast', exact: true, name: 'Broadcast', component: Broadcast },
{ path: '/closing', exact: true, name: 'Closing', component: Closing }, { path: '/panic-button', exact: true, name: 'Tombol Darurat', component: PanicButton },
{ path: '/menu', exact: true, name: 'Menu', component: Menu }, { path: '/closing', exact: true, name: 'Closing', component: Closing },
{ path: '/roles', exact: true, name: 'Roles', component: Roles },
{ path: '/project-role', exact: true, name: 'Project Role', component: ProjectRole }, { path: '/menu', exact: true, name: 'Menu', component: Menu },
{ path: '/project-type', exact: true, name: 'Project Type', component: ProjectType }, { path: '/roles', exact: true, name: 'Roles', component: Roles },
{ path: '/divisi', exact: true, name: 'Divisi', component: Divisi }, { path: '/project-role', exact: true, name: 'Project Role', component: ProjectRole },
{ path: '/satuan', exact: true, name: 'Satuan', component: Satuan }, { path: '/project-type', exact: true, name: 'Project Type', component: ProjectType },
{ path: '/config-alert', exact: true, name: 'Config Alert', component: ConfigAlert }, { path: '/divisi', exact: true, name: 'Divisi', component: Divisi },
{ path: '/satuan', exact: true, name: 'Satuan', component: Satuan },
{ path: '/checklist-k3', exact: true, name: 'Checklist K3', component: ChecklistK3 }, { path: '/config-alert', exact: true, name: 'Config Alert', component: ConfigAlert },
{ path: '/absensi', exact: true, name: 'Absensi', component: Absensi },
{ path: '/divisi-karyawan', exact: true, name: 'Divisi Karyawan', component: DivisiKaryawan }, { path: '/checklist-k3', exact: true, name: 'Checklist K3', component: ChecklistK3 },
{ path: '/izin', exact: true, name: 'Izin', component: Izin }, { path: '/absensi', exact: true, name: 'Absensi', component: Absensi },
{ path: '/laporan-alert', exact: true, name: 'Laporan Alert', component: LaporanAlert }, { path: '/divisi-karyawan', exact: true, name: 'Divisi Karyawan', component: DivisiKaryawan },
{ path: '/laporan-tugas-karyawan', exact: true, name: 'Laporan Tugas Karyawan', component: LaporanTugas }, { path: '/izin', exact: true, name: 'Izin', component: Izin },
{ path: '/lembur', exact: true, name: 'Lembur', component: Lembur }, { path: '/laporan-alert', exact: true, name: 'Laporan Alert', component: LaporanAlert },
{ path: '/map/baselayers', exact: true, name: 'Base Layers', component: BaseLayers }, { path: '/laporan-tugas-karyawan', exact: true, name: 'Laporan Tugas Karyawan', component: LaporanTugas },
{ path: '/map/config', exact: true, name: 'Config', component: MapConfig }, { path: '/lembur', exact: true, name: 'Lembur', component: Lembur },
{ path: '/map/layers', exact: true, name: 'Layers', component: Layers }, { path: '/map/baselayers', exact: true, name: 'Base Layers', component: BaseLayers },
{ path: '/map/layers/:id', exact: true, name: 'Layer Details', component: Layer }, { path: '/map/config', exact: true, name: 'Config', component: MapConfig },
{ path: '/office-hours', exact: true, name: 'Jam Kerja', component: OfficeHours }, { path: '/map/layers', exact: true, name: 'Layers', component: Layers },
{ path: '/organization', exact: true, name: 'Organisasi', component: Organization }, { path: '/map/layers/:id', exact: true, name: 'Layer Details', component: Layer },
{ path: '/planning-harian', exact: true, name: 'Planning Harian', component: PlanningHarian }, { path: '/office-hours', exact: true, name: 'Jam Kerja', component: OfficeHours },
{ path: '/presensi', exact: true, name: 'Presensi', component: Presensi }, { path: '/organization', exact: true, name: 'Organisasi', component: Organization },
{ path: '/proyek', exact: true, name: 'Created Project', component: Proyek }, { path: '/planning-harian', exact: true, name: 'Planning Harian', component: PlanningHarian },
{ path: '/proyek-gantt', exact: true, name: 'Gantt Chart Proyek', component: TestGantt }, { path: '/presensi', exact: true, name: 'Presensi', component: Presensi },
{ path: '/rate-cost', exact: true, name: 'Rate Cost', component: RateCost }, { path: '/proyek', exact: true, name: 'Created Project', component: Proyek },
{ path: '/schedule-shift', exact: true, name: 'Schedule Shift', component: ScheduleShift }, { path: '/proyek-gantt', exact: true, name: 'Gantt Chart Proyek', component: TestGantt },
{ path: '/user-admin', exact: true, name: 'User Admin', component: UserAdmin }, { path: '/rate-cost', exact: true, name: 'Rate Cost', component: RateCost },
{ path: '/user-shift', exact: true, name: 'Shift', component: UserShift }, { path: '/schedule-shift', exact: true, name: 'Schedule Shift', component: ScheduleShift },
{ path: '/working-hour', exact: true, name: 'Working Hour', component: Shift }, { path: '/user-admin', exact: true, name: 'User Admin', component: UserAdmin },
{ path: '/user-shift', exact: true, name: 'Shift', component: UserShift },
]; { path: '/working-hour', exact: true, name: 'Working Hour', component: Shift },
export default routes; ];
export default routes;

128
src/views/DashboardPMO/Dashboard.css

@ -0,0 +1,128 @@
.number-asset {
font-size: 50px;
font-weight: bold;
text-align: center;
}
.text-bold {
font-weight: bold;
}
.view-rectangle {
display: flex;
flex-direction: row;
width: 100%;
justify-content: space-between;
}
.view1 {
width: 220px;
height: 100px;
padding: 10px;
margin-bottom: -20px;
justify-content: center;
align-items: center;
text-align: center;
background-color: #008B8B;
}
.view2 {
width: 220px;
height: 100px;
padding: 10px;
justify-content: center;
align-items: center;
text-align: center;
background-color: #8B008B;
}
.view3 {
width: 220px;
height: 100px;
padding: 10px;
justify-content: center;
align-items: center;
text-align: center;
background-color: #7CFC00;
}
.view4 {
width: 220px;
height: 100px;
padding: 10px;
justify-content: center;
align-items: center;
text-align: center;
background-color: #FF0000;
}
.view5 {
width: 220px;
height: 100px;
padding: 10px;
justify-content: center;
align-items: center;
text-align: center;
background-color: #4682B4;
}
.number-style {
font-size: 30px;
color: black;
font-weight: bold;
margin-bottom:15px;
}
.number-style1 {
font-size: 30px;
color: #FFFFFF;
font-weight: bold;
margin-bottom:15px;
}
.daily-info-card {
min-width: 130px;
width: 220px;
height: 100px;
padding: 10px;
justify-content: center;
align-items: center;
text-align: center;
margin: 4px;
border-radius: 8px;
}
.dashboard-container {
overflow-x: auto;
}
.maptable-window-button-container {
float: right;
right: 0px;
}
.maptable-close, .maptable-maximize, .maptable-minimize {
cursor: pointer;
padding: 4px;
}
.maptable-header {
margin-bottom: -10px;
}
.maptable-title {
font-size: 24px;
font-weight: 700;
text-align: left;
margin-left: 20px;
}
.maptable-close:hover, .maptable-maximize:hover, .maptable-minimize:hover {
color: #20a8d8;
}

41
src/views/DashboardPMO/PieChart.js vendored

@ -0,0 +1,41 @@
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import { Pie } from '@ant-design/plots';
const PieChart = () => {
const data = [
{
type: 'FTTH',
value: 27,
},
{
type: 'Konstruksi',
value: 25,
},
];
const config = {
appendPadding: 10,
data,
angleField: 'value',
colorField: 'type',
radius: 0.9,
label: {
type: 'inner',
offset: '-30%',
content: ({ percent }) => `${(percent * 100).toFixed(0)}%`,
style: {
fontSize: 14,
textAlign: 'center',
},
},
interactions: [
{
type: 'element-active',
},
],
};
return <Pie {...config} />;
};
export default PieChart;

152
src/views/DashboardPMO/index.js

@ -0,0 +1,152 @@
import '../../../node_modules/react-grid-layout/css/styles.css';
import '../../../node_modules/react-resizable/css/styles.css';
import './Dashboard.css';
import PieChart from './PieChart';
import { BASE_OSPRO } from '../../const/ApiConst';
import ContentLoader from "react-content-loader"
import React, { useEffect, useState } from 'react';
import axios from 'axios'
import moment from 'moment';
import numeral from 'numeral';
import { Table, Tree, Row, Col, Space, Card} from 'antd';
import { Pie } from '@ant-design/plots';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import { formatRupiah, DATE_TIME_FORMAT } from '../../const/CustomFunc.js';
const token = localStorage.getItem("token")
const HEADER = {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"Access-Control-Allow-Origin": "*"
}
}
const Dashboard = () => {
const token = localStorage.getItem("token")
const HEADER = {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}
}
const [dataTable, setDataTable] = useState([])
const getProjects = async () => {
const URL = `${BASE_OSPRO}/api/project/list`
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
if (result.data.code !== 200) {
NotificationManager.error('Belum ada data proyek!', 'Failed');
}
console.log("res ", result.data.data)
// const arr = result.data.data.map((res) => {
// console.log("insd", res)
// return res
// });
setDataTable(result.data.data);
}
const columns = [
{
title: 'Project',
dataIndex: 'nama',
key: 'nama',
render: (text) => <a>{text}</a>,
},
{
title: 'Planned Interval',
dataIndex: 'plannedInterval',
key: 'plannedInterval',
},
{
title: 'Planned Cost',
dataIndex: 'plannedCost',
key: 'plannedCost',
},
{
title: 'Actual Cost',
dataIndex: 'actualCost',
key: 'actualCost',
},
{
title: 'Cost Variance',
dataIndex: 'costVariance',
key: 'costVariance',
},
{
title: 'Cost Health',
dataIndex: 'costHealth',
key: 'costHealth',
},
{
title: 'Schedule Health',
dataIndex: 'scheduleHealth',
key: 'scheduleHealth',
},
{
title: 'Progress',
dataIndex: 'progress',
key: 'progress',
},
];
useEffect(() => {
getProjects();
}, [])
return (
<>
<Row gutter={[16, 16]}>
<Col span={6} >
<Card
size="small"
title="Total Project"
align="center"
style={{
width: 300,
}}
>
<p align="center">5</p>
</Card>
</Col>
<Col span={6} >
<Card
size="small"
title="Total Project Cost"
align="center"
style={{
width: 300,
}}
>
<p align="center">5</p>
</Card>
</Col>
<Col span={6} >
<Card
size="small"
title="Cost Variance"
align="center"
style={{
width: 300,
}}
>
<p align="center">5</p>
</Card>
</Col>
<Col span={6} >
<PieChart />
</Col>
</Row>
<Row gutter={[16, 16]}>
<Col span={24}>
<Table columns={columns} dataSource={dataTable} />
</Col>
</Row>
</>
);
}
export default Dashboard;
Loading…
Cancel
Save