Browse Source

update CRUD in project charter and add dependencies CKEditor 5

pull/2/head
wahyuun 1 year ago
parent
commit
53eb2b0a1e
  1. 2
      package.json
  2. 6
      src/const/ApiConst.js
  3. 604
      src/views/SimproV2/CreatedProyek/DialogFormProyek.js
  4. 80
      src/views/SimproV2/CreatedProyek/ViewProject.js
  5. 82
      src/views/SimproV2/CreatedProyek/index.js

2
package.json

@ -13,6 +13,8 @@
},
"dependencies": {
"@ant-design/plots": "^1.1.1",
"@ckeditor/ckeditor5-build-classic": "^39.0.2",
"@ckeditor/ckeditor5-react": "^6.1.0",
"@coreui/coreui": "^2.1.12",
"@coreui/icons": "0.3.0",
"@coreui/react": "^2.5.1",

6
src/const/ApiConst.js

@ -677,3 +677,9 @@ export const HIERARCHY_FTTH_TREE = (id) => {
return `${BASE_SIMPRO_LUMEN}/hierarchy-ftths/tree/${id}`;
};
export const WAYPOINT_SEARCH = `${BASE_SIMPRO_LUMEN}/waypoint/search`;
export const IMAGE_UPLOAD = `${BASE_SIMPRO_LUMEN}/image/upload`;
export const IMAGE_DELETE = (id, category) => {
return `${BASE_SIMPRO_LUMEN}/image/delete/${id}/${category}`;
}

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

@ -4,6 +4,8 @@ import { Button, Form, FormGroup, Label, Input, Col, Row } from "reactstrap";
import { DatePicker, Tooltip, Select, Divider } from "antd";
import axios from "../../../const/interceptorApi";
import moment from "moment";
import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import {
NotificationContainer,
NotificationManager,
@ -29,11 +31,12 @@ const DialogFormProyek = ({
dataPhaseProject,
dataDivisions,
dataPM,
projectImage
}) => {
const token = localStorage.getItem("token");
const HEADER = {
headers: {
"Content-Type": "application/json",
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
};
@ -41,6 +44,8 @@ const DialogFormProyek = ({
const [name, setName] = useState("");
const [shortName, setShortName] = useState("");
const [description, setDescription] = useState("");
const [late, setLateConsequence] = useState("");
const [assumtion, setAssumtion] = useState("");
const [biaya, setBiaya] = useState("");
const [typeProject, setTypeproject] = useState(null);
const [phaseProject, setPhaseProject] = useState(null);
@ -51,6 +56,8 @@ const DialogFormProyek = ({
const [startDate, setStartDate] = useState(moment());
const [endDate, setEndDate] = useState(moment());
const [workArea, setWorkArea] = useState("");
const [duration, setProjectDuration] = useState("");
const [organization, setProjectStructureOrg] = useState(null);
const [finance, setFinance] = useState("");
const [investor, setInvestor] = useState("");
const [company, setCompany] = useState("");
@ -63,6 +70,7 @@ const DialogFormProyek = ({
const [objectives, setObjectives] = useState("");
const [projectIsConsideredSuccessful, setProjectIsConsideredSuccessful] = useState("");
const [participants, setParticipants] = useState([]);
const [image, setImage] = useState("")
const [availableResources, setAvailableResources] = useState("");
const [milestones, setMilestones] = useState([]);
const [potentialRisks, setPotentialRisks] = useState("");
@ -83,6 +91,8 @@ const DialogFormProyek = ({
setName(val.nama);
setShortName(val.kode_sortname);
setDescription(val.keterangan);
setLateConsequence(val.late_consequence ? val.late_consequence : "");
setAssumtion(val.assumtion ? val.assumtion : "");
setBiaya(val.rencana_biaya ? formatNumber(val.rencana_biaya) : "");
setTypeproject(val.type_proyek_id);
setPhaseProject(val.phase_id);
@ -92,6 +102,7 @@ const DialogFormProyek = ({
setStartDate(moment(val.mulai_proyek));
setEndDate(moment(val.akhir_proyek));
setWorkArea(val.area_kerja);
setProjectDuration(val.durasi_proyek);
setInvestor(val.investor);
setCompany(val.company);
setFinance(val.finance);
@ -152,15 +163,20 @@ const DialogFormProyek = ({
setStartDate(moment());
setEndDate(moment());
setDescription("");
setLateConsequence("");
setAssumtion("");
setInvestor("");
setFinance("");
setWorkArea("");
setProjectDuration("");
setProjectStructureOrg(null);
setCompany("");
setCurrency("");
setCurrencyCode("");
setCurrencySymbol(null);
setCurrencyName("");
setObjectives("");
setImage("");
setProjectIsConsideredSuccessful("");
setParticipants([]);
setAvailableResources("");
@ -189,7 +205,7 @@ const DialogFormProyek = ({
}
}, [openDialog]);
const handleSave = () => {
const handleSave = () => {
let data = "";
if (idTask) {
data = {
@ -208,6 +224,9 @@ const DialogFormProyek = ({
finance,
company,
area_kerja: workArea,
durasi_proyek: parseInt(duration),
late_consequence: late,
assumtion: assumtion,
keterangan: description,
project_objectives: objectives,
considered_success_when: projectIsConsideredSuccessful,
@ -218,6 +237,7 @@ const DialogFormProyek = ({
currency_name: currencyName,
};
data.projectCharter = { participants, milestones, approval };
data.imageStructureOrg = organization ? organization : null;
closeDialog("edit", data);
} else {
data = {
@ -235,17 +255,22 @@ const DialogFormProyek = ({
finance,
company,
area_kerja: workArea,
durasi_proyek: parseInt(duration),
late_consequence: late,
assumtion: assumtion,
keterangan: description,
project_objectives: objectives,
considered_success_when: projectIsConsideredSuccessful,
potential_risk: potentialRisks,
potential_risk: potentialRisks,
testing_environment: testingEnv,
currency_symbol: currencySymbol,
currency_code: currencyCode,
currency_name: currencyName,
};
data.projectCharter = { participants, milestones, approval };
closeDialog("add", data);
data.projectCharter = { participants, milestones, approval };
data.imageStructureOrg = organization ? organization : null;
closeDialog("add", data);
}
handleClearData();
};
@ -324,6 +349,10 @@ const DialogFormProyek = ({
alert("Budget cannot be empty!");
return false;
}
if (!currencySymbol || currencySymbol === "") {
alert("Currency Symbol cannot be empty!");
return false;
}
setStep(2);
};
@ -425,251 +454,303 @@ const DialogFormProyek = ({
}
}
};
const editorConfig = {
height: '900px'
};
const renderForm = () => {
return (
<Form>
<Row>
<Col md={12}>
<span style={{ color: "red" }}>*</span> Wajib diisi.
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">
Project Name<span style={{ color: "red" }}>*</span>
</Label>
<Input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Code / Short Name<span style={{ color: "red" }}>*</span></Label>
<Input
type="text"
value={shortName}
onChange={(e) => setShortName(e.target.value)}
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">
Project Type<span style={{ color: "red" }}>*</span>
</Label>
<Select
showSearch
filterOption={(inputValue, option) =>
option.children.toLowerCase().includes(inputValue.toLowerCase())
}
value={typeProject}
defaultValue={typeProject}
onChange={onChangeTypeProject}
style={{ width: "100%" }}
>
{dataTypeProyek.map((res) => (
<Option key={res.id} value={res.id}>
{res.name}
</Option>
))}
</Select>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">PM</Label>
<Select
showSearch
filterOption={(inputValue, option) =>
option.children.toLowerCase().includes(inputValue.toLowerCase())
}
value={pic}
defaultValue={pic}
onChange={onChangePm}
style={{ width: "100%" }}
>
{dataPM.map((res) => (
<Option key={res.id} value={res.id}>
{res.name}
</Option>
))}
</Select>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">
Start Date<span style={{ color: "red" }}>*</span>
</Label>
<DatePicker
format={"DD-MM-YYYY"}
style={{ width: "100%" }}
value={startDate}
onChange={handleDatePickerStart}
/>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">
End Date<span style={{ color: "red" }}>*</span>
</Label>
<DatePicker
disabledDate={(current) => {
let currentDate = moment(current).format("YYYY-MM-DD");
let customDate = moment(startDate)
.add(1, "days")
.format("YYYY-MM-DD");
return current && currentDate < customDate;
}}
format={"DD-MM-YYYY"}
style={{ width: "100%" }}
value={endDate}
onChange={handleDatePickerEnd}
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Work Area</Label>
<Input
type="text"
value={workArea}
onChange={(e) => setWorkArea(e.target.value)}
/>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Company</Label>
<Input
type="text"
value={company}
onChange={(e) => setCompany(e.target.value)}
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">
Budget<span style={{ color: "red" }}>*</span>
</Label>
<Row>
<Col md={4}>
<Select
value={currencySymbol}
onChange={onChangeCurrency}
defaultValue="IDR|Rp|Indonesian rupiah"
style={{ width: "100%" }}
>
{currencyList && currencyList.map(res => (
<Option key={res.id} value={`${res.cc}|${res.symbol}|${res.name}`}>{`${res.cc}`}</Option>
))}
</Select>
</Col>
<Col md={8}>
<Input
type="text"
value={biaya}
onChange={(e) => setBiaya(formatNumber(e.target.value))}
/>
</Col>
</Row>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Description</Label>
<Input
type="textarea"
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label>Handled By Division</Label>
<Select
value={divisiProject}
defaultValue={divisiProject}
onChange={onChangeDivisiProject}
style={{ width: "100%" }}
>
{dataDivisions.map((res) => (
<Option key={res.id} value={res.id}>
{res.displayName}
</Option>
))}
</Select>
</FormGroup>
</Col>
</Row>
<Divider orientation="left" plain>
Info Dashboard
</Divider>
<Row>
<Col md={6}>
<FormGroup>
<Label>Phase</Label>
<Select
value={phaseProject}
defaultValue={phaseProject}
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
value={budgetHealth}
defaultValue={budgetHealth}
onChange={onChangeBudgetHealth}
style={{ width: "100%" }}
>
<Option key="on-budget" value="on-budget">
On budget
</Option>
<Option key="warning" value="warning">
Warning
</Option>
<Option key="overrun" value="overrun">
Overrun
</Option>
</Select>
</FormGroup>
</Col>
</Row>
</Form>
);
};
const RenderFormProject = () => {
return (
<>
<Form style={{ display: step === 1 ? 'block' : 'none' }}>
<Row>
<Col md={12}>
<span style={{ color: "red" }}>*</span> Wajib diisi.
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">
Project Name<span style={{ color: "red" }}>*</span>
</Label>
<Input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Code / Short Name<span style={{ color: "red" }}>*</span></Label>
<Input
type="text"
value={shortName}
onChange={(e) => setShortName(e.target.value)}
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">
Project Type<span style={{ color: "red" }}>*</span>
</Label>
<Select
showSearch
filterOption={(inputValue, option) =>
option.children.toLowerCase().includes(inputValue.toLowerCase())
}
value={typeProject}
defaultValue={typeProject}
onChange={onChangeTypeProject}
style={{ width: "100%" }}
>
{dataTypeProyek.map((res) => (
<Option key={res.id} value={res.id}>
{res.name}
</Option>
))}
</Select>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">PM</Label>
<Select
showSearch
filterOption={(inputValue, option) =>
option.children.toLowerCase().includes(inputValue.toLowerCase())
}
value={pic}
defaultValue={pic}
onChange={onChangePm}
style={{ width: "100%" }}
>
{dataPM.map((res) => (
<Option key={res.id} value={res.id}>
{res.name}
</Option>
))}
</Select>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">
Start Date<span style={{ color: "red" }}>*</span>
</Label>
<DatePicker
format={"DD-MM-YYYY"}
style={{ width: "100%" }}
value={startDate}
onChange={handleDatePickerStart}
/>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">
End Date<span style={{ color: "red" }}>*</span>
</Label>
<DatePicker
disabledDate={(current) => {
let currentDate = moment(current).format("YYYY-MM-DD");
let customDate = moment(startDate)
.add(1, "days")
.format("YYYY-MM-DD");
return current && currentDate < customDate;
}}
format={"DD-MM-YYYY"}
style={{ width: "100%" }}
value={endDate}
onChange={handleDatePickerEnd}
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Work Area</Label>
<Input
type="text"
value={workArea}
onChange={(e) => setWorkArea(e.target.value)}
/>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Company</Label>
<Input
type="text"
value={company}
onChange={(e) => setCompany(e.target.value)}
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">
Budget<span style={{ color: "red" }}>*</span>
</Label>
<Row>
<Col md={4}>
<Select
value={currencySymbol}
onChange={onChangeCurrency}
defaultValue="IDR|Rp|Indonesian rupiah"
style={{ width: "100%" }}
>
{currencyList && currencyList.map(res => (
<Option key={res.id} value={`${res.cc}|${res.symbol}|${res.name}`}>{`${res.cc}`}</Option>
))}
</Select>
</Col>
<Col md={8}>
<Input
type="text"
value={biaya}
onChange={(e) => setBiaya(formatNumber(e.target.value))}
/>
</Col>
</Row>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label>Handled By Division</Label>
<Select
value={divisiProject}
defaultValue={divisiProject}
onChange={onChangeDivisiProject}
style={{ width: "100%" }}
>
{dataDivisions.map((res) => (
<Option key={res.id} value={res.id}>
{res.displayName}
</Option>
))}
</Select>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Project Duration</Label>
<Input
type="number"
min="1"
value={duration}
onChange={(e) => setProjectDuration(e.target.value)}
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={6}>
<FormGroup>
<Label className="capitalize">organizational Structure</Label>
<Input
type="file"
accept="image/*"
onChange={(e) => setProjectStructureOrg(e.target.files[0])}
/>
<small>{projectImage ? projectImage.image : <p style={{ color: "red" }}>Not found image</p> }</small>
</FormGroup>
</Col>
<Col md={6}>
<FormGroup>
<Label className="capitalize">Description</Label>
<Input
type="textarea"
value={description}
onChange={(e) => setDescription(e.target.value)}
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col md={12}>
<Label className="capitalize">Late Consequence</Label>
<CKEditor
editor={ ClassicEditor }
data={ late }
config={editorConfig}
onChange={ ( event, editor ) => {
const data = editor.getData();
setLateConsequence(data);
} }
/>
</Col>
</Row>
<Row>
<Col md={12}>
<Label className="capitalize">Assumtion</Label>
<CKEditor
editor={ClassicEditor}
data={assumtion}
config={editorConfig}
onChange={ ( event, editor ) => {
const data = editor.getData();
setAssumtion(data);
} }
/>
</Col>
</Row>
<Divider orientation="left" plain>
Info Dashboard
</Divider>
<Row>
<Col md={6}>
<FormGroup>
<Label>Phase</Label>
<Select
value={phaseProject}
defaultValue={phaseProject}
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
value={budgetHealth}
defaultValue={budgetHealth}
onChange={onChangeBudgetHealth}
style={{ width: "100%" }}
>
<Option key="on-budget" value="on-budget">
On budget
</Option>
<Option key="warning" value="warning">
Warning
</Option>
<Option key="overrun" value="overrun">
Overrun
</Option>
</Select>
</FormGroup>
</Col>
</Row>
</Form>
const renderFormCharter = () => {
return (
<Form>
<Form style={{ display: step === 2 ? 'block' : 'none' }}>
<Row>
<Col md={3}>
<b>Project Objectives</b>
@ -707,11 +788,6 @@ const DialogFormProyek = ({
<b>Project Participants</b>
</Col>
<Col md={9}>
{/* <Row>
<Col md={12}>
<Button className="pull-right" size="sm" color="primary" onClick={() => addParticipant()}><i className="fa fa-plus"></i></Button>
</Col>
</Row> */}
<Row>
<Col md={5}>
<b>Title</b>
@ -755,18 +831,10 @@ const DialogFormProyek = ({
<b>Milestones</b>
</Col>
<Col md={9}>
{/* <Row>
<Col md={12}>
<Button className="pull-right" size="sm" color="primary" onClick={() => addMilestone()}><i className="fa fa-plus"></i></Button>
</Col>
</Row> */}
<Row>
<Col md={4}>
<b>Status</b>
</Col>
{/* <Col md={3}>
<b>Due</b>
</Col> */}
<Col md={4}>
<b>Deadline</b>
</Col>
@ -807,11 +875,6 @@ const DialogFormProyek = ({
<b>Approval</b>
</Col>
<Col md={9}>
{/* <Row>
<Col md={12}>
<Button className="pull-right" size="sm" color="primary" onClick={() => addApproval()}><i className="fa fa-plus"></i></Button>
</Col>
</Row> */}
<Row>
<Col md={3}>
<b>Title</b>
@ -834,9 +897,10 @@ const DialogFormProyek = ({
<div style={{ marginBottom: 50 }}>{RenderApproval()}</div>
</Col>
</Row>
</Form>
);
};
</Form>
</>
)
}
const RenderParticipants = () => {
if (participants.length > 0) {
@ -1007,7 +1071,7 @@ const DialogFormProyek = ({
: "Add Project"
: "Project Charter"}
</ModalHeader>
<ModalBody>{step === 1 ? renderForm() : renderFormCharter()}</ModalBody>
<ModalBody>{ RenderFormProject() }</ModalBody>
<ModalFooter>
{step === 1 ? (
<>

80
src/views/SimproV2/CreatedProyek/ViewProject.js

@ -6,21 +6,28 @@ import 'antd/dist/antd.css';
import _ from 'underscore'
import './style.css'
import { formatThousand, sortBy } from '../../../const/CustomFunc';
import { BASE_OSPRO } from "../../../const/ApiConst";
const createMarkup = (element) => {
return {__html: element};
}
const ViewProject = ({ openDialog, closeDialog, toggleDialog, projectCharter, projectParticipant, projectMilestone, projectApproval, projectManager, projectK3, assignHR }) => {
const ViewProject = ({ openDialog, closeDialog, toggleDialog, projectCharter, projectParticipant, projectMilestone, projectApproval, projectManager, projectK3, assignHR, projectImage }) => {
const [proyekName, setProyekName] = useState("")
const [description, setDescription] = useState("")
const [shortname, setKodeShortname] = useState("")
const [lokasi, setLokasiKantor] = useState("")
const [durasi, setDurasiProyek] = useState("")
const [mulaiProyek, setMulaiProyek] = useState("")
const [valueProyek, setValueProyek] = useState("")
const [scoupeProyek, setScoupeProyek] = useState("")
const [sponsorProyek, setSponsorProyek] = useState("")
const [lateProyek, setLateConsequenceProyek] = useState("")
const [assumtionProyek, setAssumtionProyek] = useState("")
const [objectives, setObjective] = useState("")
const [projectSuccess, setProjectSuccess] = useState("")
const [participants, setParticipants] = useState("")
const [image, setImage] = useState("")
const [budget, setBudget] = useState("")
const [currency, setCurrency] = useState("")
const [testing, setTesting] = useState("")
@ -39,11 +46,17 @@ const createMarkup = (element) => {
setLokasiKantor("")
setDurasiProyek("")
setMulaiProyek("")
setValueProyek("")
setScoupeProyek("")
setSponsorProyek("")
setLateConsequenceProyek("")
setAssumtionProyek("")
setObjective("")
setProjectSuccess("")
setParticipants([])
setDataK3Search([])
setAssignHR([])
setImage("")
setBudget("")
setCurrency("")
setTesting("")
@ -61,6 +74,11 @@ const createMarkup = (element) => {
setLokasiKantor(projectCharter.lokasi_kantor);
setDurasiProyek(projectCharter.durasi_proyek);
setMulaiProyek(projectCharter.mulai_proyek);
setValueProyek(projectCharter.value_proyek);
setScoupeProyek(projectCharter.scoupe_of_work);
setSponsorProyek(projectCharter.nama_divisi);
setLateConsequenceProyek(projectCharter.late_consequence);
setAssumtionProyek(projectCharter.assumtion);
setObjective(projectCharter.project_objectives);
setProjectSuccess(projectCharter.considered_success_when);
setBudget(projectCharter.rencana_biaya);
@ -70,6 +88,12 @@ const createMarkup = (element) => {
}
}, [projectCharter]);
useEffect(() => {
if (projectImage && projectImage != {}) {
setImage(projectImage.image)
}
}, [projectImage]);
useEffect(() => {
if(projectParticipant && projectParticipant.length > 0){
setParticipants(projectParticipant)
@ -232,6 +256,7 @@ const createMarkup = (element) => {
const tdStyle = {
border: '1px solid black',
width: "250px"
};
const pStyle = {
marginLeft: '5pt',
@ -254,17 +279,6 @@ const createMarkup = (element) => {
padding: '0',
};
const redStyle = {
fontFamily: 'Arial',
fontSize: '10pt',
color: '#FF0000',
};
const boldItalicStyle = {
...pStyle,
fontWeight: 'bold',
fontStyle: 'italic',
};
const renderForm = () => {
return (
<div>
@ -328,7 +342,7 @@ const createMarkup = (element) => {
<p style={ pStyle }>Nilai Kontrak Proyek</p>
</td>
<td colSpan="2" style={tdStyle}>
<p>&nbsp;</p>
<p>&nbsp;{valueProyek ?? '-'}</p>
</td>
</tr>
<tr>
@ -344,7 +358,9 @@ const createMarkup = (element) => {
<p style={ pStyle }>Sponsor Proyek</p>
</td>
<td>
<p style={{ ...pStyle, fontWeight: 'normal', fontStyle: 'italic' }}>Adalah Divisi yang memiliki akun atas proyek ini berikut nama GM nya</p>
<p style={{ ...pStyle, fontWeight: 'normal', fontStyle: 'italic' }}>
{sponsorProyek ?? '-'}
</p>
</td>
<td>
<p>&nbsp;</p>
@ -378,7 +394,7 @@ const createMarkup = (element) => {
</tr>
<tr>
<td style={tdStyle}>
<p style={italicStyle}>{objectives}</p>
<p style={italicStyle}>{objectives ?? '-'}</p>
</td>
</tr>
</tbody>
@ -394,10 +410,7 @@ const createMarkup = (element) => {
<tr>
<td style={tdStyle}>
<ul>
<li style={pStyle}>Jasa</li>
<li style={pStyle}>Material</li>
<li style={pStyle}>Implementasi</li>
<li style={pStyle}>dll</li>
<li style={pStyle}>{ scoupeProyek ?? '-' }</li>
</ul>
</td>
</tr>
@ -435,7 +448,13 @@ const createMarkup = (element) => {
</tr>
<tr>
<th style={emptyCellStyle}>
<p>&nbsp;</p>
<p>&nbsp;
{image ? (
<img src={`${BASE_OSPRO}/assets/image/` + image} style={{ width: "50px" }}></img>
) : (
'-'
)}
</p>
</th>
</tr>
</tbody>
@ -515,7 +534,7 @@ const createMarkup = (element) => {
</tr>
<tr>
<td>
<p dangerouslySetInnerHTML={createMarkup(potentialRisks)}></p>
<p dangerouslySetInnerHTML={createMarkup(potentialRisks ?? '-')}></p>
</td>
</tr>
</tbody>
@ -530,11 +549,7 @@ const createMarkup = (element) => {
</th>
</tr>
<tr>
<th>
<p style={italicStyle}>Adalah dampak dari jika terjadi keterlambatan atas implementasi proyek.</p>
<p style={italicStyle}>Sampaikan berapa besar kerugian jika dikenakan dengan denda maksimal.</p>
<p style={italicStyle}>Apa dampak pada potensi repeat order untuk proyek berikutnya.</p>
</th>
<p dangerouslySetInnerHTML={createMarkup(lateProyek ?? '-')}></p>
</tr>
</tbody>
</table>
@ -548,10 +563,7 @@ const createMarkup = (element) => {
</tr>
<tr>
<th>
<p style={pStyle}>Waktu</p>
<p style={pStyle}>Biaya</p>
<p style={pStyle}>Benefit bagi customer: misalkan bisa memberikan layanan publik sebelum hari raya</p>
<p style={redStyle}>Zero accident Report: (tidak adanya kejadian yang memberikan dampak negative kepada Kesehatan tim dan warga sekitar)</p>
<p style={pStyle}>{projectSuccess ?? '-'}</p>
</th>
</tr>
</tbody>
@ -566,9 +578,7 @@ const createMarkup = (element) => {
</tr>
<tr>
<td>
<p style={pStyle}>
Disebutkan SDM/Tools apa yang bisa dan mandatory diperlukan untuk menunjang lancarnya implementasi, dan jika hal tersebut tidak terpenuhi maka potensi akan terjadinya kondisi yang tidak diinginkan akan menjadi semakin besar. Misalkan; harus tersedia 4 orang drafter yang sudah memahami alur proyek dengan baik.
</p>
<p dangerouslySetInnerHTML={createMarkup(assumtionProyek ?? '-')}></p>
</td>
</tr>
</tbody>
@ -669,10 +679,10 @@ const createMarkup = (element) => {
</td>
</tr>
<tr>
<td style={thStyle}>
<td style={tdStyle}>
<p style={pStyle}>NO</p>
</td>
<td style={thStyle}>
<td style={tdStyle}>
<p style={pStyle}>ITEM</p>
</td>
</tr>

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

@ -55,6 +55,9 @@ import {
PHASE_PROYEK,
DIVISI_LIST,
BASE_OSPRO,
IMAGE_UPLOAD,
IMAGE_GET_BY_ID,
IMAGE_DELETE,
} from "../../../const/ApiConst";
import {
formatNumber,
@ -96,6 +99,13 @@ const CreatedProyek = ({ params, ...props }) => {
},
};
const HEADER_MULTIPART = {
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${token}`,
},
};
const [idTask, setidTask] = useState(0);
const [dataTable, setDatatable] = useState([]);
const [search, setSearch] = useState("");
@ -136,6 +146,7 @@ const CreatedProyek = ({ params, ...props }) => {
const [projectPM, setPM] = useState(null);
const [projectK3Search, setK3Search] = useState(null);
const [projectAssignHR, setProjectAssignHR] = useState(null);
const [image, setProjectImage] = useState(null);
const [loadVersionGantt, setLoadVersionGantt] = useState(false);
const [loadHierarchy, setLoadHierarchy] = useState(false);
@ -431,9 +442,10 @@ const CreatedProyek = ({ params, ...props }) => {
setidTask(id);
};
const handleOpenDialogProyek = (id) => {
const handleOpenDialogProyek = async (id) => {
setOpenDialogProyek(true);
setidTask(id);
await getProjectImage(id);
};
const handleOpenDialogGantt = (data) => {
@ -504,6 +516,7 @@ const CreatedProyek = ({ params, ...props }) => {
await getProjectApproval(data.id);
await getK3toProject(data.id);
await getProjectAssignHR(data.id);
await getProjectImage(data.id);
// await handleGetDataPm(data.id);
setPM(data.join_first_name);
setOpenDialogViewDetail(true);
@ -571,8 +584,8 @@ const CreatedProyek = ({ params, ...props }) => {
.catch((error) => error.response);
if (result && result.data && result.data.code == 200) {
const {kode_sortname,nama,mulai_proyek,rencana_biaya,keterangan,durasi_proyek,project_objectives,potential_risk,currency_symbol} = result.data.data;
const dataToSend = { kode_sortname, nama, mulai_proyek, rencana_biaya, keterangan, durasi_proyek, project_objectives, potential_risk, currency_symbol };
const {kode_sortname,nama,mulai_proyek,rencana_biaya,keterangan,durasi_proyek,project_objectives,potential_risk,currency_symbol, nama_divisi, late_consequence, assumtion, considered_success_when} = result.data.data;
const dataToSend = { kode_sortname, nama, mulai_proyek, rencana_biaya, keterangan, durasi_proyek, project_objectives, potential_risk, currency_symbol, nama_divisi, late_consequence, assumtion, considered_success_when};
setProjectCharter(dataToSend);
} else {
NotificationManager.error("Gagal Mengambil Data!!", "Failed");
@ -647,6 +660,17 @@ const CreatedProyek = ({ params, ...props }) => {
}
};
const getProjectImage = async (id) => {
const url = IMAGE_GET_BY_ID(id, "project_structure_organization");
const result = await axios
.get(url, HEADER)
.then((res) => res)
.catch((err) => err.response);
if (result && result.data && result.data.code === 200) {
setProjectImage(result.data.data);
}
}
const getProjectParticipant = async (id) => {
const payload = {
select: [
@ -720,6 +744,7 @@ const CreatedProyek = ({ params, ...props }) => {
setProjectCharter(null);
setK3Search(null);
setProjectAssignHR(null);
setProjectImage(null);
setOpenDialogViewDetail(false);
};
@ -733,6 +758,7 @@ const CreatedProyek = ({ params, ...props }) => {
setProjectCharter(null);
setK3Search(null);
setProjectAssignHR(null);
setProjectImage(null);
}
setOpenDialogViewDetail(!openDialogViewDetail);
};
@ -746,7 +772,8 @@ const CreatedProyek = ({ params, ...props }) => {
if (result && result.data && result.data.code === 200) {
role_id !== "44" ? getDataProyek() : getDataProyekByCustomer();
getProjectImage(idDelete);
deleteImage(idDelete);
setIdDelete(0);
setAlertDelete(false);
NotificationManager.success(`Data proyek berhasil dihapus`, "Success!!");
@ -766,6 +793,7 @@ const CreatedProyek = ({ params, ...props }) => {
.catch((error) => error.response);
if (result && result.data && result.data.code === 200) {
const { participants, milestones, approval } = data.projectCharter;
const imageObject = data.imageStructureOrg;
const resultParticipant = await saveParticipant(
result.data.data_result.id,
participants
@ -778,12 +806,18 @@ const CreatedProyek = ({ params, ...props }) => {
result.data.data_result.id,
approval
);
if (imageObject) {
await saveImage(
result.data.data_result.id,
imageObject
);
}
if (
resultParticipant === "berhasil" &&
resultMilestone === "berhasil" &&
resultApproval === "berhasil"
) {
// getDataProyek();
NotificationManager.success(
`Data proyek berhasil ditambah`,
"Success!!"
@ -860,8 +894,33 @@ const CreatedProyek = ({ params, ...props }) => {
return "berhasil";
};
const saveImage = async (id, data) => {
const formData = new FormData;
formData.append('ref_id', id);
formData.append('category', 'project_structure_organization');
formData.append('files', data);
await axios
.post(IMAGE_UPLOAD, formData, HEADER_MULTIPART)
.then(res => res)
.catch((error) => error.response);
return "berhasil";
};
const deleteImage = async (id) => {
const URL = IMAGE_DELETE(id, 'project_structure_organization');
await axios
.delete(URL, HEADER)
.then(res => res)
.catch((error) => error.response);
return "berhasil";
};
const editProyek = async (data) => {
const { participants, milestones, approval } = data.projectCharter;
const imageObject = data.imageStructureOrg;
let urlEdit = PROYEK_EDIT(data.id);
const formData = data;
@ -872,6 +931,15 @@ const CreatedProyek = ({ params, ...props }) => {
const resultParticipant = await editParticipant(data.id, participants);
const resultMilestone = await editMilestone(data.id, milestones);
const resultApproval = await editApproval(data.id, approval);
if (imageObject) {
await deleteImage(
data.id
);
await saveImage(
data.id,
imageObject
);
}
if (result && result.status === 200) {
role_id !== "44" ? getDataProyek() : getDataProyekByCustomer();
NotificationManager.success(`Data proyek berhasil Ubah`, "Success!!");
@ -882,7 +950,6 @@ const CreatedProyek = ({ params, ...props }) => {
const editParticipant = async (id, data) => {
await axios.delete(PROJECT_PARTICIPANT_DELETE_BY_PROYEK(id), HEADER);
// if (restDelete){
const request = data.map((res) => {
const payload = {
proyek_id: parseInt(id),
@ -1432,6 +1499,7 @@ const CreatedProyek = ({ params, ...props }) => {
dataPhaseProject={dataPhaseProject}
dataDivisions={dataDivisions}
dataPM={dataPm}
projectImage={image}
/>
),
[
@ -1441,6 +1509,7 @@ const CreatedProyek = ({ params, ...props }) => {
dataPhaseProject,
dataTypeProyek,
idTask,
image
]
);
@ -1559,6 +1628,7 @@ const CreatedProyek = ({ params, ...props }) => {
projectManager={projectPM}
projectK3={projectK3Search}
assignHR={projectAssignHR}
projectImage={image}
/>
),
[openDialogViewDetail]

Loading…
Cancel
Save