Browse Source

progress

pull/2/head
Yusuf 2 years ago
parent
commit
e98437b215
  1. 28
      src/App.js
  2. 40
      src/const/ApiConst.js
  3. 5
      src/containers/DefaultLayout/DefaultHeader.js
  4. 7
      src/containers/DefaultLayout/DefaultLayout.js
  5. 2
      src/routes.js
  6. 3
      src/scss/_custom.scss
  7. 114
      src/views/DashboardPMO/index.js
  8. 78
      src/views/DashboardPMOV1/chartDashboard.js
  9. 335
      src/views/DashboardPMOV1/index.js
  10. 36
      src/views/DashboardPMOV1/projectPhaseChart.js
  11. 2
      src/views/DashboardPMOV1/tableDashboard.js
  12. 74
      src/views/DashboardPMOV1/tableDashboardv1.js
  13. 18
      src/views/DashboardProject/index.js
  14. 484
      src/views/DashboardSimpro/index.js
  15. 121
      src/views/Master/ProjectPhase/DialogForm.js
  16. 89
      src/views/Master/ProjectPhase/DialogFormInitial.js
  17. 217
      src/views/Master/ProjectPhase/DialogInitialGantt.js
  18. 325
      src/views/Master/ProjectPhase/index.js
  19. 117
      src/views/SimproV2/CreatedProyek/DialogFormProyek.js
  20. 23
      src/views/SimproV2/CreatedProyek/index.js

28
src/App.js

