Detailed View
diff --git a/src/views/Dashboard/DashboardProjectCarousell.js b/src/views/Dashboard/DashboardProjectCarousell.js
new file mode 100644
index 0000000..64e9f94
--- /dev/null
+++ b/src/views/Dashboard/DashboardProjectCarousell.js
@@ -0,0 +1,977 @@
+import React, { useEffect, useMemo, useRef, useState } from "react";
+import axios from "axios";
+import { Row, Col, Button, Input,Spin } from "antd";
+import {
+ CardDashboard,
+ CardExpenditure,
+ CardScheduleHealthPerDivision,
+} from "../../components/CardDashboard/CardDashboard";
+import L from "leaflet";
+import "../../assets/css/customscroll.css";
+import moment from "moment";
+import { renderFormatRupiah } from "../../const/CustomFunc";
+import { BASE_OSPRO, BASE_OSPRO_FE, VERSION_GANTT_SEARCH } from "../../const/ApiConst";
+import { SendOutlined } from "@ant-design/icons";
+import {
+ NotificationContainer,
+ NotificationManager,
+} from "react-notifications";
+import {
+ Carousel,
+ CarouselItem,
+ CarouselControl,
+ CarouselIndicators,
+ CarouselCaption,
+} from 'reactstrap';
+import ContentLoader from "react-content-loader";
+import {
+ BehindTaskItem,
+ Comment,
+ HealthByBudget,
+ HealthBySchedule,
+ ListLoader,
+ PopupContent,
+ ProgressActualBar,
+ ProgressPlanningBar,
+ SingleTextLoader,
+} from "./Components";
+import { Fab, Action } from "react-tiny-fab";
+import "react-tiny-fab/dist/styles.css";
+import { useHistory, useLocation, useParams } from "react-router-dom";
+
+const { TextArea } = Input;
+
+const styles = {
+ cardContainer: {
+ backgroundColor: "#F8F8F8",
+ margin: 2,
+ paddingLeft: 20,
+ paddingRight: 20,
+ paddingTop: 10,
+ },
+ cardHeaderContainer: {
+ display: "flex",
+ flexDirection: "row",
+ marginBottom: 10,
+ },
+ cardChartContainer: {
+ position: "relative",
+ height: "21vh",
+ margin: "auto",
+ paddingBottom: 10,
+ justifyContent: "center",
+ },
+ cardTitle: { color: "#444444", fontSize: 16, fontWeight: "bold" },
+ cardSubtitle: { color: "#888888", fontSize: 12 },
+};
+const center = {
+ lat: -6.2,
+ lng: 106.816666,
+};
+
+const DashboardProject = (args) => {
+ const token = localStorage.getItem("token");
+ const HEADER = {
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${token}`,
+ },
+ };
+ const { PROJECT_ID } = useParams();
+ const mapRef = useRef();
+ const [mymap, setMymap] = useState(null);
+ const [activeTabIdx, setActiveTabIdx] = useState(0);
+ const [activeTabCommentIdx, setActiveTabCommentIdx] = useState(0);
+ const [planningProgress, setPlanningProgress] = useState(0);
+ const [actualProgress, setActualProgress] = useState(0);
+ const [isReadyComments, setIsReadyComments] = useState(false);
+ const [isSendingComment, setIsSendingComment] = useState(false);
+ const [isReadyProjectDetail, setIsReadyProjectDetail] = useState(false);
+ const [isReadySCurve, setIsReadySCurve] = useState(false);
+ const [isReadyGantt, setIsReadyGantt] = useState(false);
+ const [reportDistribution, setReportDistribution] = useState([]);
+ const [isReadyOverdueActivities, setIsReadyOverdueActivities] =
+ useState(false);
+ const [healthBySchedule, setHealthBySchedule] = useState("-");
+ const [allDataMaster, sourceData] = useState([]);
+ const [isHierarchy, setIsHierarchy] = useState(false);
+ let history = useHistory();
+ // Carousell
+ const [activeIndex, setActiveIndex] = useState(0);
+ const [animating, setAnimating] = useState(false);
+ const [loading, setLoading] = useState(true);
+
+
+ useEffect(() => {
+ setLoading(true);
+ getAllData();
+ },[]);
+
+ useEffect(() => {
+ if (activeTabIdx === 1) {
+ initMap();
+ }
+ }, [activeTabIdx]);
+
+ const getAllData = async () => {
+ setIsReadyProjectDetail(false);
+ setIsReadySCurve(false)
+ setIsReadySCurve(false);
+ const URL = `${BASE_OSPRO}/api/project-carausell`;
+ const result = await axios
+ .get(URL, HEADER)
+ .then((res) => res)
+ .catch((err) => err.response);
+ if (!result) {
+ NotificationManager.error(`Could not connect to internet.`, "Failed");
+ setIsReadyProjectDetail(true);
+ setIsReadySCurve(true);
+ setLoading(false);
+ return;
+ }
+
+ if (result.status !== 200) {
+ NotificationManager.error(
+ `Get project detail failed, ${result.data.message}`,
+ "Failed"
+ );
+ setIsReadyProjectDetail(true);
+ setIsReadySCurve(true);
+ setLoading(false);
+ return;
+ } else if (result.status == 200 && result.data.data) {
+ const dataResault = result.data.data;
+ console.log("Resault Data",dataResault);
+ sourceData(dataResault);
+ setIsReadyGantt(true);
+ setIsReadyProjectDetail(true);
+ // // SCurve
+ // let statusHealthBySchedule = "on-schedule";
+ // let selisihProgress = 0;
+ // dataResault.map((item, idx) => {
+ // item.SCurve.map((itemSCurve, idx) => {
+ // let planningProgress = 0;
+ // let actualProgress = 0;
+ // let now = new Date().toISOString().slice(0, 10);
+ // let dates = itemSCurve.data?.date;
+ // let n = dates.findIndex(
+ // (element) => new Date(now) < new Date(element)
+ // );
+ // if (
+ // itemSCurve.length > 0 &&
+ // itemSCurve.data?.percentagePlan &&
+ // itemSCurve.data?.percentagePlan.length > 0
+ // ) {
+ // planningProgress = itemSCurve.data?.percentagePlan[n];
+ // if (n < 0) {
+ // planningProgress = 100;
+ // }
+ // setPlanningProgress(planningProgress);
+ // }
+ // if (
+ // itemSCurve.length > 0 &&
+ // itemSCurve.data?.percentageReal &&
+ // itemSCurve.data?.percentageReal.length > 0
+ // ) {
+ // actualProgress =
+ // itemSCurve.data?.percentageReal[
+ // itemSCurve.data?.percentageReal.length - 1
+ // ];
+ // setActualProgress(actualProgress);
+ // }
+ // });
+ // });
+
+ // selisihProgress = planningProgress - actualProgress;
+ // if (selisihProgress > 0 && selisihProgress <= 5) {
+ // statusHealthBySchedule = "warning";
+ // } else if (selisihProgress > 5) {
+ // statusHealthBySchedule = "danger";
+ // }
+ // setHealthBySchedule(statusHealthBySchedule);
+ setIsReadySCurve(true);
+ // setHierarchy
+ setIsHierarchy(true);
+ // Get Overdue
+ setIsReadyOverdueActivities(true);
+ // Distribution
+ setReportDistribution(dataResault);
+ // loading
+ setLoading(false);
+
+ }
+ };
+
+ const initMap = () => {
+ let mymap = L.map("map-area", {
+ center: center,
+ zoom: 13,
+ });
+
+ setMymap(mymap);
+ L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
+ attribution:
+ '©
OpenStreetMap contributors',
+ }).addTo(mymap);
+ };
+
+ useEffect(() => {
+ if (mymap) {
+ reportDistribution.map((item, idx) => {
+ if (item.report_distribution.length > 0) {
+ item.report_distribution.map((itemDistribution, idx) => {
+ L.marker([itemDistribution.lat, itemDistribution.lon])
+ .addTo(mymap)
+ .bindPopup(PopupContent(itemDistribution));
+ })
+ }
+ });
+ }
+ }, [mymap, reportDistribution]);
+
+ useEffect(() => {
+ // Add event listener for receiving messages from the iframe
+ window.addEventListener("message", handleIframeMessage);
+
+ // Clean up the event listener on component unmount
+ return () => {
+ window.removeEventListener("message", handleIframeMessage);
+ };
+ }, []);
+
+ const handleIframeMessage = (event) => {
+ if (event.data && event.data.action === "getUrl") {
+ const childUrl = window.location.href;
+
+ // Send the URL back to the iframe
+ event.source.postMessage(
+ { action: "sendUrl", url: childUrl, isHierarchy: isHierarchy },
+ event.origin
+ );
+ }
+ };
+
+ const next = () => {
+ if (animating) return;
+ const nextIndex = activeIndex === allDataMaster.length - 1 ? 0 : activeIndex + 1;
+ setActiveIndex(nextIndex);
+ };
+
+ const previous = () => {
+ if (animating) return;
+ const nextIndex = activeIndex === 0 ? allDataMaster.length - 1 : activeIndex - 1;
+ setActiveIndex(nextIndex);
+ };
+
+ const goToIndex = (newIndex) => {
+ if (animating) return;
+ setActiveIndex(newIndex);
+ };
+
+ const slides = allDataMaster.map((item, index) => {
+ let URL_GANTT = "";
+ let version_gantt = "";
+ item.project.gantt.map((itemGantt, index) => {
+ URL_GANTT = `http://localhost:8444/adw-gantt/view-mode/index.html?base_url=${BASE_OSPRO}/api&gantt_id=${itemGantt.gantt_id}&proyek_id=${itemGantt.proyek_id}&token=${token}&ro=1`;
+ version_gantt = itemGantt.name_version
+ });
+ const today = moment();
+ const assignedList = item.assigned
+ .filter((itemAssigned) =>
+ today.isBetween(moment(itemAssigned.start_date), moment(itemAssigned.end_date))
+ )
+ .map((itemMap) => itemMap.user_id);
+ // SCurve
+ let statusHealthBySchedule = "on-schedule";
+ let selisihProgress = 0;
+ let SetplanningProgress = 0;
+ let SetactualProgress = 0;
+ let now = new Date().toISOString().slice(0, 10);
+ let dates = item.SCurve[0].data?.date;
+ let n = dates.findIndex(
+ (element) => new Date(now) < new Date(element)
+ );
+ if (
+ item.SCurve[0].length > 0 &&
+ item.SCurve[0].data?.percentagePlan &&
+ item.SCurve[0].data?.percentagePlan.length > 0
+ ) {
+ SetplanningProgress = item.SCurve[0].data?.percentagePlan[n];
+ if (n < 0) {
+ SetplanningProgress = 100;
+ }
+ }
+ if (
+ item.SCurve[0].length > 0 &&
+ item.SCurve[0].data?.percentageReal &&
+ item.SCurve[0].data?.percentageReal.length > 0
+ ) {
+ SetactualProgress =
+ item.SCurve[0].data?.percentageReal[
+ item.SCurve[0].data?.percentageReal.length - 1
+ ];
+ }
+
+ selisihProgress = SetplanningProgress - SetactualProgress;
+ if (selisihProgress > 0 && selisihProgress <= 5) {
+ statusHealthBySchedule = "warning";
+ } else if (selisihProgress > 5) {
+ statusHealthBySchedule = "danger";
+ }
+ return (
+
setAnimating(true)}
+ onExited={() => setAnimating(false)}
+ key={parseInt(item.key)}>
+
+
+
+
+
+
+
+
+ Project
+
+
+ {isReadyProjectDetail &&
+ isReadyGantt ? (
+ (() => {
+ let parentNames = "";
+ if (item.hierarchy.length > 0)
+ {
+ for ( let i = item.hierarchy.length - 1; i >= 0; i--) {
+ parentNames += " - ";
+ parentNames += item.hierarchy[i].name;
+ }
+ }
+ return item.project.nama +
+ parentNames +
+ " - " +
+ version_gantt
+ })()
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Project Manager
+
+
+ {isReadyProjectDetail ? (
+ item.project_manager
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Customer
+
+
+ {isReadyProjectDetail ? (
+ item.project.company
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Planned Start
+
+
+ {isReadyProjectDetail ? (
+ item.activity.planned_start ? (
+ moment(item.activity.planned_start).format("D MMMM YYYY")
+ ) : (
+ "-"
+ )
+ ) : (
+
+ )}
+
+
+
+
+
+ Actual Start
+
+
+ {isReadyProjectDetail ? (
+ item.activity.start_date ? (
+ moment(item.activity.start_date).format("D MMMM YYYY")
+ ) : (
+ "-"
+ )
+ ) : (
+
+ )}
+
+
+
+
+
+ Planned Finish
+
+
+ {isReadyProjectDetail ? (
+ item.activity.planned_end ? (
+ moment(item.activity.planned_end).format("D MMMM YYYY")
+ ) : (
+ "-"
+ )
+ ) : (
+
+ )}
+
+
+
+
+
+ Estimated Finish
+
+
+ {isReadyProjectDetail ? (
+ item.activity.end_date ? (
+ moment(item.activity.end_date).format("D MMMM YYYY")
+ ) : (
+ "-"
+ )
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+ setActiveTabIdx(0)}
+ >
+ S Curve
+
+
+
+ setActiveTabIdx(1)}
+ >
+ Maps
+
+
+
+
+
+
+
+
+
+ {activeTabIdx === 1 && (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ Progress
+
+ {isReadySCurve ? (
+
100 ? 100 : SetplanningProgress}
+ />
+ ) : (
+
+ )}
+
+ {isReadySCurve ? (
+ 100 || SetactualProgress > 100
+ ? parseFloat(
+ (SetactualProgress / SetplanningProgress) * 100
+ ).toFixed(0)
+ : SetactualProgress
+ }
+ />
+ ) : (
+
+ )}
+
+
+
+
+
+
+ {isReadyOverdueActivities && (
+
+ )}
+ {isReadySCurve && (
+
+ )}
+
+
+
+
+
+
+ Manpower : {item.manpower}
+
+
+
+
+
+
+ Assigned: {item.assigned && assignedList.length}
+
+
+
+
+ Actual : {item.actual}
+
+
+
+
+
+
+
+
+
+
+ setActiveTabCommentIdx(0)}
+ >
+ Behind Task
+
+
+
+ setActiveTabCommentIdx(1)}
+ >
+ Comment From Customer
+
+
+
+
+ {activeTabCommentIdx === 0 && (
+
+ {isReadyOverdueActivities && item.overdueActivities != [] && item.overdueActivities.length > 0 ? (
+ item.overdueActivities.map((overdueItem, idx) => {
+ let end_date;
+ let planned_end;
+ let diffDays = 0;
+ let message = "";
+
+ if (overdueItem.end_date && overdueItem.end_date !== null) {
+ end_date = moment(overdueItem.end_date);
+ planned_end = moment(overdueItem.planned_end);
+ diffDays = end_date.diff(planned_end, "days");
+
+ if (isNaN(diffDays)) {
+ return null;
+ } else {
+ if (diffDays > 0) {
+ message = `Overdue by ${diffDays + 1} days`;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ return
;
+ })
+ ) : (
+
+ No overdue activity found.
+
+ )}
+
+ )}
+ {activeTabCommentIdx === 1 &&(
+
+ {item.project_comment && item.project_comment != [] ? (
+ item.project_comment.map((commentItem, idx) => {
+
+ return
+ })
+ ) : (
+
+ No comments found.
+
+ )}
+
+ )}
+
+
+
+
+
+
+
+
+
+ );
+ });
+
+ return (
+
+
+
+
+
+
+
+ {slides}
+
+
+
+
+
+
+
+
+ );
+};
+
+export default DashboardProject;
diff --git a/src/views/SimproV2/CreatedProyek/DialogFormProyek.js b/src/views/SimproV2/CreatedProyek/DialogFormProyek.js
index e09fd47..3f4d89b 100644
--- a/src/views/SimproV2/CreatedProyek/DialogFormProyek.js
+++ b/src/views/SimproV2/CreatedProyek/DialogFormProyek.js
@@ -1455,8 +1455,8 @@ const DialogFormProyek = ({
handleInputChangeApproval(e, index)}
/>
diff --git a/src/views/SimproV2/CreatedProyek/index.js b/src/views/SimproV2/CreatedProyek/index.js
index f2942ce..5b9f8f6 100644
--- a/src/views/SimproV2/CreatedProyek/index.js
+++ b/src/views/SimproV2/CreatedProyek/index.js
@@ -96,20 +96,19 @@ const url = "";
const format = "DD-MM-YYYY";
const CreatedProyek = ({ params, ...props }) => {
- let role_id = '', user_id='',proyek_id='',isLogin='',token='';
+ let role_id = '', user_id = '', proyek_id = '', isLogin = '', token = '';
if (props.location.state && props.location.state.role_id && props.location.state.user_id) {
role_id = props.location.state.role_id;
user_id = props.location.state.user_id;
token = props.location.state.token;
isLogin = props.location.state.isLogin;
- console.log('props.location.state success');
+
} else {
role_id = localStorage.getItem("role_id");
proyek_id = localStorage.getItem("proyek_id");
user_id = localStorage.getItem("user_id");
token = localStorage.getItem("token");
isLogin = localStorage.getItem("isLogin");
- console.error('Undefined in props.location.state');
}
const history = useHistory();
const HEADER = {
@@ -210,7 +209,10 @@ const CreatedProyek = ({ params, ...props }) => {
}, [openDialogProyek]);
useEffect(() => {
- parseInt(role_id) !== 44 ? getDataProyek() : getDataProyekByCustomer();
+ if (parseInt(role_id) === 44) {
+ getDataProyekByCustomer()
+ }
+ getDataProyek();
}, [search, rowsPerPage, currentPage]);
useEffect(() => {
@@ -714,7 +716,7 @@ const CreatedProyek = ({ params, ...props }) => {
if (result && result.data && result.data.code === 200) {
setLoading(false)
setProjectImage(result.data.data);
- }else{
+ } else {
setLoading(false)
}
}
@@ -1090,7 +1092,7 @@ const CreatedProyek = ({ params, ...props }) => {
const request = data.map((res) => {
const payload = {
proyek_id: parseInt(id),
- tittle: res.title,
+ tittle: res.tittle,
name: res.name,
date_approval: res.date,
};
@@ -1275,7 +1277,7 @@ const CreatedProyek = ({ params, ...props }) => {
const request = data.map((res) => {
const payload = {
proyek_id: parseInt(id),
- tittle: res.tittle ? res.tittle : res.title,
+ tittle: res.tittle ? res.tittle : res.tittle,
name: res.name,
date_approval: res.date ? res.date : res.date_approval,
};
@@ -1631,7 +1633,7 @@ const CreatedProyek = ({ params, ...props }) => {
dataIndex: "",
key: "x",
render: (text, record) =>
- parseInt(role_id) == 44 ? (
+ parseInt(role_id) == 44 ? (
<>