Browse Source

progress

pull/2/head
Yusuf 2 years ago
parent
commit
e98437b215
  1. 14
      src/App.js
  2. 8
      src/const/ApiConst.js
  3. 5
      src/containers/DefaultLayout/DefaultHeader.js
  4. 5
      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. 289
      src/views/DashboardPMOV1/index.js
  10. 36
      src/views/DashboardPMOV1/projectPhaseChart.js
  11. 2
      src/views/DashboardPMOV1/tableDashboard.js
  12. 42
      src/views/DashboardPMOV1/tableDashboardv1.js
  13. 6
      src/views/DashboardProject/index.js
  14. 4
      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. 51
      src/views/SimproV2/CreatedProyek/DialogFormProyek.js
  20. 17
      src/views/SimproV2/CreatedProyek/index.js

14
src/App.js

@ -21,16 +21,16 @@ class App extends Component {
<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>

8
src/const/ApiConst.js

@ -122,7 +122,7 @@ switch (APP_MODE) {
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`;
@ -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:

5
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,9 +212,11 @@ class DefaultLayout extends Component {
}); });
} }
else { else {
if (!window.location.href.includes("dashboard")){
return <AppBreadcrumb appRoutes={this.state.finalRoutes} router={router} /> return <AppBreadcrumb appRoutes={this.state.finalRoutes} router={router} />
} }
} }
}
isKominfo = () => { isKominfo = () => {
let u_group = localStorage.getItem('u_group'); let u_group = localStorage.getItem('u_group');

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} />;
}

289
src/views/DashboardPMOV1/index.js

@ -1,40 +1,66 @@
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'> <>
<div style={{ backgroundColor: bgColor }} class='box-dashboard-pm'>
<Row> <Row>
<Col span={7}> <Col span={4}>
<div className='box-icon'> <div class='box-icon'>
{icon} {icon}
</div> </div>
</Col> </Col>
<Col span={17}> <Col span={20}>
<div className='box-content'> <div class='box-content'>
<div style={{ fontSize: '1.4rem' }} className='text-box'>{value}</div> <div style={{ fontSize: '1.0rem' }} class='text-box'>{value}</div>
<div style={{ fontSize: '0.7rem' }} className='text-box'>{title.toUpperCase()}</div> <div style={{ fontSize: '0.7rem' }} class='text-box'>{title.toUpperCase()}</div>
<div style={{ fontSize: '0.6rem' }} className='text-box-secondary'>{secondaryTitle && secondaryTitle.toUpperCase()}</div> <div style={{ fontSize: '0.6rem' }} class='text-box-secondary'>{secondaryTitle && secondaryTitle.toUpperCase()}</div>
</div> </div>
</Col> </Col>
</Row> </Row>
</div> </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 = {
@ -44,156 +70,137 @@ const DashbaoardPM = () => {
} }
} }
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> <div>
<Row> <Row
<Col span={4}><h6 style={{ textAlign: 'center' }}>PORTOFOLIO DASHBOARD</h6></Col> gutter={{
{/* <Col span={5}> xs: 8,
<Select sm: 16,
style={{ width: '100%', padding: '0 5px' }} md: 24,
showSearch lg: 32,
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> <Col span={6} style={{ margin: '' }}>
<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' }}>
<Collapse>
<Panel key="1">
<Row style={{ margin: '15px 10px 0px 0px' }}>
<Col span={8} >
<Row
gutter={{
xs: 8,
sm: 16,
md: 24,
lg: 32,
}}
>
<Col span={12}> <Col span={12}>
<BarChart /> <BoxDashboardNoIcon
value="-"
bgColor="#077857"
title="Active / Standby"
/>
</Col> </Col>
<Col span={12}> <Col span={12}>
<DoughnutChart /> <BoxDashboardNoIcon
value="-"
bgColor="#077857"
title="Need Maintenance"
/>
</Col> </Col>
</Row> </Row>
</div> <Row
<div style={{ paddingLeft: 5, }}> 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 /> <TableDashboardV1 />
</div>
</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',

42
src/views/DashboardPMOV1/tableDashboardv1.js

@ -1,35 +1,20 @@
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}`,
} }
} }
@ -37,12 +22,11 @@ const TableDashboardV1 = () => {
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) {
}
// console.log("res ", result.data.data)
setDataTable(result.data.data); setDataTable(result.data.data);
} }
}
const columns = [ const columns = [
{ {
@ -60,28 +44,28 @@ 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>
@ -92,6 +76,9 @@ const TableDashboardV1 = () => {
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>
}
}, },
]; ];
@ -108,7 +95,6 @@ const TableDashboardV1 = () => {
</Col> </Col>
</Row> </Row>
</> </>
); );
} }

6
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>
) )
} }
@ -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>

4
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';

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;

51
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());
@ -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());
@ -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);
@ -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>

17
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}
/> />
), ),

Loading…
Cancel
Save