@ -19,20 +19,20 @@ class App extends Component {
render() { render() {
return ( return (
<HashRouter> <HashRouter>
<React.Suspense fallback={loading()}> <React.Suspense fallback={loading()}>
<Switch> <Switch>
<Route exact path="/login" name="Login Page" render={props => <Login {...props}/>} /> <Route exact path="/login" name="Login Page" render={props => <Login {...props} />} />
{/* <Route exact path="/home" name="Home" render={props => <DefaultLayout {...props}/>} /> */} {/* <Route exact path="/home" name="Home" render={props => <DefaultLayout {...props}/>} /> */}
<Route exact path="/register" name="Register Page" render={props => <Register {...props}/>} /> <Route exact path="/register" name="Register Page" render={props => <Register {...props} />} />
<Route exact path="/404" name="Page 404" render={props => <Page404 {...props}/>} /> <Route exact path="/404" name="Page 404" render={props => <Page404 {...props} />} />
<Route exact path="/403" name="Page 403" render={props => <Page403 {...props}/>} /> <Route exact path="/403" name="Page 403" render={props => <Page403 {...props} />} />
<Route exact path="/500" name="Page 500" render={props => <Page500 {...props}/>} /> <Route exact path="/500" name="Page 500" render={props => <Page500 {...props} />} />
<Route exact path="/map/view" name="Map" render={props => <SiopasMap {...props}/>} /> <Route exact path="/map/view" name="Map" render={props => <SiopasMap {...props} />} />
{/*<Route exact path="/layerswitcher" name="Layer Switcher" render={props => <LayerSwitcherExample {...props}/>} />*/} {/*<Route exact path="/layerswitcher" name="Layer Switcher" render={props => <LayerSwitcherExample {...props}/>} />*/}
{/*<Route exact path="/muidt" name="Mui Datatable Example" render={props => <MuiDatatablesExample {...props}/>} />*/} {/*<Route exact path="/muidt" name="Mui Datatable Example" render={props => <MuiDatatablesExample {...props}/>} />*/}
<Route path="/" name="Home" render={props => <DefaultLayout {...props}/>} /> <Route path="/" name="Home" render={props => <DefaultLayout {...props} />} />
</Switch> </Switch>
</React.Suspense> </React.Suspense>
</HashRouter> </HashRouter>
); );
} }

40
src/const/ApiConst.js

@ -116,29 +116,29 @@ export let BASE_SIMPRO_LUMEN_IMAGE = `${BASE_OSPRO}/assets/image`;
export let BASE_SIMPRO_LUMEN_FILE = `${BASE_OSPRO}/assets/file/project`; export let BASE_SIMPRO_LUMEN_FILE = `${BASE_OSPRO}/assets/file/project`;
switch (APP_MODE) { switch (APP_MODE) {
case 'KIT': case 'KIT':
BASE_OSPRO = "https://kit-api.oslogdev.com" BASE_OSPRO = "https://kit-api.oslogdev.com"
break; break;
case 'ADW': case 'ADW':
BASE_OSPRO = "https://ospro-api.ospro.id" BASE_OSPRO = "https://api-staging-adw.ospro.id"
BASE_SIMPRO_LUMEN = `${BASE_OSPRO}/api`; BASE_SIMPRO_LUMEN = `${BASE_OSPRO}/api`;
BASE_SIMPRO_LUMEN_IMAGE = `${BASE_OSPRO}/assets/image`; BASE_SIMPRO_LUMEN_IMAGE = `${BASE_OSPRO}/assets/image`;
BASE_SIMPRO_LUMEN_FILE = `${BASE_OSPRO}/assets/file/project`; BASE_SIMPRO_LUMEN_FILE = `${BASE_OSPRO}/assets/file/project`;
break; break;
case 'IU': case 'IU':
BASE_OSPRO = "https://api-iu.ospro.id" BASE_OSPRO = "https://api-iu.ospro.id"
BASE_SIMPRO_LUMEN = `${BASE_OSPRO}/api`; BASE_SIMPRO_LUMEN = `${BASE_OSPRO}/api`;
BASE_SIMPRO_LUMEN_IMAGE = `${BASE_OSPRO}/assets/image`; BASE_SIMPRO_LUMEN_IMAGE = `${BASE_OSPRO}/assets/image`;
BASE_SIMPRO_LUMEN_FILE = `${BASE_OSPRO}/assets/file/project`; BASE_SIMPRO_LUMEN_FILE = `${BASE_OSPRO}/assets/file/project`;
break; break;
default: default:
BASE_OSPRO = "https://ospro-api.ospro.id" BASE_OSPRO = "https://ospro-api.ospro.id"
} }
@ -305,6 +305,12 @@ export const PROJECT_TYPE_EDIT = (id) => { return `${BASE_SIMPRO_LUMEN}/project-
export const PROJECT_TYPE_DELETE = (id) => { return `${BASE_SIMPRO_LUMEN}/project-type/delete/${id}` } export const PROJECT_TYPE_DELETE = (id) => { return `${BASE_SIMPRO_LUMEN}/project-type/delete/${id}` }
export const TYPE_PROYEK = `${BASE_SIMPRO_LUMEN}/project-type/list` export const TYPE_PROYEK = `${BASE_SIMPRO_LUMEN}/project-type/list`
export const PROJECT_PHASE_ADD = `${BASE_SIMPRO_LUMEN}/project-phase/add`
export const PROJECT_PHASE_SEARCH = `${BASE_SIMPRO_LUMEN}/project-phase/search`
export const PROJECT_PHASE_EDIT = (id) => { return `${BASE_SIMPRO_LUMEN}/project-phase/update/${id}` }
export const PROJECT_PHASE_DELETE = (id) => { return `${BASE_SIMPRO_LUMEN}/project-phase/delete/${id}` }
export const PHASE_PROYEK = `${BASE_SIMPRO_LUMEN}/project-phase/list`
export const PROJECT_CHARTER_ADD = `${BASE_SIMPRO_LUMEN}/project-charter/add` export const PROJECT_CHARTER_ADD = `${BASE_SIMPRO_LUMEN}/project-charter/add`
export const PROJECT_CHARTER_SEARCH = `${BASE_SIMPRO_LUMEN}/project-charter/search` export const PROJECT_CHARTER_SEARCH = `${BASE_SIMPRO_LUMEN}/project-charter/search`
export const PROJECT_CHARTER_EDIT = (id) => { return `${BASE_SIMPRO_LUMEN}/project-charter/update/${id}` } export const PROJECT_CHARTER_EDIT = (id) => { return `${BASE_SIMPRO_LUMEN}/project-charter/update/${id}` }

5
src/containers/DefaultLayout/DefaultHeader.js

@ -126,13 +126,10 @@ class DefaultHeader extends Component {
case 'KIT': case 'KIT':
img = <img style={{ width: '100%', height: '100%' }} src={logo_header_kit} /> img = <img style={{ width: '100%', height: '100%' }} src={logo_header_kit} />
break; break;
case 'ADW':
img = <img style={{ width: '100%', height: '100%' }} src={logo_header_adw} />
break;
case 'NAWAKARA': case 'NAWAKARA':
img = <img style={{ width: '32%', height: '32%', display: 'flex', justifyContent: 'center' }} src={logo_header_nawakara} /> img = <img style={{ width: '32%', height: '32%', display: 'flex', justifyContent: 'center' }} src={logo_header_nawakara} />
break; break;
case 'IU': case 'ADW':
img = <div style={{ fontWeight: 'bold', fontSize: 30, fontFamily: 'Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif', textAlign: 'center', marginLeft: 25, marginRigth: 20 }}><span style={{ color: '#4472C4' }}>OS</span><span style={{ color: '#ED7D31' }}>PRO</span></div> img = <div style={{ fontWeight: 'bold', fontSize: 30, fontFamily: 'Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif', textAlign: 'center', marginLeft: 25, marginRigth: 20 }}><span style={{ color: '#4472C4' }}>OS</span><span style={{ color: '#ED7D31' }}>PRO</span></div>
break; break;
default: default:

7
src/containers/DefaultLayout/DefaultLayout.js

@ -157,10 +157,7 @@ class DefaultLayout extends Component {
} }
setMenu = data => { setMenu = data => {
const menu = data.map(res => { const menu = data.map(res => {
const obj = { const obj = {
name: res.name, name: res.name,
url: res.url, url: res.url,
@ -215,7 +212,9 @@ class DefaultLayout extends Component {
}); });
} }
else { else {
return <AppBreadcrumb appRoutes={this.state.finalRoutes} router={router} /> if (!window.location.href.includes("dashboard")){
return <AppBreadcrumb appRoutes={this.state.finalRoutes} router={router} />
}
} }
} }

2
src/routes.js

@ -30,6 +30,7 @@ const PlanningHarian = React.lazy(() => import('./views/SimproV2/PlanningHarian'
const Presensi = React.lazy(() => import('./views/SimproV2/Presence')); const Presensi = React.lazy(() => import('./views/SimproV2/Presence'));
const ProjectRole = React.lazy(() => import('./views/Master/RoleProject')); const ProjectRole = React.lazy(() => import('./views/Master/RoleProject'));
const ProjectType = React.lazy(() => import('./views/SimproV2/ProjectType')); const ProjectType = React.lazy(() => import('./views/SimproV2/ProjectType'));
const ProjectPhase = React.lazy(() => import('./views/Master/ProjectPhase'));
const Proyek = React.lazy(() => import('./views/Master/Proyek')); const Proyek = React.lazy(() => import('./views/Master/Proyek'));
const RateCost = React.lazy(() => import('./views/SimproV2/RateCost')); const RateCost = React.lazy(() => import('./views/SimproV2/RateCost'));
const ResourceMaterial = React.lazy(() => import('./views/SimproV2/ResourceMaterial')); const ResourceMaterial = React.lazy(() => import('./views/SimproV2/ResourceMaterial'));
@ -70,6 +71,7 @@ const routes = [
{ path: '/roles', exact: true, name: 'Roles', component: Roles }, { path: '/roles', exact: true, name: 'Roles', component: Roles },
{ path: '/project-role', exact: true, name: 'Project Role', component: ProjectRole }, { path: '/project-role', exact: true, name: 'Project Role', component: ProjectRole },
{ path: '/project-type', exact: true, name: 'Project Type', component: ProjectType }, { path: '/project-type', exact: true, name: 'Project Type', component: ProjectType },
{ path: '/project-phase', exact: true, name: 'Project Phase', component: ProjectPhase },
{ path: '/divisi', exact: true, name: 'Divisi', component: Divisi }, { path: '/divisi', exact: true, name: 'Divisi', component: Divisi },
{ path: '/satuan', exact: true, name: 'Satuan', component: Satuan }, { path: '/satuan', exact: true, name: 'Satuan', component: Satuan },
{ path: '/config-alert', exact: true, name: 'Config Alert', component: ConfigAlert }, { path: '/config-alert', exact: true, name: 'Config Alert', component: ConfigAlert },

3
src/scss/_custom.scss

@ -18,8 +18,7 @@
.box-dashboard-pm { .box-dashboard-pm {
margin-top: 10px; margin-top: 10px;
width: 100%; width: 100%;
height: 90px; padding: 5px;
padding: 10px;
border-radius: 2px; border-radius: 2px;
box-shadow: 1px 1px 3px 0px rgba(97, 96, 96, 0.5); box-shadow: 1px 1px 3px 0px rgba(97, 96, 96, 0.5);
-webkit-box-shadow: 1px 1px 3px 0px rgba(97, 96, 96, 0.5); -webkit-box-shadow: 1px 1px 3px 0px rgba(97, 96, 96, 0.5);

114
src/views/DashboardPMO/index.js

@ -1,114 +0,0 @@
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 { formatRibuanDecimal, DATE_TIME_FORMAT } from '../../const/CustomFunc.js';
import { Badge } from 'reactstrap';
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)
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',
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 Dashboard;

78
src/views/DashboardPMOV1/chartDashboard.js

@ -1,15 +1,15 @@
import React from 'react'; import React from 'react';
import { Doughnut, Bar } from 'react-chartjs-2'; import { Doughnut } from 'react-chartjs-2';
import { faker } from '@faker-js/faker'; import { faker } from '@faker-js/faker';
export const optionsDoughnut = { const options = {
title: { title: {
display: true, display: true,
text: 'PROJECT BY TYPE' text: 'PROJECT BY TYPE'
}, },
}; };
export const data = { const data = {
labels: ['Pengadaan Barang dan Jasa','Kontruksi', 'FTTH'], labels: ['Pengadaan Barang dan Jasa','Kontruksi', 'FTTH'],
datasets: [ datasets: [
{ {
@ -20,8 +20,6 @@ export const data = {
'rgba(54, 162, 235, 0.2)', 'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)', 'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)', 'rgba(75, 192, 192, 0.2)',
// 'rgba(153, 102, 255, 0.2)',
// 'rgba(255, 159, 64, 0.2)',
], ],
borderColor: [ borderColor: [
'rgba(255, 99, 132, 1)', 'rgba(255, 99, 132, 1)',
@ -29,78 +27,12 @@ export const data = {
'rgba(255, 206, 86, 1)', 'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)', 'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)', 'rgba(153, 102, 255, 1)',
// 'rgba(255, 159, 64, 1)',
], ],
borderWidth: 1, borderWidth: 1,
}, },
], ],
}; };
export const DoughnutChart = () => { export const ProjectTypeChart = () => {
return <Doughnut data={data} options={optionsDoughnut} />; return <Doughnut data={data} options={options} />;
} }
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} />;
}

335
src/views/DashboardPMOV1/index.js

@ -1,199 +1,206 @@
import React, {useEffect, useState} from 'react'; import React, { useEffect, useState } from 'react';
import { Row, Col, Select } from 'antd'; import { Row, Col, Select, Collapse } from 'antd';
import TableDashboard from './tableDashboard'; import { Column } from '@ant-design/plots';
import TableDashboardV1 from './tableDashboardv1'; import TableDashboardV1 from './tableDashboardv1';
import { BarChart, DoughnutChart } from './chartDashboard'; import { ProjectTypeChart } from './chartDashboard';
import { ProjectPhaseChart } from './projectPhaseChart';
import axios from 'axios' import axios from 'axios'
import { NotificationContainer, NotificationManager } from 'react-notifications';
import { BASE_OSPRO } from '../../const/ApiConst'; import { BASE_OSPRO } from '../../const/ApiConst';
import { formatRibuanDecimal } from '../../const/CustomFunc.js';
const { Panel } = Collapse;
function BoxDashboard({ value, title, secondaryTitle, icon, bgColor }) { function BoxDashboard({ value, title, secondaryTitle, icon, bgColor }) {
return ( return (
<div style={{ backgroundColor: bgColor }} className='box-dashboard-pm'> <>
<Row> <div style={{ backgroundColor: bgColor }} class='box-dashboard-pm'>
<Col span={7}> <Row>
<div className='box-icon'> <Col span={4}>
{icon} <div class='box-icon'>
</div> {icon}
</Col> </div>
<Col span={17}> </Col>
<div className='box-content'> <Col span={20}>
<div style={{ fontSize: '1.4rem' }} className='text-box'>{value}</div> <div class='box-content'>
<div style={{ fontSize: '0.7rem' }} className='text-box'>{title.toUpperCase()}</div> <div style={{ fontSize: '1.0rem' }} class='text-box'>{value}</div>
<div style={{ fontSize: '0.6rem' }} className='text-box-secondary'>{secondaryTitle && secondaryTitle.toUpperCase()}</div> <div style={{ fontSize: '0.7rem' }} class='text-box'>{title.toUpperCase()}</div>
</div> <div style={{ fontSize: '0.6rem' }} class='text-box-secondary'>{secondaryTitle && secondaryTitle.toUpperCase()}</div>
</Col> </div>
</Row> </Col>
</div> </Row>
</div>
</>
) )
} }
const { Option } = Select; // pardon this, i've no time
function BoxDashboardNoIcon({ value, title, secondaryTitle, bgColor }) {
return (
<>
<div style={{ backgroundColor: bgColor }} class='box-dashboard-pm'>
<Row>
<Col span={24}>
<div class='box-content'>
<div style={{ fontSize: '1.4rem' }} class='text-box'>{value}</div>
<div style={{ fontSize: '0.7rem' }} class='text-box'>{title.toUpperCase()}</div>
<div style={{ fontSize: '0.6rem' }} class='text-box-secondary'>{secondaryTitle && secondaryTitle.toUpperCase()}</div>
</div>
</Col>
</Row>
</div>
</>
)
}
const DashbaoardPM = () => {
const [PROJECTCOUNT, SET_PROJECTCOUNT] = useState([]) const DashboardPM = () => {
const [PROJECTBUDGETTOTAL, SET_PROJECTBUDGETTOTAL] = useState([]) const [PROJECTCOUNT, SET_PROJECTCOUNT] = useState(0)
const [PROJECTMANPOWER, SET_PROJETMANPOWER] = useState([]) const [PROJECTBUDGETTOTAL, SET_PROJECTBUDGETTOTAL] = useState(0)
const [PROJECTACTUALCOSTTOTAL, SET_PROJECTACTUALCOSTTOTAL] = useState([]) const [PROJECTMANPOWER, SET_PROJETMANPOWER] = useState(0)
const [PROJECTACTUALCOSTTOTAL, SET_PROJECTACTUALCOSTTOTAL] = useState(0)
const [PROJECTCOSTTOTAL, SET_PROJECTCOSTTOTAL] = useState(0)
const [TOTALREVENUE, SET_TOTALREVENUE] = useState(0)
const token = localStorage.getItem("token") const token = localStorage.getItem("token")
const HEADER = { const HEADER = {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"Authorization": `Bearer ${token}` "Authorization": `Bearer ${token}`
} }
} }
const getProjects = async () => { const getProjectInfos = async () => {
const URL = `${BASE_OSPRO}/api/project/list` const URL = `${BASE_OSPRO}/api/project/list`
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response) 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_PROJECTCOUNT(result.data.totalRecord)
SET_PROJECTACTUALCOSTTOTAL(result.data.totalActualCost) result.data.totalActualCost != undefined ? SET_PROJECTCOSTTOTAL(result.data.totalActualCost) : SET_PROJECTCOSTTOTAL(0)
SET_PROJECTBUDGETTOTAL(result.data.totalPlannedCost) result.data.totalPlannedCost != undefined ? SET_PROJECTBUDGETTOTAL(result.data.totalPlannedCost) : SET_PROJECTBUDGETTOTAL(0)
result.data.totalRevenue != undefined ? SET_TOTALREVENUE(result.data.totalRevenue) : SET_TOTALREVENUE(0)
} }
useEffect(() => { useEffect(() => {
getProjects(); getProjectInfos();
}, []) }, [])
return ( return (
<div> <>
<Row> <div>
<Col span={4}><h6 style={{ textAlign: 'center' }}>PORTOFOLIO DASHBOARD</h6></Col> <Row
{/* <Col span={5}> gutter={{
<Select xs: 8,
style={{ width: '100%', padding: '0 5px' }} sm: 16,
showSearch md: 24,
placeholder="Department" lg: 32,
optionFilterProp="children" }}
onChange={onChange} >
onSearch={onSearch} <Col span={6} style={{ margin: '' }}>
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 <BoxDashboard
icon={<i style={{ color: '#fff' }} class="zmdi zmdi-money zmdi-hc-3x"></i>} icon={<i style={{ color: '#fff' }} class="zmdi zmdi-money zmdi-hc-4x"></i>}
value={`${PROJECTBUDGETTOTAL} M`} value={`${formatRibuanDecimal(PROJECTBUDGETTOTAL)}`}
bgColor="#047857" bgColor="#077857"
title="Budget Project Total" title="Budget"
// secondaryTitle="(dollars)" />
/> </Col>
<Col span={6} style={{ margin: '' }}>
<BoxDashboard <BoxDashboard
icon={<i style={{ color: '#fff' }} class="zmdi zmdi-accounts-alt zmdi-hc-3x"></i>} icon={<i style={{ color: '#fff' }} class="zmdi zmdi-money zmdi-hc-4x"></i>}
value="2000" value={`${formatRibuanDecimal(PROJECTCOSTTOTAL)}`}
bgColor="#0284c7" bgColor="#077857"
title="Project Manpower" title="Spent on Projects"
/> />
</Col>
<Col span={6} style={{ margin: '' }}>
<BoxDashboard <BoxDashboard
icon={<i style={{ color: '#fff' }} class="zmdi zmdi-account zmdi-hc-3x"></i>} icon={<i style={{ color: '#fff' }} class="zmdi zmdi-money zmdi-hc-4x"></i>}
value="540" value={`${formatRibuanDecimal(TOTALREVENUE)}`}
bgColor="#0369a1" bgColor="#077857"
title="Manpower Variance" title="Revenue"
/> />
</Col>
<Col span={6} style={{ margin: '' }}>
<BoxDashboard <BoxDashboard
icon={<i style={{ color: '#fff' }} class="zmdi zmdi-alert-circle zmdi-hc-3x"></i>} icon={<i style={{ color: '#fff' }} class="zmdi zmdi-accounts-alt zmdi-hc-4x"></i>}
value="80" value="-"
bgColor="#b30000" bgColor="#0287c7"
title="Active Car" /> title="Manpowers"
/>
</Col> </Col>
<Col span={20}> </Row>
<div style={{ padding: '20px 0 20px 5px' }}> <Row style={{ marginTop: '15px' }}>
<Row> <Col span={24} style={{ margin: '0px 0px 0px 0px' }}>
<Col span={12}> <Collapse>
<BarChart /> <Panel key="1">
</Col> <Row style={{ margin: '15px 10px 0px 0px' }}>
<Col span={12}> <Col span={8} >
<DoughnutChart /> <Row
</Col> gutter={{
</Row> xs: 8,
</div> sm: 16,
<div style={{ paddingLeft: 5, }}> md: 24,
<TableDashboardV1 /> lg: 32,
</div> }}
>
<Col span={12}>
<BoxDashboardNoIcon
value="-"
bgColor="#077857"
title="Active / Standby"
/>
</Col>
<Col span={12}>
<BoxDashboardNoIcon
value="-"
bgColor="#077857"
title="Need Maintenance"
/>
</Col>
</Row>
<Row
gutter={{
xs: 8,
sm: 16,
md: 24,
lg: 32,
}}
>
<Col span={12}>
<BoxDashboardNoIcon
bgColor="#077857"
title=""
value={<i style={{ color: '#fff' }} class="zmdi zmdi-truck zmdi-hc-2x"></i>}
/>
</Col>
<Col span={12}>
<BoxDashboardNoIcon
value="-"
bgColor="#077857"
title="On Maintenance"
/>
</Col>
</Row>
</Col>
<Col span={8}>
<ProjectPhaseChart />
</Col>
<Col span={8}>
<ProjectTypeChart />
</Col>
</Row>
</Panel>
</Collapse>
</Col>
</Row>
<Row style={{ marginTop: '15px' }}>
<Col span={24}>
<TableDashboardV1 />
</Col> </Col>
</Row> </Row>
</div> </div>
</div> </>
); );
} }
export default DashbaoardPM; export default DashboardPM;

36
src/views/DashboardPMOV1/projectPhaseChart.js vendored

@ -0,0 +1,36 @@
import React from 'react';
import { Bar } from 'react-chartjs-2';
import { faker } from '@faker-js/faker';
const options = {
indexAxis: 'y',
responsive: true,
};
const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
export const data = {
labels,
datasets: [
{
label: 'Dataset 1',
data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
borderColor: 'rgb(255, 99, 132)',
backgroundColor: 'rgba(255, 99, 132, 0.5)',
},
{
label: 'Dataset 2',
data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
borderColor: 'rgb(53, 162, 235)',
backgroundColor: 'rgba(53, 162, 235, 0.5)',
},
],
};
export function ProjectPhaseChart() {
return <Bar options={options} data={data} />;
}

2
src/views/DashboardPMOV1/tableDashboard.js

@ -8,7 +8,7 @@ const columns = [
key: 'project', key: 'project',
fixed: 'left', fixed: 'left',
width: 200, width: 200,
// render: text => <a>{text}</a>, render: text => <a>{text}</a>,
}, },
{ {
title: 'Project Owner', title: 'Project Owner',

74
src/views/DashboardPMOV1/tableDashboardv1.js

@ -1,47 +1,31 @@
import '../../../node_modules/react-grid-layout/css/styles.css'; import '../../../node_modules/react-grid-layout/css/styles.css';
import '../../../node_modules/react-resizable/css/styles.css'; import '../../../node_modules/react-resizable/css/styles.css';
import './../DashboardPMO/Dashboard.css'; import './../DashboardPMO/Dashboard.css';
// import PieChart from './PieChart';
import { BASE_OSPRO } from '../../const/ApiConst'; import { BASE_OSPRO } from '../../const/ApiConst';
import ContentLoader from "react-content-loader"
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import axios from 'axios' import axios from 'axios'
import moment from 'moment'; import { Table, Row, Col } from 'antd';
import numeral from 'numeral'; import { formatRibuanDecimal } from '../../const/CustomFunc.js';
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 { Badge } from 'reactstrap';
import { Link } from "react-router-dom"; 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 TableDashboardV1 = () => {
const token = localStorage.getItem("token") const token = localStorage.getItem("token")
const HEADER = { const HEADER = {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"Authorization": `Bearer ${token}` "Authorization": `Bearer ${token}`,
} }
} }
const [dataTable, setDataTable] = useState([]) const [dataTable, setDataTable] = useState([])
const getProjects = async () => { const getProjects = async () => {
const URL = `${BASE_OSPRO}/api/project/list` const URL = `${BASE_OSPRO}/api/project/list`
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response) const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
if (result.data.code !== 200) { console.log("qqq", result)
NotificationManager.error('Belum ada data proyek!', 'Failed'); if (result.data.code == 200) {
setDataTable(result.data.data);
} }
// console.log("res ", result.data.data)
setDataTable(result.data.data);
} }
const columns = [ const columns = [
@ -60,38 +44,41 @@ const TableDashboardV1 = () => {
title: 'Budget Project', title: 'Budget Project',
dataIndex: 'plannedCost', dataIndex: 'plannedCost',
key: 'plannedCost', key: 'plannedCost',
render: (text) => <a>{ formatRibuanDecimal(text) }</a>, render: (text) => <a>{formatRibuanDecimal(text)}</a>,
}, },
{ {
title: 'Actual Cost', title: 'Actual Cost',
dataIndex: 'actualCost', dataIndex: 'actualCost',
key: 'actualCost', key: 'actualCost',
render: (text) => <a>{ formatRibuanDecimal(text) }</a>, render: (text) => <a>{formatRibuanDecimal(text)}</a>,
}, },
{ {
title: 'Cost Variance', title: 'Cost Variance',
dataIndex: 'costVariance', dataIndex: 'costVariance',
key: 'costVariance', key: 'costVariance',
render: (text) => <a>{ formatRibuanDecimal(text) }</a>, render: (text) => <a>{formatRibuanDecimal(text)}</a>,
}, },
{ {
title: 'Cost Health', title: 'Cost Health',
dataIndex: 'costHealth', dataIndex: 'costHealth',
key: 'costHealth', key: 'costHealth',
render: (text) => { render: (text) => {
if(text == "on-budget") { if (text == "on-budget") {
return <Badge color="success">On Budget</Badge> return <Badge color="success">On Budget</Badge>
} else if(text == "warning") { } else if (text == "warning") {
return <Badge color="warning">Warning</Badge> return <Badge color="warning">Warning</Badge>
} else { } else {
return <Badge color="danger">Danger</Badge> return <Badge color="danger">Danger</Badge>
} }
} }
}, },
{ {
title: 'Progress', title: 'Progress',
dataIndex: 'progress', dataIndex: 'progress',
key: 'progress', key: 'progress',
render: (text) => {
return <Badge color={parseInt(text) > 74 ? 'success' : text > 49 ? 'warning' : 'danger'}>{text}%</Badge>
}
}, },
]; ];
@ -100,16 +87,15 @@ const TableDashboardV1 = () => {
}, []) }, [])
return ( return (
<> <>
<Row gutter={[16, 16]}> <Row gutter={[16, 16]}>
<Col span={24}> <Col span={24}>
<Table columns={columns} dataSource={dataTable} /> <Table columns={columns} dataSource={dataTable} />
</Col> </Col>
</Row> </Row>
</> </>
);
);
} }
export default TableDashboardV1; export default TableDashboardV1;

18
src/views/DashboardProject/index.js

@ -20,7 +20,7 @@ function BoxDashboard({ value, title, secondaryTitle, icon, bgColor }) {
<div style={{ fontSize: '0.8rem', fontWeight: 500, color: '#fff', textTransform: 'uppercase' }}>{title}</div> <div style={{ fontSize: '0.8rem', fontWeight: 500, color: '#fff', textTransform: 'uppercase' }}>{title}</div>
<div>{icon}</div> <div>{icon}</div>
</div> </div>
<div style={{ fontSize: '1rem', fontWeight: 500, color: '#fff' }}>Rp. {value}</div> <div style={{ fontSize: '1rem', fontWeight: 500, color: '#fff' }}>{value}</div>
</div> </div>
) )
} }
@ -45,12 +45,12 @@ const DashboardProject = () => {
const token = localStorage.getItem("token") const token = localStorage.getItem("token")
const HEADER = { const HEADER = {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"Authorization": `Bearer ${token}` "Authorization": `Bearer ${token}`
} }
} }
const getProjectDetail = async () => { const getProjectDetail = async () => {
const URL = `${BASE_OSPRO}/api/project/dashboard/${ID}` const URL = `${BASE_OSPRO}/api/project/dashboard/${ID}`
@ -75,7 +75,7 @@ const DashboardProject = () => {
return ( return (
<div style={{ margin: "-15px" }}> <div style={{ margin: "10px" }}>
<Row> <Row>
<Col span={9}> <Col span={9}>
<div style={{ display: 'flex', justifyContent: 'space-between', margin: '0 5px' }} className="box-header-dashboard-project"> <div style={{ display: 'flex', justifyContent: 'space-between', margin: '0 5px' }} className="box-header-dashboard-project">
@ -95,7 +95,7 @@ const DashboardProject = () => {
<Col span={7}> <Col span={7}>
<div style={{ display: 'flex', justifyContent: 'space-between', margin: '0 5px' }} className="box-header-dashboard-project"> <div style={{ display: 'flex', justifyContent: 'space-between', margin: '0 5px' }} className="box-header-dashboard-project">
<div><i style={{ color: '#b91c1c' }} class="zmdi zmdi-home zmdi-hc-lg"></i></div> <div><i style={{ color: '#b91c1c' }} class="zmdi zmdi-home zmdi-hc-lg"></i></div>
<div style={{ textTransform: 'uppercase' }}>Company</div> <div style={{ textTransform: 'uppercase' }}>Customer</div>
<div style={{ fontWeight: 500, color: '#404040', textTransform: 'uppercase' }}>{RO}</div> <div style={{ fontWeight: 500, color: '#404040', textTransform: 'uppercase' }}>{RO}</div>
</div> </div>
</Col> </Col>

484
src/views/DashboardSimpro/index.js

@ -2,8 +2,8 @@ import '../../../node_modules/react-grid-layout/css/styles.css';
import '../../../node_modules/react-resizable/css/styles.css'; import '../../../node_modules/react-resizable/css/styles.css';
import '../Map/CustomScroll.css'; import '../Map/CustomScroll.css';
import './Dashboard.css'; import './Dashboard.css';
import Chart from 'chart.js'; import { Chart } from 'chart.js';
import ChartDataLabels from 'chartjs-plugin-datalabels'; import { ChartDataLabels } from 'chartjs-plugin-datalabels';
import ContentLoader from "react-content-loader" import ContentLoader from "react-content-loader"
import LineChart from './LineChart'; import LineChart from './LineChart';
import PieChart from './PieChart'; import PieChart from './PieChart';
@ -20,18 +20,18 @@ import { Pagination, Tooltip, Tree, List, Checkbox } from 'antd';
import { getChildrenTree, formatRupiah, DATE_TIME_FORMAT } from '../../const/CustomFunc.js'; import { getChildrenTree, formatRupiah, DATE_TIME_FORMAT } from '../../const/CustomFunc.js';
import { projectTreeConst } from '../../const/LayerTreeConst.js'; import { projectTreeConst } from '../../const/LayerTreeConst.js';
import { import {
Card, Modal, ModalHeader, ModalBody, ModalFooter, Button, Card, Modal, ModalHeader, ModalBody, ModalFooter, Button,
CardBody, CardHeader, Col, Dropdown, DropdownItem, DropdownMenu, DropdownToggle, Row CardBody, CardHeader, Col, Dropdown, DropdownItem, DropdownMenu, DropdownToggle, Row
} from 'reactstrap'; } from 'reactstrap';
import { import {
DONE_COLOR, IZIN_COLOR, NOT_YET_COLOR, DONE_COLOR, IZIN_COLOR, NOT_YET_COLOR,
PRESENT_COLOR, TOTAL_COLOR, PRESENT_COLOR, TOTAL_COLOR,
RED_COLOR, RED_COLOR,
ORANGE_COLOR, ORANGE_COLOR,
GREEN_COLOR, GREEN_COLOR,
DARK_GREY_COLOR, DARK_GREY_COLOR,
BLUE_COLOR, BLUE_COLOR,
PURPLE_COLOR PURPLE_COLOR
} from '../../const/AppConst.js'; } from '../../const/AppConst.js';
const id_org = window.localStorage.getItem('id_org'); const id_org = window.localStorage.getItem('id_org');
const roleName = window.localStorage.getItem('role_name'); const roleName = window.localStorage.getItem('role_name');
@ -40,269 +40,269 @@ Chart.plugins.register(ChartDataLabels);
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
let menu = [ let menu = [
{ {
"id": 3, "id": 3,
"title": "PANIC BUTTON", "title": "PANIC BUTTON",
"key": "absent", "key": "absent",
"color": IZIN_COLOR "color": IZIN_COLOR
}, },
{ {
"id": 4, "id": 4,
"title": "WASPANG ACTIVE", "title": "WASPANG ACTIVE",
"key": "karyawan telat", "key": "karyawan telat",
"color": GREEN_COLOR "color": GREEN_COLOR
}, },
{ {
"id": 5, "id": 5,
"title": "WASPANG ABSENT", "title": "WASPANG ABSENT",
"key": "karyawan tanpa keterangan", "key": "karyawan tanpa keterangan",
"color": ORANGE_COLOR "color": ORANGE_COLOR
} }
] ]
const defaultPersentaseProyek = { const defaultPersentaseProyek = {
labels: [], labels: [],
datasets: [ datasets: [
{ {
label: 'Progress', label: 'Progress',
data: [], data: [],
fill: false, fill: false,
backgroundColor: 'rgb(54, 162, 235)', backgroundColor: 'rgb(54, 162, 235)',
borderColor: 'rgba(54, 162, 235, 0.2)', borderColor: 'rgba(54, 162, 235, 0.2)',
yAxisID: 'y-axis-1', yAxisID: 'y-axis-1',
}, },
], ],
}; };
const defaultCostProyek = { const defaultCostProyek = {
labels: [], labels: [],
datasets: [ datasets: [
{ {
label: 'Perencanaan', label: 'Perencanaan',
data: [], data: [],
fill: false, fill: false,
backgroundColor: 'rgb(255, 99, 132)', backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgba(255, 99, 132, 0.2)', borderColor: 'rgba(255, 99, 132, 0.2)',
yAxisID: 'y-axis-1', yAxisID: 'y-axis-1',
}, },
{ {
label: 'Realisasi', label: 'Realisasi',
data: [], data: [],
fill: false, fill: false,
backgroundColor: 'rgb(54, 162, 235)', backgroundColor: 'rgb(54, 162, 235)',
borderColor: 'rgba(54, 162, 235, 0.2)', borderColor: 'rgba(54, 162, 235, 0.2)',
yAxisID: 'y-axis-1', yAxisID: 'y-axis-1',
}, },
], ],
}; };
const defaultStatusProyek = { const defaultStatusProyek = {
labels: ['Aman', 'Alert', 'Critical'], labels: ['Aman', 'Alert', 'Critical'],
datasets: [ datasets: [
{ {
label: '# of Votes', label: '# of Votes',
data: [], data: [],
backgroundColor: [ backgroundColor: [
'rgba(54, 162, 235, 0.2)', 'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)', 'rgba(255, 206, 86, 0.2)',
'rgba(255, 99, 132, 0.2)', 'rgba(255, 99, 132, 0.2)',
], ],
borderColor: [ borderColor: [
'rgba(54, 162, 235, 1)', 'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)', 'rgba(255, 206, 86, 1)',
'rgba(255, 99, 132, 1)', 'rgba(255, 99, 132, 1)',
], ],
borderWidth: 1, borderWidth: 1,
}, },
], ],
}; };
const DashboardSimpro = () => { const DashboardSimpro = () => {
const token = localStorage.getItem("token") const token = localStorage.getItem("token")
const HEADER = { const HEADER = {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"Authorization": `Bearer ${token}` "Authorization": `Bearer ${token}`
} }
} }
const [openPlanRealisasi, setopenPlanRealisasi] = useState(false); const [openPlanRealisasi, setopenPlanRealisasi] = useState(false);
const [openCostPlanRealisasi, setopenCostPlanRealisasi] = useState(false); const [openCostPlanRealisasi, setopenCostPlanRealisasi] = useState(false);
const [dataChart, setDataChart] = useState([]); const [dataChart, setDataChart] = useState([]);
const [projectTree, setProjectTree] = useState([]); const [projectTree, setProjectTree] = useState([]);
const [allProyek, setAllProyek] = useState(true); const [allProyek, setAllProyek] = useState(true);
const [dataStatusProyek, setDataStatusProyek] = useState(null); const [dataStatusProyek, setDataStatusProyek] = useState(null);
const [dataPersentaseProyek, setDataPersentaseProyek] = useState(null); const [dataPersentaseProyek, setDataPersentaseProyek] = useState(null);
const [dataCostProyek, setdataCostProyek] = useState(null); const [dataCostProyek, setdataCostProyek] = useState(null);
const [projectTreeVisible, setProjectTreeVisible] = useState(false); const [projectTreeVisible, setProjectTreeVisible] = useState(false);
const [checkedKeysProjectTree, setCheckedKeysProjectTree] = useState([]); const [checkedKeysProjectTree, setCheckedKeysProjectTree] = useState([]);
const [openModalTable, setOpenModalTable] = useState(false); const [openModalTable, setOpenModalTable] = useState(false);
const [dataDashboard, setDataDashboard] = useState(null); const [dataDashboard, setDataDashboard] = useState(null);
const handleGetDataDashboard = async () => { const handleGetDataDashboard = async () => {
const URL = `${BASE_SIMPRO}/dashboard-proyek/search` const URL = `${BASE_SIMPRO}/dashboard-proyek/search`
const payload = { const payload = {
"columns": [ "columns": [
{ "name": "created_at", "logic_operator": "range", "value": "2021-11-06 00:00:00", "value1": "2021-11-06 23:59:59", "operator": "AND" } { "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 } "paging": { "start": 0, "length": -1 }
} }
const result = await axios.post(URL, payload, HEADER).then(res => res).catch(err => err.response) const result = await axios.post(URL, payload, HEADER).then(res => res).catch(err => err.response)
if (result.data.code !== 200) { if (result.data.code !== 200) {
NotificationManager.error('Gaga Menambah Data!!', 'Failed'); NotificationManager.error('Gaga Menambah Data!!', 'Failed');
} }
setDataDashboard(result.data.data); setDataDashboard(result.data.data);
} }
const handleGetDataDashboardChart = async () => { const handleGetDataDashboardChart = async () => {
const URL = `${BASE_SIMPRO}/dashboard-status/search` const URL = `${BASE_SIMPRO}/dashboard-status/search`
let str = '' let str = ''
checkedKeysProjectTree.map((res, idx) => { checkedKeysProjectTree.map((res, idx) => {
if (idx == 0) str += `${res}` if (idx == 0) str += `${res}`
if (idx != 0) str += `,${res}` if (idx != 0) str += `,${res}`
}) })
const payload = { const payload = {
"columns": [ "columns": [
{ "name": "id", "logic_operator": "in", "value": str ? str : "0", "operator": "AND" } { "name": "id", "logic_operator": "in", "value": str ? str : "0", "operator": "AND" }
], ],
"orders": { "columns": ["nama"], "ascending": true } "orders": { "columns": ["nama"], "ascending": true }
} }
const result = await axios.post(URL, payload, HEADER).then(res => res).catch(err => err.response) const result = await axios.post(URL, payload, HEADER).then(res => res).catch(err => err.response)
if (result.data.code !== 200) { if (result.data.code !== 200) {
NotificationManager.error('Gaga Menambah Data!!', 'Failed'); NotificationManager.error('Gaga Menambah Data!!', 'Failed');
} }
const { persentase_progress, progress_cost_planning, progress_cost_realisasi, status_proyek } = result.data.data 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 labelPersentaseProyek = persentase_progress ? persentase_progress.map(res => res.label) : []
const valuePersentaseProyek = persentase_progress ? persentase_progress.map(res => res.total) : [] const valuePersentaseProyek = persentase_progress ? persentase_progress.map(res => res.total) : []
const persentaseProyek = { const persentaseProyek = {
labels: labelPersentaseProyek, labels: labelPersentaseProyek,
datasets: [ datasets: [
{ {
label: 'Progress', label: 'Progress',
data: valuePersentaseProyek, data: valuePersentaseProyek,
fill: false, fill: false,
backgroundColor: 'rgb(54, 162, 235)', backgroundColor: 'rgb(54, 162, 235)',
borderColor: 'rgba(54, 162, 235, 0.2)', borderColor: 'rgba(54, 162, 235, 0.2)',
yAxisID: 'y-axis-1', yAxisID: 'y-axis-1',
}, },
], ],
}; };
setDataPersentaseProyek(persentaseProyek) setDataPersentaseProyek(persentaseProyek)
const labelCostPlaning = progress_cost_planning ? progress_cost_planning.map(res => res.label) : [] 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 valueCostPlaning = progress_cost_planning ? progress_cost_planning.map(res => res.total) : []
const valueCostRealisasi = progress_cost_realisasi ? progress_cost_realisasi.map(res => res.total) : [] const valueCostRealisasi = progress_cost_realisasi ? progress_cost_realisasi.map(res => res.total) : []
const costProyek = { const costProyek = {
labels: labelCostPlaning, labels: labelCostPlaning,
datasets: [ datasets: [
{ {
label: 'Perencanaan', label: 'Perencanaan',
data: valueCostPlaning, data: valueCostPlaning,
fill: false, fill: false,
backgroundColor: 'rgb(255, 99, 132)', backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgba(255, 99, 132, 0.2)', borderColor: 'rgba(255, 99, 132, 0.2)',
yAxisID: 'y-axis-1', yAxisID: 'y-axis-1',
}, },
{ {
label: 'Realisasi', label: 'Realisasi',
data: valueCostRealisasi, data: valueCostRealisasi,
fill: false, fill: false,
backgroundColor: 'rgb(54, 162, 235)', backgroundColor: 'rgb(54, 162, 235)',
borderColor: 'rgba(54, 162, 235, 0.2)', borderColor: 'rgba(54, 162, 235, 0.2)',
yAxisID: 'y-axis-1', yAxisID: 'y-axis-1',
}, },
], ],
}; };
setdataCostProyek(costProyek) setdataCostProyek(costProyek)
const valueStatusProyek = status_proyek ? status_proyek.map(res => res.total) : [] const valueStatusProyek = status_proyek ? status_proyek.map(res => res.total) : []
const statusProyek = { const statusProyek = {
labels: ['Aman', 'Alert', 'Critical'], labels: ['Aman', 'Alert', 'Critical'],
datasets: [ datasets: [
{ {
label: '# of Votes', label: '# of Votes',
data: valueStatusProyek, data: valueStatusProyek,
backgroundColor: [ backgroundColor: [
'rgba(54, 162, 235, 0.2)', 'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)', 'rgba(255, 206, 86, 0.2)',
'rgba(255, 99, 132, 0.2)', 'rgba(255, 99, 132, 0.2)',
], ],
borderColor: [ borderColor: [
'rgba(54, 162, 235, 1)', 'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)', 'rgba(255, 206, 86, 1)',
'rgba(255, 99, 132, 1)', 'rgba(255, 99, 132, 1)',
], ],
borderWidth: 1, borderWidth: 1,
}, },
], ],
}; };
setDataStatusProyek(statusProyek) setDataStatusProyek(statusProyek)
} }
const getProyek = async () => { const getProyek = async () => {
const URL = `${BASE_SIMPRO}/proyek/list?start=0&length=-1&orderby=nama&asc=true` 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) const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
if (result.data.code !== 200) { if (result.data.code !== 200) {
NotificationManager.error('Gaga Menambah Data!!', 'Failed'); NotificationManager.error('Gaga Menambah Data!!', 'Failed');
} }
setProjectTree(result.data.data); setProjectTree(result.data.data);
const arr = result.data.data.map(res => res.id) const arr = result.data.data.map(res => res.id)
setCheckedKeysProjectTree(arr) setCheckedKeysProjectTree(arr)
} }
const renderDailyInfo = () => { const renderDailyInfo = () => {
return ( return (
<> <>
<div className="daily-info-card" style={{ backgroundColor: IZIN_COLOR, cursor: 'pointer' }} > <div className="daily-info-card" style={{ backgroundColor: IZIN_COLOR, cursor: 'pointer' }} >
<p className="number-style1">{dataDashboard ? dataDashboard.panic_button : 0}</p> <p className="number-style1">{dataDashboard ? dataDashboard.panic_button : 0}</p>
<p style={{ color: "#FFFFFF", fontWeight: "bold" }}>PANIC BUTTON</p> <p style={{ color: "#FFFFFF", fontWeight: "bold" }}>PANIC BUTTON</p>
</div> </div>
<div className="daily-info-card" style={{ backgroundColor: GREEN_COLOR, cursor: 'pointer' }} > <div className="daily-info-card" style={{ backgroundColor: GREEN_COLOR, cursor: 'pointer' }} >
<p className="number-style1">{dataDashboard ? dataDashboard.waspang_status.presensi : 0}</p> <p className="number-style1">{dataDashboard ? dataDashboard.waspang_status.presensi : 0}</p>
<p style={{ color: "#FFFFFF", fontWeight: "bold" }}>WASPANG ACTIVE</p> <p style={{ color: "#FFFFFF", fontWeight: "bold" }}>WASPANG ACTIVE</p>
</div> </div>
<div className="daily-info-card" style={{ backgroundColor: ORANGE_COLOR, cursor: 'pointer' }} > <div className="daily-info-card" style={{ backgroundColor: ORANGE_COLOR, cursor: 'pointer' }} >
<p className="number-style1">{dataDashboard ? dataDashboard.waspang_status.absensi : 0}</p> <p className="number-style1">{dataDashboard ? dataDashboard.waspang_status.absensi : 0}</p>
<p style={{ color: "#FFFFFF", fontWeight: "bold" }}>WASPANG ABSENT</p> <p style={{ color: "#FFFFFF", fontWeight: "bold" }}>WASPANG ABSENT</p>
</div> </div>
</> </>
) )
} }
const handleClickChart = param => { const handleClickChart = param => {
if (!param.length) return; if (!param.length) return;
const { _datasetIndex, _index } = param[0]; const { _datasetIndex, _index } = param[0];
const data = dataPersentaseProyek.datasets[_datasetIndex].label const data = dataPersentaseProyek.datasets[_datasetIndex].label
setOpenModalTable(true) setOpenModalTable(true)
} }
const handleClickProyek = id => { const handleClickProyek = id => {
const arr = [...checkedKeysProjectTree] const arr = [...checkedKeysProjectTree]
const idx = arr.indexOf(id) const idx = arr.indexOf(id)
if (idx == -1) { if (idx == -1) {
arr.push(id) arr.push(id)
} else { } else {
arr.splice(idx, 1) arr.splice(idx, 1)
} }
setCheckedKeysProjectTree(arr) setCheckedKeysProjectTree(arr)
} }
return ( return (
<> <>
<SiopasMap /> <SiopasMap />
</> </>
); );
} }
export default DashboardSimpro; export default DashboardSimpro;

121
src/views/Master/ProjectPhase/DialogForm.js

@ -0,0 +1,121 @@
import React, { useEffect, useState } from 'react'
import {
Modal, ModalHeader, ModalBody, ModalFooter,
Button, Form, FormGroup, Label, Input, Col, Row
} from 'reactstrap';
import { DatePicker, Tooltip, Select } from 'antd';
import { formatRupiah, formatNumber } from '../../../const/CustomFunc'
import moment from 'moment';
import 'antd/dist/antd.css';
const { Option } = Select
const DialogForm = ({openDialog, closeDialog, toggleDialog, typeDialog, dataEdit}) => {
const [id, setId] = useState(0)
const [projectType, setProjectType] = useState('')
const [uom, setUom] = useState('')
const [description, setDescription] = useState('')
const [unitPrice, setUnitPrice] = useState()
useEffect(()=> {
if(typeDialog==="Edit"){
console.log("cel data Edit", dataEdit)
setId(dataEdit.id)
setDescription(dataEdit.description)
setUnitPrice(dataEdit.unit_price)
setUom(dataEdit.uom)
setProjectType(dataEdit.name)
}else{
setId(0)
}
},[dataEdit,openDialog])
const handleSave = () => {
let data = '';
if(typeDialog==="Save"){
data = {
name: projectType,
description
}
closeDialog('save', data);
}else{
data = {
id,
name: projectType,
description
}
closeDialog('edit', data);
}
setId(0)
setDescription('')
}
const handleCancel = () => {
closeDialog('cancel', 'none')
setId(0)
setDescription('')
}
const renderForm = () => {
return(
<Form>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Project Type</Label>
<Input type="text" value={projectType} onChange={(e)=> setProjectType(e.target.value)} placeholder={`Input material name...`}/>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Description</Label>
<Input row="4" type="textarea" value={description} onChange={(e)=> setDescription(e.target.value)} placeholder={`Description ...`} />
</FormGroup>
</Col>
</Row>
</Form>
)
}
return (
<>
<Modal size="lg" isOpen={openDialog} toggle={toggleDialog}>
<ModalHeader className="capitalize" toggle={closeDialog}>{typeDialog=="Save" ? `Add` : "Edit"} Resource</ModalHeader>
<ModalBody>
{renderForm()}
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={() => handleSave()}>{typeDialog}</Button>{' '}
<Button className="capitalize" color="secondary" onClick={() => handleCancel()}>Batal</Button>
</ModalFooter>
</Modal>
{/* <DialogMap
openDialog={openDialogMap}
closeDialog={handleCloseDialogMap}
toggleDialog={() => toggleMapDialog}
dataEdit={dataEdit}
workArea_={workArea}
lat_={lat}
lon_={lon}
radius_={radius}
/> */}
</>
)
}
export default DialogForm;

89
src/views/Master/ProjectPhase/DialogFormInitial.js

@ -0,0 +1,89 @@
import React, { useEffect, useState } from 'react'
import {
Modal, ModalHeader, ModalBody, ModalFooter,
Button, Form, FormGroup, Label, Input, Col, Row
} from 'reactstrap';
const DialogForm = ({openDialog, closeDialog, toggleDialog, typeDialog, dataEdit, idActivity, projectTypeId}) => {
const [id, setId] = useState(0)
const [activity, setActivity] = useState('')
useEffect(()=> {
if(typeDialog==="edit"){
setId(dataEdit.id)
setActivity(dataEdit.name_activity)
}else{
setId(0)
setActivity('')
}
},[dataEdit,openDialog])
const handleSave = () => {
let data = '';
if(typeDialog==="add"){
data = {
name_activity: activity,
proyek_type_id:projectTypeId
}
if(idActivity && idActivity > 0){
data['parent_id'] = idActivity
}
console.log("cek cek cek")
closeDialog('save', data);
}else{
data = {
id,
name_activity: activity,
proyek_type_id:projectTypeId
}
if(idActivity && idActivity > 0){
data['parent_id'] = idActivity
}
console.log("cek cek cek 2")
closeDialog('edit', data);
}
setId(0)
setActivity('')
}
const handleCancel = () => {
closeDialog('cancel', 'none')
setId(0)
setActivity('')
}
const renderForm = () => {
return(
<Form>
<FormGroup>
<Label className="capitalize">Activity</Label>
<Input row="4" type="textarea" value={activity} onChange={(e)=> setActivity(e.target.value)} placeholder={`Persiapan ...`} />
</FormGroup>
</Form>
)
}
return (
<>
<Modal isOpen={openDialog} toggle={toggleDialog}>
<ModalHeader className="capitalize" toggle={closeDialog}>{typeDialog=="add" ? `Add` : "Edit"} Activity</ModalHeader>
<ModalBody>
{renderForm()}
</ModalBody>
<ModalFooter>
<Button className='capitalize' color="primary" onClick={() => handleSave()}>{typeDialog}</Button>{' '}
<Button className="capitalize" color="secondary" onClick={() => handleCancel()}>Batal</Button>
</ModalFooter>
</Modal>
</>
)
}
export default DialogForm;

217
src/views/Master/ProjectPhase/DialogInitialGantt.js

@ -0,0 +1,217 @@
import React, { useEffect, useMemo, useState } from 'react'
import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import { Button } from 'reactstrap';
import { Table, Tooltip } from 'antd';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import 'antd/dist/antd.css';
import SweetAlert from 'react-bootstrap-sweetalert';
import { TEMPLATE_GANTT_ADD, TEMPLATE_GANTT_DELETE, TEMPLATE_GANTT_EDIT, TEMPLATE_GANTT_TREE } from '../../../const/ApiConst';
import axios from "../../../const/interceptorApi"
import DialogForm from './DialogFormInitial';
const DialogInitialGantt = ({ openDialog, closeDialog, toggleDialog, idTypeProject }) => {
const token = window.localStorage.getItem('token');
const config = {
headers:
{
Authorization: `Bearer ${token}`,
"Content-type": `application/json`
}
};
const [dataTable, setDataTable] = useState([])
const [alertDelete, setAlertDelete] = useState(false)
const [idDelete, setIdDelete] = useState(0)
const [idActivity, setIdActivity] = useState(0)
const [openDialogForm, setOpenDialogForm] = useState(false)
const [typeDialog, setTypeDialog] = useState("add")
const [dataEdit, setDataEdit] = useState([])
useEffect(() => {
if (idTypeProject && idTypeProject > 0) {
getDataInitial();
}
}, [idTypeProject])
const getDataInitial = async () => {
const url = TEMPLATE_GANTT_TREE(idTypeProject)
const result = await axios
.get(url, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
setDataTable(result.data.data);
} else {
NotificationManager.error('Gagal mengambil data, Silahkan coba lagi!!', 'Failed');
}
}
const handleDelete = async (id) => {
await setIdDelete(id)
await setAlertDelete(true)
}
const onConfirmDelete = async () => {
let url = TEMPLATE_GANTT_DELETE(idDelete);
const result = await axios.delete(url, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code === 200) {
getDataInitial()
setIdDelete(0)
setAlertDelete(false)
NotificationManager.success(`Activity berhasil dihapus!`, 'Success!!');
} else {
setIdDelete(0)
setAlertDelete(false)
NotificationManager.error(`Activity gagal dihapus!}`, 'Failed!!');
}
}
const cancelDelete = () => {
setIdDelete(0)
setAlertDelete(false)
}
const handleAdd = async () => {
setIdActivity(0)
await setTypeDialog("add")
setOpenDialogForm(true)
}
const handleEdit = async (data) => {
await setDataEdit(data)
if (data.parent_id) {
await setIdActivity(data.parent_id);
}
await setTypeDialog("edit")
setOpenDialogForm(true)
}
const handleAddWithParent = async (id) => {
setIdActivity(id)
await setTypeDialog("add")
setOpenDialogForm(true)
}
const closeDialogForm = (type, data) => {
if (type == "save") {
saveActivity(data)
} else if (type == "edit") {
updateActivity(data)
}
setIdActivity(0)
setOpenDialogForm(false)
}
const toggleDialogForm = () => {
if (openDialogForm) {
setIdActivity(0)
}
setOpenDialogForm(!openDialogForm);
}
const saveActivity = async (data) => {
const result = await axios.post(TEMPLATE_GANTT_ADD, data, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code === 200) {
getDataInitial()
NotificationManager.success(`Data activity berhasil ditambah`, 'Success!!');
} else {
NotificationManager.error(`${result.data.message}`, 'Failed!!');
}
}
const updateActivity = async (data) => {
const url = TEMPLATE_GANTT_EDIT(data.id)
const result = await axios.put(url, data, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code === 200) {
getDataInitial()
NotificationManager.success(`Data activity berhasil diedit`, 'Success!!');
} else {
NotificationManager.error(`${result.data.message}`, 'Failed!!');
}
}
const renderTable = useMemo(() => {
const columns = [
{
title: 'Action',
dataIndex: '',
key: 'id',
className: "nowrap",
render: (text, record) =>
<>
<Tooltip title="Delete Activity">
<Button size="small" size={"sm"} color='danger' onClick={() => handleDelete(text.id)}><i className="fa fa-trash"></i></Button>
</Tooltip>{" "}<Tooltip title="Add Activity">
<Button size="small" size={"sm"} color='primary' onClick={() => handleAddWithParent(text.id)}><i className="fa fa-plus"></i></Button>
</Tooltip>{" "}<Tooltip title="Edit Activity">
<Button size="small" size={"sm"} color='warning' onClick={() => handleEdit(text)}><i className="fa fa-edit"></i></Button>
</Tooltip>
</>
,
},
{ title: 'Nama Activity', dataIndex: 'name_activity', key: 'name_activity' },
];
return (
<Table
size="small"
columns={columns}
dataSource={dataTable}
pagination={{ position: ["bottomLeft"] }}
/>
)
}, [dataTable])
return (<>
<NotificationContainer />
<SweetAlert
show={alertDelete}
warning
showCancel
confirmBtnText="Delete"
confirmBtnBsStyle="danger"
title={`Are you sure?`}
onConfirm={onConfirmDelete}
onCancel={cancelDelete}
focusCancelBtn
>
Delete this data
</SweetAlert>
<DialogForm
openDialog={openDialogForm}
closeDialog={closeDialogForm}
toggleDialog={toggleDialogForm}
idActivity={idActivity}
typeDialog={typeDialog}
dataEdit={dataEdit}
projectTypeId={idTypeProject}
/>
<Modal size="lg" isOpen={openDialog} toggle={toggleDialog}>
{/* <ModalHeader className="capitalize" toggle={closeDialog}>Initial Gantt</ModalHeader> */}
<ModalHeader className="capitalize withBtn" toggle={closeDialog} style={{ width: "100%" }}>
<div>Template Gantt</div> <Button onClick={handleAdd} size='sm' color="primary"><i className='fa fa-plus'></i></Button>
</ModalHeader>
<ModalBody>
{renderTable}
</ModalBody>
<ModalFooter>
<Button className="capitalize" color="secondary" onClick={closeDialog}>Close</Button>
</ModalFooter>
</Modal>
</>
)
}
export default DialogInitialGantt;

325
src/views/Master/ProjectPhase/index.js

@ -0,0 +1,325 @@
import * as XLSX from 'xlsx';
import DialogForm from './DialogForm';
import DialogInitialGantt from './DialogInitialGantt';
import React, { useState, useEffect, useMemo } from 'react';
import SweetAlert from 'react-bootstrap-sweetalert';
import axios from "../../../const/interceptorApi"
import moment from 'moment'
import { Card, CardBody, CardHeader, Col, Row, Input } from 'reactstrap';
import { NotificationContainer, NotificationManager } from 'react-notifications';
import { PROJECT_PHASE_ADD, PROJECT_PHASE_EDIT, PROJECT_PHASE_DELETE, PROJECT_PHASE_SEARCH } from '../../../const/ApiConst';
import { Pagination, Button, Tooltip, Table } from 'antd';
const token = window.localStorage.getItem('token');
const config = {
headers:
{
Authorization: `Bearer ${token}`,
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Access-Control-Allow-Origin": `*`
}
};
const ProjectPhase = ({ params }) => {
const token = localStorage.getItem("token")
const HEADER = {
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Access-Control-Allow-Origin": "*",
"Authorization": `Bearer ${token}`
}
}
const pageName = params.name;
const [alertDelete, setAlertDelete] = useState(false)
const [allDataMenu, setAllDataMenu] = useState([])
const [clickOpenModal, setClickOpenModal] = useState(false)
const [currentPage, setCurrentPage] = useState(1)
const [dataEdit, setDataEdit] = useState([])
const [dataTable, setDatatable] = useState([])
const [idDelete, setIdDelete] = useState(0)
const [idPhaseProject, setIdPhaseProject] = useState(0)
const [openDialog, setOpenDialog] = useState(false)
const [openDialogIG, setOpenDialogIG] = useState(false)
const [rowsPerPage, setRowsPerPage] = useState(10)
const [search, setSearch] = useState('')
const [totalPage, setTotalPage] = useState(0)
const [typeDialog, setTypeDialog] = useState('Save')
useEffect(() => {
getDataProjectPhase()
}, [currentPage, rowsPerPage, search])
const getDataProjectPhase = async () => {
let start = 0;
if (currentPage !== 1 && currentPage > 1) {
start = (currentPage * rowsPerPage) - rowsPerPage
}
const payload = {
"columns": [
{
"name": "name",
"logic_operator": "like",
"value": search,
"operator": "AND"
}
],
"orders": {
"ascending": true,
"columns": [
'id'
]
},
"paging": {
"length": rowsPerPage,
"start": start
}
}
const result = await axios
.post(PROJECT_PHASE_SEARCH, payload, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
setDatatable(result.data.data);
setTotalPage(result.data.totalRecord);
} else {
NotificationManager.error('Gagal Mengambil Data!!', 'Failed');
}
}
const handleSearch = e => {
const value = e.target.value
setSearch(value);
setCurrentPage(1)
};
const handleOpenDialog = (type) => {
setOpenDialog(true)
setTypeDialog(type)
}
const handleExportExcel = async () => {
let start = 0;
const payload = {
"paging": { "start": start, "length": -1 },
"columns": [
{ "name": "name", "logic_operator": "ilike", "value": search, "operator": "AND" }
],
"joins": [],
"orders": { "columns": ["id"], "ascending": false }
}
const result = await axios
.post(PROJECT_PHASE_SEARCH, payload)
.then(res => res)
.catch((error) => error.response);
}
const handleEdit = (data) => {
setDataEdit(data)
handleOpenDialog('Edit');
}
const handleDelete = async (id) => {
await setAlertDelete(true)
await setIdDelete(id)
}
const handleCloseDialog = (type, data) => {
if (type === "save") {
saveProjectPhase(data);
} else if (type === "edit") {
editMaterialR(data);
}
setDataEdit([])
setOpenDialog(false)
}
const saveProjectPhase = async (data) => {
const formData = data
const result = await axios.post(PROJECT_PHASE_ADD, formData, HEADER)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code === 200) {
getDataProjectPhase()
NotificationManager.success(`Data project type berhasil ditambah`, 'Success!!');
} else {
NotificationManager.error(`${result.data.message}`, 'Failed!!');
}
}
const editMaterialR = async (data) => {
let urlEdit = PROJECT_PHASE_EDIT(data.id)
const formData = data
const result = await axios.put(urlEdit, formData, HEADER)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code === 200) {
getDataProjectPhase();
NotificationManager.success(`Data project phase berhasil diedit`, 'Success!!');
} else {
NotificationManager.error(`Data project phase gagal di edit`, `Failed!!`);
}
}
const toggleAddDialog = () => {
setOpenDialog(!openDialog)
}
const handleDialogIg = (id) => {
setIdPhaseProject(id)
setOpenDialogIG(true)
}
const closeDialogIG = () => {
setIdPhaseProject(0)
setOpenDialogIG(false)
}
const toggleDialogIG = () => {
if (openDialogIG) {
setIdPhaseProject(0)
}
setOpenDialogIG(!openDialogIG);
}
const onConfirmDelete = async () => {
let url = PROJECT_PHASE_DELETE(idDelete);
const result = await axios.delete(url, config)
.then(res => res)
.catch((error) => error.response);
if (result && result.data && result.data.code === 200) {
getDataProjectPhase()
setIdDelete(0)
setAlertDelete(false)
NotificationManager.success(`Data project phase berhasil dihapus!`, 'Success!!');
} else {
setIdDelete(0)
setAlertDelete(false)
NotificationManager.error(`Data project phase gagal dihapus!}`, 'Failed!!');
}
}
const cancelDelete = () => {
setAlertDelete(false)
setIdDelete(0)
}
const onShowSizeChange = (current, pageSize) => {
setRowsPerPage(pageSize)
}
const onPagination = (current, pageSize) => {
setCurrentPage(current)
}
const dataNotAvailable = () => {
if (dataTable.length === 0) {
return (
<tr>
<td align="center" colSpan="3">Tidak ada data project phase</td>
</tr>
)
}
}
const renderTable = useMemo(() => {
const columns = [
{
title: 'Action',
dataIndex: '',
key: 'x',
className: 'nowrap',
render: (text, record) => <>
<Tooltip title="Delete">
<i className="fa fa-trash" style={{ color: 'red', marginRight: '10px', cursor: "pointer" }} onClick={() => handleDelete(text.id)}></i>
</Tooltip>
<Tooltip title="Edit">
<i className="fa fa-edit" style={{ color: 'green', cursor: "pointer" }} onClick={() => handleEdit(text)}></i>
</Tooltip>{" "}
</>,
},
{ title: 'Fase', dataIndex: 'name', key: 'name', className: "nowrap" },
{ title: 'Warna', dataIndex: 'color', key: 'color' },
];
return (
<Table
rowKey="id"
size="small"
columns={columns}
dataSource={dataTable}
pagination={false}
/>
)
}, [dataTable])
return (
<div>
<NotificationContainer />
<SweetAlert
show={alertDelete}
warning
showCancel
confirmBtnText="Delete"
confirmBtnBsStyle="danger"
title={`Are you sure?`}
onConfirm={onConfirmDelete}
onCancel={() => cancelDelete()}
focusCancelBtn
>
Delete this data
</SweetAlert>
<DialogForm
openDialog={openDialog}
closeDialog={handleCloseDialog}
toggleDialog={() => toggleAddDialog}
typeDialog={typeDialog}
dataEdit={dataEdit}
clickOpenModal={clickOpenModal}
dataParent={allDataMenu}
/>
<DialogInitialGantt
closeDialog={closeDialogIG}
openDialog={openDialogIG}
toggleDialog={toggleDialogIG}
idPhaseProject={idPhaseProject}
/>
<Card>
<CardHeader style={{ display: "flex", justifyContent: "space-between" }}>
<h4 className="capitalize">{pageName}</h4>
<Row>
<Col>
<Tooltip title="Add Material Resource">
<Button style={{ background: "#4caf50", color: "#fff" }} onClick={() => handleOpenDialog('Save')}><i className="fa fa-plus"></i></Button>
</Tooltip>
</Col>
</Row>
</CardHeader>
<CardBody>
{renderTable}
<Pagination
style={{ marginTop: "25px" }}
showSizeChanger
onShowSizeChange={onShowSizeChange}
onChange={onPagination}
defaultCurrent={currentPage}
pageSize={rowsPerPage}
total={totalPage}
pageSizeOptions={["10", "15", "20", "25", "30", "35", "40"]}
/>
</CardBody>
</Card>
</div>
)
}
export default ProjectPhase;

117
src/views/SimproV2/CreatedProyek/DialogFormProyek.js

@ -28,6 +28,7 @@ const DialogFormProyek = ({
toggleDialog, toggleDialog,
idTask, idTask,
dataTypeProyek, dataTypeProyek,
dataPhaseProject,
dataPM, dataPM,
}) => { }) => {
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
@ -43,6 +44,7 @@ const DialogFormProyek = ({
const [description, setDescription] = useState(""); const [description, setDescription] = useState("");
const [biaya, setBiaya] = useState(""); const [biaya, setBiaya] = useState("");
const [typeProject, setTypeproject] = useState(null); const [typeProject, setTypeproject] = useState(null);
const [phaseProject, setPhaseProject] = useState(null);
const [sdm, setSdm] = useState(0); const [sdm, setSdm] = useState(0);
const [pic, setPic] = useState(null); const [pic, setPic] = useState(null);
const [startDate, setStartDate] = useState(moment()); const [startDate, setStartDate] = useState(moment());
@ -68,9 +70,9 @@ const DialogFormProyek = ({
const [approval, setApproval] = useState([]); const [approval, setApproval] = useState([]);
const [testingEnv, setTestingEnv] = useState(""); const [testingEnv, setTestingEnv] = useState("");
const [lastIdxParticipants, setLastIdxParticipants] = useState(0); const [lastIdxParticipants, setLastIdxParticipants] = useState(0);
const [lastIdxMilestones, setLastIdxMilestones] = useState(0); const [lastIdxMilestones, setLastIdxMilestones] = useState(0);
const [lastIdxApproval, setLastIdxApproval] = useState(0); const [lastIdxApproval, setLastIdxApproval] = useState(0);
const handleGetdataIdproyek = async (id) => { const handleGetdataIdproyek = async (id) => {
// const URL = `${BASE_SIMPRO_LUMEN}/project/edit/${id}` // const URL = `${BASE_SIMPRO_LUMEN}/project/edit/${id}`
@ -86,6 +88,7 @@ const DialogFormProyek = ({
setDescription(val.keterangan); setDescription(val.keterangan);
setBiaya(val.rencana_biaya ? formatNumber(val.rencana_biaya) : ""); setBiaya(val.rencana_biaya ? formatNumber(val.rencana_biaya) : "");
setTypeproject(val.type_proyek_id); setTypeproject(val.type_proyek_id);
setPhaseProject(val.phase_id);
setPic(val.pm_id); setPic(val.pm_id);
setStartDate(moment(val.mulai_proyek)); setStartDate(moment(val.mulai_proyek));
setEndDate(moment(val.akhir_proyek)); setEndDate(moment(val.akhir_proyek));
@ -215,6 +218,7 @@ const DialogFormProyek = ({
setShortName(""); setShortName("");
setBiaya(""); setBiaya("");
setTypeproject(null); setTypeproject(null);
setPhaseProject(null);
setPic(null); setPic(null);
setStartDate(moment()); setStartDate(moment());
setEndDate(moment()); setEndDate(moment());
@ -242,10 +246,10 @@ const DialogFormProyek = ({
setStep(1); setStep(1);
}; };
useEffect(() => { useEffect(() => {
if (openDialog) { if (openDialog) {
handleGetDataCurrency(); handleGetDataCurrency();
} }
if (idTask && idTask > 0) { if (idTask && idTask > 0) {
console.log("cel data Edit"); console.log("cel data Edit");
@ -327,6 +331,11 @@ const DialogFormProyek = ({
setTypeproject(val); setTypeproject(val);
}; };
const onChangePhaseProject = (val) => {
setPhaseProject(val);
};
const onChangePm = (val) => { const onChangePm = (val) => {
let data = [...dataPM]; let data = [...dataPM];
var item = data.find((item) => item.id === val); var item = data.find((item) => item.id === val);
@ -404,12 +413,12 @@ const DialogFormProyek = ({
console.log("participants", participants); console.log("participants", participants);
}; };
const handleInputChangeParticipants = (e, index) => { const handleInputChangeParticipants = (e, index) => {
const { name, value } = e.target; const { name, value } = e.target;
const newParticipants = [...participants]; const newParticipants = [...participants];
newParticipants[index][name] = value; newParticipants[index][name] = value;
setParticipants(newParticipants); setParticipants(newParticipants);
}; };
// remove participant from array // remove participant from array
const deleteParticipant = (id) => { const deleteParticipant = (id) => {
@ -440,12 +449,12 @@ const DialogFormProyek = ({
setLastIdxMilestones(lastIdxMilestones + 1); setLastIdxMilestones(lastIdxMilestones + 1);
}; };
const handleInputChangeMilestones = (e, index) => { const handleInputChangeMilestones = (e, index) => {
const { name, value } = e.target; const { name, value } = e.target;
const newMilestones = [...milestones]; const newMilestones = [...milestones];
newMilestones[index][name] = value; newMilestones[index][name] = value;
setMilestones(newMilestones); setMilestones(newMilestones);
}; };
const handleInputChangeMilestonesDate = (date, name, index) => { const handleInputChangeMilestonesDate = (date, name, index) => {
const newMilestones = [...milestones]; const newMilestones = [...milestones];
@ -482,12 +491,12 @@ const DialogFormProyek = ({
setLastIdxApproval(lastIdxApproval + 1); setLastIdxApproval(lastIdxApproval + 1);
}; };
const handleInputChangeApproval = (e, index) => { const handleInputChangeApproval = (e, index) => {
const { name, value } = e.target; const { name, value } = e.target;
const newApproval = [...approval]; const newApproval = [...approval];
newApproval[index][name] = value; newApproval[index][name] = value;
setApproval(newApproval); setApproval(newApproval);
}; };
const handleInputChangeApprovalDate = (date, name, index) => { const handleInputChangeApprovalDate = (date, name, index) => {
const newApproval = [...approval]; const newApproval = [...approval];
@ -682,6 +691,48 @@ const DialogFormProyek = ({
</FormGroup> </FormGroup>
</Col> </Col>
</Row> </Row>
<Row>
<Col md={6}>
<FormGroup>
<Label>Phase</Label>
<Select
showSearch
value={pic}
defaultValue={pic}
onChange={onChangePhaseProject}
style={{ width: "100%" }}
>
{dataPhaseProject.map((res) => (
<Option key={res.id} value={res.id}>
{res.name}
</Option>
))}
</Select>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label>Cost Health</Label>
<Select
showSearch
value={pic}
defaultValue={pic}
onChange={onChangePm}
style={{ width: "100%" }}
>
<Option key="on-budget" value="on-budget">
On budget
</Option>
<Option key="warning" value="warning">
Warning
</Option>
<Option key="danger" value="danger">
Danger
</Option>
</Select>
</FormGroup>
</Col>
</Row>
<Row> <Row>
<Col md={12}> <Col md={12}>
<div>Notes:</div> <div>Notes:</div>
@ -1062,15 +1113,15 @@ const DialogFormProyek = ({
</Button> </Button>
</> </>
) : ( ) : (
<> <>
<Button color="primary" onClick={() => previousStep()}> <Button color="primary" onClick={() => previousStep()}>
<i className="fa fa-chevron-left"></i> Previous <i className="fa fa-chevron-left"></i> Previous
</Button>{" "} </Button>{" "}
<Button color="success" onClick={() => handleSave()}> <Button color="success" onClick={() => handleSave()}>
{idTask ? `Save` : "Add"} {idTask ? `Save` : "Add"}
</Button> </Button>
</> </>
)} )}
</ModalFooter> </ModalFooter>
</Modal> </Modal>
</> </>

23
src/views/SimproV2/CreatedProyek/index.js

@ -50,6 +50,7 @@ import {
PROJECT_APPROVAL_SEARCH, PROJECT_APPROVAL_SEARCH,
CHECKLIST_K3_LIST, CHECKLIST_K3_LIST,
VERSION_GANTT_SEARCH, VERSION_GANTT_SEARCH,
PHASE_PROYEK,
} from "../../../const/ApiConst"; } from "../../../const/ApiConst";
import { import {
formatNumber, formatNumber,
@ -112,6 +113,7 @@ const CreatedProyek = ({ params, ...props }) => {
const [materialResource, setMaterialResource] = useState([]); const [materialResource, setMaterialResource] = useState([]);
const [toolsResource, setToolsResource] = useState([]); const [toolsResource, setToolsResource] = useState([]);
const [dataTypeProyek, setDataTypeProyek] = useState([]); const [dataTypeProyek, setDataTypeProyek] = useState([]);
const [dataPhaseProject, setDataPhaseProject] = useState([]);
const [dataPm, setDataPM] = useState([]); const [dataPm, setDataPM] = useState([]);
const [openDialogDoc, setOpenDialogDoc] = useState(false); const [openDialogDoc, setOpenDialogDoc] = useState(false);
const [proyekName, setProyekName] = useState(""); const [proyekName, setProyekName] = useState("");
@ -132,6 +134,7 @@ const CreatedProyek = ({ params, ...props }) => {
getDataMaterialResource(); getDataMaterialResource();
getDataToolsResource(); getDataToolsResource();
handleGetTipeProject(); handleGetTipeProject();
handleGetPhaseProject();
handleGetDataPm(); handleGetDataPm();
getDataK3(); getDataK3();
}, []); }, []);
@ -170,6 +173,18 @@ const CreatedProyek = ({ params, ...props }) => {
} }
}; };
const handleGetPhaseProject = async () => {
const result = await axios
.get(PHASE_PROYEK, HEADER)
.then((res) => res)
.catch((err) => err.response);
console.log("PHASEEEE", result);
if (result && result.data && result.data.code === 200) {
setDataPhaseProject(result.data.data);
}
};
const handleGetDataPm = async () => { const handleGetDataPm = async () => {
const result = await axios const result = await axios
.get(USER_LIST, HEADER) .get(USER_LIST, HEADER)
@ -1120,6 +1135,7 @@ const CreatedProyek = ({ params, ...props }) => {
toggleDialog={() => toggleAddDialog} toggleDialog={() => toggleAddDialog}
idTask={idTask} idTask={idTask}
dataTypeProyek={dataTypeProyek} dataTypeProyek={dataTypeProyek}
dataPhaseProject={dataPhaseProject}
dataPM={dataPm} dataPM={dataPm}
/> />
), ),
@ -1134,6 +1150,7 @@ const CreatedProyek = ({ params, ...props }) => {
toggleDialog={() => toggleAddDialogProyek} toggleDialog={() => toggleAddDialogProyek}
idTask={idTask} idTask={idTask}
dataTypeProyek={dataTypeProyek} dataTypeProyek={dataTypeProyek}
dataPhaseProject={dataPhaseProject}
dataPM={dataPm} dataPM={dataPm}
/> />
), ),
@ -1326,12 +1343,12 @@ const CreatedProyek = ({ params, ...props }) => {
</Button> </Button>
</> </>
} }
// visible={visible} // visible={visible}
// onVisibleChange={handleVisibleChange} // onVisibleChange={handleVisibleChange}
> >
<Button <Button
style={{ marginLeft: "5px" }} style={{ marginLeft: "5px" }}
// onClick={() => handleExportExcel()} // onClick={() => handleExportExcel()}
> >
<i className="fa fa-print"></i> <i className="fa fa-print"></i>
</Button> </Button>

Loading…
Cancel
Save