Browse Source

dashboard project types & project-phase

pull/2/head
Yusuf 2 years ago
parent
commit
a69c0df10d
  1. 1
      package.json
  2. 33
      src/scss/_custom.scss
  3. 56
      src/views/DashboardPMOV1/chartDashboard.js
  4. 7
      src/views/DashboardPMOV1/index.js
  5. 141
      src/views/Master/ProjectPhase/DialogForm.js
  6. 217
      src/views/Master/ProjectPhase/DialogInitialGantt.js
  7. 46
      src/views/Master/ProjectPhase/InputColor.js
  8. 42
      src/views/Master/ProjectPhase/index.js
  9. 41
      src/views/Master/ProjectPhase/styles.css

1
package.json

@ -54,6 +54,7 @@
"numeral": "^2.0.6",
"ol": "^5.3.3",
"prop-types": "^15.7.2",
"rc-color-picker": "^1.2.6",
"react": "^16.14.0",
"react-app-polyfill": "^1.0.1",
"react-awesome-query-builder": "^4.3.0",

33
src/scss/_custom.scss

@ -127,3 +127,36 @@
.chat-body {
padding: 6px 10px
}
.rc-color-picker-panel {
border: 1px solid #ccc;
}
.rc-color-picker-panel-inner {
border: none;
box-shadow: none;
}
.rc-color-picker-panel-board-hsv {
border-radius: 12px;
outline: none;
}
.rc-color-picker-panel-board-value {
border: none;
border-radius: 12px;
}
.rc-color-picker-panel-board-saturation {
border: none;
border-radius: 12px;
}
.rc-color-picker-panel-ribbon {
border-radius: 12px;
}
.rc-color-picker-panel-wrap-preview {
border-radius: 12px;
}
.rc-color-picker-panel-preview span {
border-radius: 12px;
}
.rc-color-picker-panel-preview input {
border-radius: 12px;
}

56
src/views/DashboardPMOV1/chartDashboard.js

@ -1,6 +1,5 @@
import React from 'react';
import { Doughnut } from 'react-chartjs-2';
import { faker } from '@faker-js/faker';
const options = {
title: {
@ -9,30 +8,37 @@ const options = {
},
};
const data = {
labels: ['Pengadaan Barang dan Jasa','Kontruksi', 'FTTH'],
datasets: [
{
label: '# of Votes',
data: [1, 1, 2],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
],
borderWidth: 1,
},
],
};
export const ProjectTypeChart = ({ projectTypes, projectsByType }) => {
let total = []
for (var j = 0; j < projectTypes.length; j++) {
total.push(projectsByType[j].total)
}
let dataSets = [{
label: "#",
data: total,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
],
borderWidth: 1,
}]
const data = {
labels: projectTypes,
datasets: dataSets,
};
export const ProjectTypeChart = () => {
return <Doughnut data={data} options={options} />;
}

7
src/views/DashboardPMOV1/index.js

