Browse Source

update route dashboard, and page dashboard PMO v1

pull/2/head
bnu 2 years ago
parent
commit
9aebdc3483
  1. 3
      src/routes.js
  2. 106
      src/views/DashboardPMOV1/chartDashboard.js
  3. 198
      src/views/DashboardPMOV1/index.js
  4. 130
      src/views/DashboardPMOV1/tableDashboard.js
  5. 115
      src/views/DashboardPMOV1/tableDashboardv1.js

3
src/routes.js

@ -43,11 +43,12 @@ const TestGantt = React.lazy(() => import('./views/testgantt'));
const UserAdmin = React.lazy(() => import('./views/Master/UserAdmin'));
const UserShift = React.lazy(() => import('./views/SimproV2/UserShift'));
const DashboardProject = React.lazy(() => import('./views/DashboardProject'));
const DashboardPMOV1 = React.lazy(() => import('./views/DashboardPMOV1'));
const routes = [
{ path: '/', exact: true, name: 'Home' },
{ path: '/dashboardold', name: 'Dashboard', component: DashboardSimpro },
{ path: '/dashboard', name: 'Dashboard', component: DashboardPMO },
{ path: '/dashboard', name: 'Dashboard', component: DashboardPMOV1 },
{ path: '/projects', exact: true, name: 'Projects', component: CreatedProyek },
{ path: '/projects/:id/:project/gantt', exact: true, name: 'Gantt', component: Gantt },

106
src/views/DashboardPMOV1/chartDashboard.js

@ -0,0 +1,106 @@
import React from 'react';
import { Doughnut, Bar } from 'react-chartjs-2';
import { faker } from '@faker-js/faker';
export const optionsDoughnut = {
title: {
display: true,
text: 'PROJECT BY TYPE'
},
};
export const data = {
labels: ['Pengadaan Barang dan Jasa','Kontruksi', 'FTTH'],
datasets: [
{
label: '# of Votes',
data: [1, 1, 2],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
// 'rgba(153, 102, 255, 0.2)',
// 'rgba(255, 159, 64, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
// 'rgba(255, 159, 64, 1)',
],
borderWidth: 1,
},
],
};
export const DoughnutChart = () => {
return <Doughnut data={data} options={optionsDoughnut} />;
}
export const options = {
title: {
display: true,
text: 'PROJECT BY GOVERNANCE PHASE'
},
legend: {
position: 'right',
},
responsive: true,
scales: {
yAxes: [{
display: true,
// position: 'right',
stacked: true,
}],
xAxes: [{
display: true,
// position: 'right',
stacked: true,
}],
},
};
const labels = [''];
export const dataBar = {
labels,
datasets: [
{
indexAxis: 'y',
label: 'Initiation',
data: labels.map(() => faker.datatype.number({ min: 0, max: 10 })),
backgroundColor: 'rgb(255, 99, 132)',
},
{
indexAxis: 'y',
label: 'Execution',
data: labels.map(() => faker.datatype.number({ min: 0, max: 10 })),
backgroundColor: 'rgb(75, 192, 192)',
},
{
indexAxis: 'y',
label: 'Closing',
data: labels.map(() => faker.datatype.number({ min: 0, max: 10 })),
backgroundColor: 'rgb(53, 162, 235)',
},
// {
// indexAxis: 'y',
// label: 'Excecution',
// data: labels.map(() => faker.datatype.number({ min: 0, max: 10 })),
// backgroundColor: 'rgba(255, 159, 64, 1)',
// },
],
};
export function BarChart() {
return <Bar indexAxis='y' options={options} data={dataBar} />;
}

198
src/views/DashboardPMOV1/index.js