@ -64,6 +64,9 @@ const DashboardPM = () => {
const [PROJECTPHASES, SET_PROJECTPHASES] = useState([])
const [PROJECTSBYPHASE, SET_PROJECTSBYPHASE] = useState([])
const [PROJECTTYPES, SET_PROJECTTYPES] = useState([])
const [PROJECTSBYTYPE, SET_PROJECTSBYTYPE] = useState([])
const token = localStorage.getItem("token")
const HEADER = {
headers: {
@ -83,6 +86,8 @@ const DashboardPM = () => {
result.data.manpowers != undefined ? SET_MANPOWERS(result.data.manpowers) : SET_MANPOWERS(0)
result.data.projectPhases != undefined ? SET_PROJECTPHASES(result.data.projectPhases) : SET_PROJECTPHASES([])
result.data.projectsByPhase != undefined ? SET_PROJECTSBYPHASE(result.data.projectsByPhase) : SET_PROJECTSBYPHASE([])
result.data.projectTypes != undefined ? SET_PROJECTTYPES(result.data.projectTypes) : SET_PROJECTTYPES([])
result.data.projectsByType != undefined ? SET_PROJECTSBYTYPE(result.data.projectsByType) : SET_PROJECTSBYTYPE([])
}
@ -205,7 +210,7 @@ const DashboardPM = () => {
<ProjectPhaseChart projectPhases={PROJECTPHASES} projectsByPhase={PROJECTSBYPHASE} />
</Col>
<Col span={8}>
<ProjectTypeChart />
<ProjectTypeChart projectTypes={PROJECTTYPES} projectsByType={PROJECTSBYTYPE} />
</Col>
</Row>
</Panel>

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

@ -1,121 +1,90 @@
import React, { useEffect, useState } from 'react'
import {
Modal, ModalHeader, ModalBody, ModalFooter,
Button, Form, FormGroup, Label, Input, Col, Row
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
import InputColor from "./InputColor";
import "./styles.css";
import "rc-color-picker/assets/index.css";
const DialogForm = ({openDialog, closeDialog, toggleDialog, typeDialog, dataEdit}) => {
const [id, setId] = useState(0)
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()
const [color, setColor] = useState('')
useEffect(()=> {
if(typeDialog==="Edit"){
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{
setColor(dataEdit.color)
} else {
setId(0)
setColor('')
setProjectType('')
}
},[dataEdit,openDialog])
}, [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);
let data = '';
if (typeDialog === "Save") {
data = {
name: projectType,
color
}
setId(0)
setDescription('')
closeDialog('save', data);
} else {
data = {
id,
name: projectType,
color
}
closeDialog('edit', data);
}
setId(0)
}
const handleCancel = () => {
closeDialog('cancel', 'none')
setId(0)
setDescription('')
}
const renderForm = () => {
return(
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>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Phase</Label>
<Input type="text" value={projectType} onChange={(e) => setProjectType(e.target.value)} />
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Warna</Label>
<InputColor value={color} onChange={(e) => setColor(e.color)} />
</FormGroup>
</Col>
</Row>
</Form>
)
}
return (
<>
<Modal size="lg" isOpen={openDialog} toggle={toggleDialog}>
<ModalHeader className="capitalize" toggle={closeDialog}>{typeDialog=="Save" ? `Add` : "Edit"} Resource</ModalHeader>
<ModalBody>
<Modal size="lg" isOpen={openDialog} toggle={toggleDialog}>
<ModalHeader className="capitalize" toggle={closeDialog}>{typeDialog == "Save" ? `Add` : "Edit"} data</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}
/> */}
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={() => handleSave()}>{typeDialog}</Button>{' '}
<Button className="capitalize" color="secondary" onClick={() => handleCancel()}>Batal</Button>
</ModalFooter>
</Modal>
</>
)
}
export default DialogForm;
export default DialogForm;

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

@ -1,217 +0,0 @@
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;

46
src/views/Master/ProjectPhase/InputColor.js

@ -0,0 +1,46 @@
import React from "react";
import Input from "antd/lib/input";
import Button from "antd/lib/button";
import Dropdown from "antd/lib/dropdown";
import { Panel } from 'rc-color-picker'
import "antd/dist/antd.css";
import "./styles.css";
export default function InputColor(props) {
const { color, onChange } = props;
const [internalColor, setInternalColor] = React.useState(color);
const handleChange = (color) => {
setInternalColor(color.color);
if (onChange) {
onChange(color);
}
};
const overlay = (
<div>
<Panel
color={internalColor}
enableAlpha={false}
onChange={handleChange}
/>
</div>
);
return (
<>
<Input
value={internalColor || ""}
onChange={(e) => setInternalColor(e.target.value)}
suffix={
<Dropdown trigger={["click"]} overlay={overlay}>
<Button style={{ background: internalColor }}> </Button>
</Dropdown>
}
/>
</>
);
}

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

@ -1,13 +1,12 @@
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 { PROJECT_PHASE_ADD, PROJECT_PHASE_EDIT, PROJECT_PHASE_DELETE, PROJECT_PHASE_SEARCH, BASE_OSPRO } from '../../../const/ApiConst';
import { Pagination, Button, Tooltip, Table } from 'antd';
const token = window.localStorage.getItem('token');
@ -16,18 +15,23 @@ const config = {
{
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 = {
/*const HEADER = {
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Access-Control-Allow-Origin": "*",
"Authorization": `Bearer ${token}`
}
}*/
const HEADER = {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}
}
const pageName = params.name;
@ -77,10 +81,15 @@ const ProjectPhase = ({ params }) => {
}
}
const result = await axios
/*const result = await axios
.post(PROJECT_PHASE_SEARCH, payload, config)
.then(res => res)
.catch((error) => error.response);
.catch((error) => error.response);*/
//const result = await axios.post(PROJECT_PHASE_SEARCH, payload, HEADER).then(res => res).catch(err => err.response)
const URL = `${BASE_OSPRO}/api/project-phase/list`
const result = await axios.get(URL, HEADER).then(res => res).catch(err => err.response)
console.log(result)
if (result && result.data && result.data.code == 200) {
setDatatable(result.data.data);
@ -249,7 +258,16 @@ const ProjectPhase = ({ params }) => {
</>,
},
{ title: 'Fase', dataIndex: 'name', key: 'name', className: "nowrap" },
{ title: 'Warna', dataIndex: 'color', key: 'color' },
{
title: 'Warna',
dataIndex: 'color',
key: 'color',
render: (text) => <>
<Tooltip title={text}>
<i className="fa fa-square" style={{ color: text }} ></i>
</Tooltip>
</>,
},
];
return (
<Table
@ -277,7 +295,7 @@ const ProjectPhase = ({ params }) => {
focusCancelBtn
>
Delete this data
</SweetAlert>
</SweetAlert>
<DialogForm
openDialog={openDialog}
closeDialog={handleCloseDialog}
@ -287,18 +305,12 @@ const ProjectPhase = ({ params }) => {
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">
<Tooltip title="Add new data">
<Button style={{ background: "#4caf50", color: "#fff" }} onClick={() => handleOpenDialog('Save')}><i className="fa fa-plus"></i></Button>
</Tooltip>
</Col>

41
src/views/Master/ProjectPhase/styles.css

@ -0,0 +1,41 @@
.App {
font-family: sans-serif;
padding: 20px;
}
h2 {
margin-top: 40px;
}
.rc-color-picker-panel {
border: 1px solid #ccc;
}
.rc-color-picker-panel-inner {
border: none;
box-shadow: none;
}
.rc-color-picker-panel-board-hsv {
border-radius: 12px;
outline: none;
}
.rc-color-picker-panel-board-value {
border: none;
border-radius: 12px;
}
.rc-color-picker-panel-board-saturation {
border: none;
border-radius: 12px;
}
.rc-color-picker-panel-ribbon {
border-radius: 12px;
}
.rc-color-picker-panel-wrap-preview {
border-radius: 12px;
}
.rc-color-picker-panel-preview span {
border-radius: 12px;
}
.rc-color-picker-panel-preview input {
border-radius: 12px;
}
Loading…
Cancel
Save