@ -0,0 +1,198 @@
import React, {useEffect, useState} from 'react';
import { Row, Col, Select } from 'antd';
import TableDashboard from './tableDashboard';
import TableDashboardV1 from './tableDashboardv1';
import { BarChart, DoughnutChart } from './chartDashboard';
import axios from 'axios'
import { NotificationContainer, NotificationManager } from 'react-notifications';
import { BASE_OSPRO } from '../../const/ApiConst';
function BoxDashboard({ value, title, secondaryTitle, icon, bgColor }) {
return (
<div style={{ backgroundColor: bgColor }} className='box-dashboard-pm'>
<Row>
<Col span={7}>
<div className='box-icon'>
{icon}
</div>
</Col>
<Col span={17}>
<div className='box-content'>
<div style={{ fontSize: '1.4rem' }} className='text-box'>{value}</div>
<div style={{ fontSize: '0.7rem' }} className='text-box'>{title.toUpperCase()}</div>
<div style={{ fontSize: '0.6rem' }} className='text-box-secondary'>{secondaryTitle && secondaryTitle.toUpperCase()}</div>
</div>
</Col>
</Row>
</div>
)
}
const { Option } = Select;
const DashbaoardPM = () => {
const [PROJECTCOUNT, SET_PROJECTCOUNT] = useState([])
const [PROJECTBUDGETTOTAL, SET_PROJECTBUDGETTOTAL] = useState([])
const [PROJECTMANPOWER, SET_PROJETMANPOWER] = useState([])
const [PROJECTACTUALCOSTTOTAL, SET_PROJECTACTUALCOSTTOTAL] = useState([])
const token = localStorage.getItem("token")
const HEADER = {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}
}
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)
// setDataTable(result.data.data);
SET_PROJECTCOUNT(result.data.totalRecord)
SET_PROJECTACTUALCOSTTOTAL(result.data.totalActualCost)
SET_PROJECTBUDGETTOTAL(result.data.totalPlannedCost)
}
useEffect(() => {
getProjects();
}, [])
return (
<div>
<Row>
<Col span={4}><h6 style={{ textAlign: 'center' }}>PORTOFOLIO DASHBOARD</h6></Col>
{/* <Col span={5}>
<Select
style={{ width: '100%', padding: '0 5px' }}
showSearch
placeholder="Department"
optionFilterProp="children"
onChange={onChange}
onSearch={onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="tom">Tom</Option>
</Select>
</Col>
<Col span={5}>
<Select
style={{ width: '100%', padding: '0 5px' }}
showSearch
placeholder="Project Type"
optionFilterProp="children"
onChange={onChange}
onSearch={onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{['Manned guarding ', 'C&T', 'CMS ', 'ESS', 'RSO'].map(res => (
<Option value={res}>{res}</Option>
))}
</Select>
</Col>
<Col span={5}>
<Select
style={{ width: '100%', padding: '0 5px' }}
showSearch
placeholder="Project Owner"
optionFilterProp="children"
onChange={onChange}
onSearch={onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="tom">Tom</Option>
</Select>
</Col>
<Col span={5}>
<Select
style={{ width: '100%', padding: '0 5px' }}
showSearch
placeholder="Governance Phase"
optionFilterProp="children"
onChange={onChange}
onSearch={onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{['Initiation ', 'Excecution', 'Closing '].map(res => (
<Option value={res}>{res}</Option>
))}
</Select>
</Col> */}
</Row>
<div style={{ paddingTop: 0 }}>
<Row>
<Col span={4}>
<BoxDashboard
icon={<i style={{ color: '#fff' }} class="zmdi zmdi-assignment zmdi-hc-3x"></i>}
value={PROJECTCOUNT}
bgColor="teal"
title="Project Count" />
{/* <BoxDashboard
icon={<i style={{ color: '#fff' }} class="zmdi zmdi-money-box zmdi-hc-3x"></i>}
value="19 M"
bgColor="#059669"
title="Project Cost"
secondaryTitle="(dollars)" /> */}
<BoxDashboard
icon={<i style={{ color: '#fff' }} class="zmdi zmdi-money zmdi-hc-3x"></i>}
value={PROJECTBUDGETTOTAL}
bgColor="#047857"
title="Budget Project Total"
secondaryTitle="(dollars)" />
<BoxDashboard
icon={<i style={{ color: '#fff' }} class="zmdi zmdi-accounts-alt zmdi-hc-3x"></i>}
value="2000"
bgColor="#0284c7"
title="Project Manpower"
/>
<BoxDashboard
icon={<i style={{ color: '#fff' }} class="zmdi zmdi-account zmdi-hc-3x"></i>}
value="540"
bgColor="#0369a1"
title="Manpower Variance"
/>
<BoxDashboard
icon={<i style={{ color: '#fff' }} class="zmdi zmdi-alert-circle zmdi-hc-3x"></i>}
value="80"
bgColor="#b30000"
title="Active Car" />
</Col>
<Col span={20}>
<div style={{ padding: '20px 0 20px 5px' }}>
<Row>
<Col span={12}>
<BarChart />
</Col>
<Col span={12}>
<DoughnutChart />
</Col>
</Row>
</div>
<div style={{ paddingLeft: 5, }}>
<TableDashboardV1 />
</div>
</Col>
</Row>
</div>
</div>
);
}
export default DashbaoardPM;

130
src/views/DashboardPMOV1/tableDashboard.js

@ -0,0 +1,130 @@
import React from 'react';
import { Table, Tag, Space } from 'antd';
const columns = [
{
title: 'Project Name',
dataIndex: 'project',
key: 'project',
fixed: 'left',
width: 200,
// render: text => <a>{text}</a>,
},
{
title: 'Project Owner',
dataIndex: 'owner',
key: 'owner',
},
{
title: 'Start Date',
dataIndex: 'startDate',
key: 'startDate',
},
{
title: 'End Date',
dataIndex: 'endDate',
key: 'endDate',
},
{
title: 'Cost',
dataIndex: 'cost',
key: 'cost',
render: text => `Rp. ${text.toLocaleString()}`,
align: 'right'
},
{
title: 'Cost Health',
dataIndex: 'costHealth',
key: 'costHealth',
render: text =>
text === 'good' ? <div className='health-status-good' /> :
text === 'danger' ? <div className='health-status-danger' /> :
text === 'warning' ? <div className='health-status-warning' /> : <div className='health-status-default' />
,
align: 'center',
},
{
title: 'Work Health',
dataIndex: 'workHealth',
key: 'workHealth',
render: text =>
text === 'good' ? <div className='health-status-good' /> :
text === 'danger' ? <div className='health-status-danger' /> :
text === 'warning' ? <div className='health-status-warning' /> : <div className='health-status-default' />,
align: 'center',
},
{
title: 'Schedule Health',
dataIndex: 'scheduleHealth',
key: 'scheduleHealth',
render: text =>
text === 'good' ? <div className='health-status-good' /> :
text === 'danger' ? <div className='health-status-danger' /> :
text === 'warning' ? <div className='health-status-warning' /> : <div className='health-status-default' />,
align: 'center',
},
{
title: '% Complete',
dataIndex: 'complete',
key: 'complete',
render: text => `${text}%`,
align: 'right'
},
// {
// title: 'Action',
// key: 'action',
// render: (text, record) => (
// <Space size="middle">
// <a>Invite {record.name}</a>
// <a>Delete</a>
// </Space>
// ),
// },
];
const data = [
{
key: '1',
project: 'Bay Plaza',
owner: 'John Brown',
startDate: '1/22/2022',
endDate: '1/22/2023',
complete: 20,
cost: 40000000,
costHealth: 'good',
workHealth: 'default',
scheduleHealth: 'warning'
},
{
key: '2',
project: 'Jambi Bridge',
owner: 'Jim Green',
startDate: '4/22/2022',
endDate: '11/22/2023',
complete: 65,
cost: 20000000,
costHealth: 'good',
workHealth: 'default',
scheduleHealth: 'danger'
},
{
key: '3',
project: 'Banten International Airport',
owner: 'Joe Black',
startDate: '1/22/2022',
endDate: '1/22/2025',
complete: 50,
cost: 200000000,
costHealth: 'default',
workHealth: 'default',
scheduleHealth: 'default'
},
];
const TableDashboard = () => {
return (
<Table size="small" columns={columns} dataSource={data} scroll={{ x: 1300, y: 300 }} />
);
}
export default TableDashboard;

115
src/views/DashboardPMOV1/tableDashboardv1.js

@ -0,0 +1,115 @@
import '../../../node_modules/react-grid-layout/css/styles.css';
import '../../../node_modules/react-resizable/css/styles.css';
import './../DashboardPMO/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 { formatRibuanDecimal, DATE_TIME_FORMAT } from '../../const/CustomFunc.js';
import { Badge } from 'reactstrap';
import { Link } from "react-router-dom";
const token = localStorage.getItem("token")
const HEADER = {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`,
"Access-Control-Allow-Origin": "*"
}
}
const TableDashboardV1 = () => {
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)
setDataTable(result.data.data);
}
const columns = [
{
title: 'Project',
dataIndex: 'nama',
key: 'nama',
render: (text, record) => <Link to={`/dashboard-project/${record.id}/${record.lastGanttId}`}>{text}</Link>,
},
{
title: 'Planned Interval',
dataIndex: 'plannedInterval',
key: 'plannedInterval',
},
{
title: 'Budget Project',
dataIndex: 'plannedCost',
key: 'plannedCost',
render: (text) => <a>{ formatRibuanDecimal(text) }</a>,
},
{
title: 'Actual Cost',
dataIndex: 'actualCost',
key: 'actualCost',
render: (text) => <a>{ formatRibuanDecimal(text) }</a>,
},
{
title: 'Cost Variance',
dataIndex: 'costVariance',
key: 'costVariance',
render: (text) => <a>{ formatRibuanDecimal(text) }</a>,
},
{
title: 'Cost Health',
dataIndex: 'costHealth',
key: 'costHealth',
render: (text) => {
if(text == "on-budget") {
return <Badge color="success">On Budget</Badge>
} else if(text == "warning") {
return <Badge color="warning">Warning</Badge>
} else {
return <Badge color="danger">Danger</Badge>
}
}
},
{
title: 'Progress',
dataIndex: 'progress',
key: 'progress',
},
];
useEffect(() => {
getProjects();
}, [])
return (
<>
<Row gutter={[16, 16]}>
<Col span={24}>
<Table columns={columns} dataSource={dataTable} />
</Col>
</Row>
</>
);
}
export default TableDashboardV1;
Loading…
Cancel
Save