Compare commits
No commits in common. "ddfbed1020e6aa27032188cf1c440d3211c09694" and "e6a687c8e23fbcdf5789bc026c316edf81f3956c" have entirely different histories.
ddfbed1020
...
e6a687c8e2
@ -1,81 +0,0 @@
|
|||||||
import React, { createContext, useContext, useState, useEffect, useRef } from "react";
|
|
||||||
|
|
||||||
const ModalContext = createContext();
|
|
||||||
|
|
||||||
export const useModal = () => useContext(ModalContext);
|
|
||||||
|
|
||||||
// ModalProvider to manage modal state and expose functionality to the rest of the app
|
|
||||||
export const ModalProvider = ({ children }) => {
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
|
||||||
const [modalContent, setModalContent] = useState(null);
|
|
||||||
const [onSubmit, setOnSubmit] = useState(null);
|
|
||||||
const [modalSize, setModalSize] = useState('lg');
|
|
||||||
|
|
||||||
// Ref to track the modal content element
|
|
||||||
const modalRef = useRef(null);
|
|
||||||
|
|
||||||
const openModal = (content, onSubmitCallback, size = 'lg') => {
|
|
||||||
setModalContent(content); // Set modal content dynamically
|
|
||||||
setOnSubmit(() => onSubmitCallback); // Set the submit handler dynamically
|
|
||||||
setIsOpen(true); // Open the modal
|
|
||||||
setModalSize(size); // Set the modal size
|
|
||||||
};
|
|
||||||
|
|
||||||
// Function to close the modal
|
|
||||||
const closeModal = () => {
|
|
||||||
setIsOpen(false); // Close the modal
|
|
||||||
setModalContent(null); // Clear modal content
|
|
||||||
setOnSubmit(null); // Clear the submit callback
|
|
||||||
setModalSize('lg'); // Reset modal size
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleClickOutside = (event) => {
|
|
||||||
if (modalRef.current && !modalRef.current.contains(event.target)) {
|
|
||||||
closeModal();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
document.addEventListener("mousedown", handleClickOutside);
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener("mousedown", handleClickOutside);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ModalContext.Provider value={{ isOpen, openModal, closeModal, modalContent, modalSize, onSubmit }}>
|
|
||||||
{children}
|
|
||||||
|
|
||||||
{isOpen && (
|
|
||||||
<div style={overlayStyles}>
|
|
||||||
<div ref={modalRef} style={{ ...modalStyles, maxWidth: modalSize === 'sm' ? '400px' : '800px' }}>
|
|
||||||
<div>{modalContent}</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</ModalContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const overlayStyles = {
|
|
||||||
position: "fixed",
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
zIndex: 1050,
|
|
||||||
};
|
|
||||||
|
|
||||||
const modalStyles = {
|
|
||||||
backgroundColor: "white",
|
|
||||||
padding: "20px",
|
|
||||||
borderRadius: "5px",
|
|
||||||
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
|
|
||||||
width: "90%",
|
|
||||||
maxWidth: "800px",
|
|
||||||
};
|
|
||||||
@ -9,7 +9,7 @@ import { useNavigate } from "react-router-dom";
|
|||||||
|
|
||||||
const Attendance = ( {attendance, getRole, handleModalData} ) =>
|
const Attendance = ( {attendance, getRole, handleModalData} ) =>
|
||||||
{
|
{
|
||||||
console.log(attendance)
|
|
||||||
const { currentPage, totalPages, currentItems, paginate } = usePagination(attendance, 5);
|
const { currentPage, totalPages, currentItems, paginate } = usePagination(attendance, 5);
|
||||||
const [loading,setLoading] = useState(false);
|
const [loading,setLoading] = useState(false);
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
@ -38,7 +38,7 @@ console.log(attendance)
|
|||||||
return checkInB - checkInA; // Sort in descending order of checkInTime
|
return checkInB - checkInA; // Sort in descending order of checkInTime
|
||||||
})
|
})
|
||||||
.map( ( item ) => (
|
.map( ( item ) => (
|
||||||
<tr key={item.employeeId}>
|
<tr key={item.id}>
|
||||||
<td colSpan={2}>
|
<td colSpan={2}>
|
||||||
<div className="d-flex justify-content-start align-items-center">
|
<div className="d-flex justify-content-start align-items-center">
|
||||||
<Avatar
|
<Avatar
|
||||||
@ -60,10 +60,9 @@ console.log(attendance)
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
{/* <span className="badge bg-label-primary me-1">
|
<span className="badge bg-label-primary me-1">
|
||||||
{getRole(item.roleID)}
|
{getRole(item.roleID)}
|
||||||
</span> */}
|
</span>
|
||||||
---
|
|
||||||
</td>
|
</td>
|
||||||
<td>{item.checkInTime ? convertShortTime(item.checkInTime):"--"}</td>
|
<td>{item.checkInTime ? convertShortTime(item.checkInTime):"--"}</td>
|
||||||
<td>{item.checkOutTime ? convertShortTime(item.checkOutTime):"--"}</td>
|
<td>{item.checkOutTime ? convertShortTime(item.checkOutTime):"--"}</td>
|
||||||
|
|||||||
@ -1,105 +1,567 @@
|
|||||||
|
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import "../../components/Project/ProjectInfra.css";
|
import "../../components/Project/ProjectInfra.css";
|
||||||
import BuildingModel from "../Project/Infrastructure/BuildingModel";
|
import BuildingModel from "../../components/Project/BuildingModel";
|
||||||
import FloorModel from "../Project/Infrastructure/FloorModel";
|
import FloorModel from "../../components/Project/FloorModel";
|
||||||
import showToast from "../../services/toastService";
|
import showToast from "../../services/toastService";
|
||||||
import WorkAreaModel from "../Project/Infrastructure/WorkAreaModel";
|
import WorkAreaModel from "../../components/Project/WorkAreaModel";
|
||||||
import TaskModel from "../Project/Infrastructure/TaskModel";
|
import TaskModel from "../../components/Project/TaskModel";
|
||||||
import ProjectRepository from "../../repositories/ProjectRepository";
|
import ProjectRepository from "../../repositories/ProjectRepository";
|
||||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||||
import {useProjectDetails, useProjects} from "../../hooks/useProjects";
|
|
||||||
import {useHasUserPermission} from "../../hooks/useHasUserPermission";
|
|
||||||
import {MANAGE_PROJECT_INFRA} from "../../utils/constants";
|
|
||||||
import {useDispatch, useSelector} from "react-redux";
|
|
||||||
import {useProfile} from "../../hooks/useProfile";
|
|
||||||
import {setProjectId} from "../../slices/localVariablesSlice";
|
|
||||||
import InfraTable from "../Project/Infrastructure/InfraTable";
|
|
||||||
|
|
||||||
|
|
||||||
const InfraPlanning = () =>
|
const InfraPlanning = ({ data, activityMaster, onDataChange }) => {
|
||||||
{
|
const [expandedBuildings, setExpandedBuildings] = useState([]);
|
||||||
const {profile: LoggedUser} = useProfile()
|
const [project, setProject] = useState(data);
|
||||||
const dispatch = useDispatch()
|
const [buildings, setBuildings] = useState(data?.buildings);
|
||||||
const selectedProject = useSelector((store)=>store.localVariables.projectId)
|
|
||||||
const ManageInfra = useHasUserPermission( MANAGE_PROJECT_INFRA )
|
const [isBuildingModalOpen, setIsBuildingModalOpen] = useState(false);
|
||||||
const {projects,loading:project_listLoader,error:projects_error} = useProjects()
|
const [isFloorModalOpen, setIsFloorModalOpen] = useState(false);
|
||||||
const {projects_Details, loading: project_deatilsLoader, error: project_error} = useProjectDetails(selectedProject)
|
const [isWorkAreaModelOpen, setIsWorkAreaModalOpen] = useState(false);
|
||||||
|
const [isTaskModelOpen, setIsTaskModalOpen] = useState(false);
|
||||||
|
|
||||||
|
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||||
|
const [clearFormTrigger, setClearFormTrigger] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setProject(data);
|
||||||
|
setBuildings(data?.buildings);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
const openModal = (projectData) => {
|
||||||
|
setIsCreateModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openFloorModel = (projectData) => {
|
||||||
|
setIsFloorModalOpen(true);
|
||||||
|
};
|
||||||
|
const closeFloorModel = () => {
|
||||||
|
setIsFloorModalOpen(false);
|
||||||
|
// const modalBackdrop = document.querySelector(".modal-backdrop");
|
||||||
|
// if (modalBackdrop) modalBackdrop.remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFloorModelFormSubmit = (updatedFloor) => {
|
||||||
|
if (updatedFloor.id == "") delete updatedFloor.id;
|
||||||
|
|
||||||
|
submitData([
|
||||||
|
{
|
||||||
|
building: null,
|
||||||
|
floor: updatedFloor,
|
||||||
|
workArea: null,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const submitData = (infraObject) => {
|
||||||
|
|
||||||
|
ProjectRepository.manageProjectInfra(infraObject)
|
||||||
|
.then((response) => {
|
||||||
|
fetchData();
|
||||||
|
onDataChange("building-change");
|
||||||
|
showToast("Details updated successfully.", "success");
|
||||||
|
setClearFormTrigger(true); // Set trigger to true
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
showToast(error.message, "error");
|
||||||
|
});
|
||||||
|
|
||||||
|
// api
|
||||||
|
// .post("/api/project/manage-infra", infraObject)
|
||||||
|
// .then((data) => {
|
||||||
|
// fetchData();
|
||||||
|
// onDataChange("building-change");
|
||||||
|
// showToast("Details updated successfully.", "success");
|
||||||
|
// setClearFormTrigger(true); // Set trigger to true
|
||||||
|
// })
|
||||||
|
// .catch((error) => {
|
||||||
|
// showToast(error.message, "error");
|
||||||
|
// });
|
||||||
|
};
|
||||||
|
|
||||||
|
const openBuildingModel = (projectData) => {
|
||||||
|
setIsBuildingModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeBuildingModel = () => {
|
||||||
|
setIsBuildingModalOpen(false);
|
||||||
|
|
||||||
|
};
|
||||||
|
const handleBuildingModelFormSubmit = (buildingmodel) => {
|
||||||
|
if (buildingmodel.id == "" || buildingmodel.id == 0)
|
||||||
|
delete buildingmodel.id;
|
||||||
|
|
||||||
|
let data = [
|
||||||
|
{
|
||||||
|
building: buildingmodel,
|
||||||
|
floor: null,
|
||||||
|
workArea: null,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
submitData(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openWorkAreaModel = (projectData) => {
|
||||||
|
setIsWorkAreaModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeWorkAreaModel = () => {
|
||||||
|
setIsWorkAreaModalOpen(false);
|
||||||
|
|
||||||
|
};
|
||||||
|
const handleWorkAreaModelFormSubmit = (updatedModel) => {
|
||||||
|
if (updatedModel.id == "") delete updatedModel.id;
|
||||||
|
|
||||||
|
submitData([
|
||||||
|
{
|
||||||
|
building: null,
|
||||||
|
floor: null,
|
||||||
|
workArea: updatedModel,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openTaskModel = (projectData) => {
|
||||||
|
setIsTaskModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeTaskModel = () => {
|
||||||
|
setIsTaskModalOpen(false);
|
||||||
|
// const modalBackdrop = document.querySelector(".modal-backdrop");
|
||||||
|
// if (modalBackdrop) modalBackdrop.remove();
|
||||||
|
};
|
||||||
|
const handleTaskModelFormSubmit = (updatedModel) => {
|
||||||
|
if (updatedModel.id == "") updatedModel.id = 0;
|
||||||
|
|
||||||
|
//console.log("Form submitted:", updatedModel); // Replace this with an API call or state update
|
||||||
|
ProjectRepository.manageProjectTasks([updatedModel])
|
||||||
|
.then((response) => {
|
||||||
|
onDataChange("task-change");
|
||||||
|
showToast("Details updated successfully.", "success");
|
||||||
|
setClearFormTrigger(true); // Set trigger to true
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
showToast(error.message, "error");
|
||||||
|
});
|
||||||
|
|
||||||
|
// api
|
||||||
|
// .post("/api/project/task", [updatedModel])
|
||||||
|
// .then((data) => {
|
||||||
|
// onDataChange("task-change");
|
||||||
|
// showToast("Details updated successfully.", "success");
|
||||||
|
// setClearFormTrigger(true); // Set trigger to true
|
||||||
|
// })
|
||||||
|
// .catch((error) => {
|
||||||
|
// showToast(error.message, "error");
|
||||||
|
// });
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleBuilding = (id) => {
|
||||||
|
setExpandedBuildings((prev) =>
|
||||||
|
prev.includes(id) ? prev.filter((bid) => bid !== id) : [...prev, id]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getContent = (building) => {
|
||||||
|
let hasFloors =
|
||||||
|
building.floors && building.floors.length > 0 ? true : false;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{(() => {
|
||||||
|
if (hasFloors) {
|
||||||
|
return building.floors.map((floor) => (
|
||||||
|
<React.Fragment key={floor.id}>
|
||||||
|
{floor.workAreas.length > 0 ? (
|
||||||
|
floor.workAreas.map((workArea) => (
|
||||||
|
<React.Fragment key={workArea.id}>
|
||||||
|
<tr>
|
||||||
|
<td colSpan="4" className="text-start table-cell">
|
||||||
|
<div className="row ps-2">
|
||||||
|
<div className="col-6">
|
||||||
|
{" "}
|
||||||
|
<h6>
|
||||||
|
<span>
|
||||||
|
{" "}
|
||||||
|
{floor.floorName} - {workArea.areaName} {" "}
|
||||||
|
</span>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div className="col-6 text-end">
|
||||||
|
{/* <a
|
||||||
|
type="button"
|
||||||
|
className="text-end me-2"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#floor-model"
|
||||||
|
onClick={() => openFloorModel()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-edit-alt me-2"></i>
|
||||||
|
Edit Floor
|
||||||
|
</a> */}
|
||||||
|
|
||||||
|
{/* <a
|
||||||
|
type="button"
|
||||||
|
className="text-end"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#editproject"
|
||||||
|
onClick={() => openModal()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Add Activities
|
||||||
|
</a> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{workArea.workItems.length > 0 ? (
|
||||||
|
<tr>
|
||||||
|
{" "}
|
||||||
|
<td colSpan={4}>
|
||||||
|
<table
|
||||||
|
className="table ms-4"
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Activity</th>
|
||||||
|
<th>Planned</th>
|
||||||
|
<th>Complated</th>
|
||||||
|
<th>Progress</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="table-border-bottom-0">
|
||||||
|
{workArea.workItems.map((workItem) => (
|
||||||
|
<React.Fragment key={workItem.workItemId}>
|
||||||
|
<tr>
|
||||||
|
<td className="text-start table-cell-small">
|
||||||
|
<i className="bx bx-right-arrow-alt"></i>
|
||||||
|
<span className="fw-medium">
|
||||||
|
{workItem.workItem.activityMaster
|
||||||
|
? workItem.workItem.activityMaster
|
||||||
|
.activityName
|
||||||
|
: "NA"}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td className="text-center">
|
||||||
|
{workItem.workItem
|
||||||
|
? workItem.workItem.plannedWork
|
||||||
|
: "NA"}
|
||||||
|
</td>
|
||||||
|
<td className="text-center">
|
||||||
|
{workItem.workItem
|
||||||
|
? workItem.workItem.completedWork
|
||||||
|
: "NA"}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td
|
||||||
|
className="text-center"
|
||||||
|
style={{ width: "15%" }}
|
||||||
|
>
|
||||||
|
<div className="progress p-0">
|
||||||
|
<div
|
||||||
|
className="progress-bar"
|
||||||
|
role="progressbar"
|
||||||
|
style={{
|
||||||
|
width: getProgress(
|
||||||
|
workItem.workItem.plannedWork,
|
||||||
|
workItem.workItem.completedWork
|
||||||
|
),
|
||||||
|
height: "10px",
|
||||||
|
}}
|
||||||
|
aria-valuenow={
|
||||||
|
workItem.workItem
|
||||||
|
? workItem.workItem
|
||||||
|
.completedWork
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuemax={
|
||||||
|
workItem.workItem
|
||||||
|
? workItem.workItem.plannedWork
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
{/* <input type="range" id="customRange1" max="@workItem.PlannedWork" min="0" value="@workItem.CompletedWork"> */}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div className="dropdown">
|
||||||
|
<button
|
||||||
|
aria-label="Modify"
|
||||||
|
type="button"
|
||||||
|
className="btn p-0 dropdown-toggle hide-arrow"
|
||||||
|
>
|
||||||
|
<i class="bx bxs-edit me-2 text-primary"></i>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
aria-label="Delete"
|
||||||
|
type="button"
|
||||||
|
className="btn p-0 dropdown-toggle hide-arrow"
|
||||||
|
>
|
||||||
|
<i className="bx bx-trash me-1 text-danger"></i>{" "}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>{" "}
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>{" "}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
) : (
|
||||||
|
<span></span>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<React.Fragment key={building.id + floor.id}>
|
||||||
|
<tr>
|
||||||
|
<td colSpan="4" className="text-start table-cell">
|
||||||
|
<div className="row ps-2">
|
||||||
|
<div className="col-6">
|
||||||
|
{" "}
|
||||||
|
<h6>
|
||||||
|
<span> {floor.floorName} </span>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div className="col-6 text-end">
|
||||||
|
{/* <a
|
||||||
|
type="button"
|
||||||
|
className="text-end me-2"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#floor-model"
|
||||||
|
onClick={() => openFloorModel()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-edit-alt me-2"></i>
|
||||||
|
Edit Floor
|
||||||
|
</a> */}
|
||||||
|
|
||||||
|
{/* <a
|
||||||
|
type="button"
|
||||||
|
className="text-end"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#editproject"
|
||||||
|
onClick={() => openModal()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Add Work Area
|
||||||
|
</a> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p>No Floors Added, Please add them</p>
|
||||||
|
{/* <p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
className="btn btn-sm btn-danger m-1"
|
||||||
|
data-bs-target="#editproject"
|
||||||
|
onClick={() => openModal()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Add Floors
|
||||||
|
</button>
|
||||||
|
</p> */}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})()}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getProgress = (planned, completed) => {
|
||||||
|
return (completed * 100) / planned + "%";
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="col-md-12 col-lg-12 col-xl-12 order-0 mb-4">
|
<>
|
||||||
<div className="card">
|
{isBuildingModalOpen && (
|
||||||
<div className="card-body" style={{ padding: "0.5rem" }}>
|
<div
|
||||||
<div className="align-items-center">
|
className={`modal fade `}
|
||||||
<div className="row ">
|
id="building-model"
|
||||||
<div className="col-sm-3 col-8 text-start mb-1">
|
tabIndex="-1"
|
||||||
<select name="DataTables_Table_0_length"
|
aria-hidden="true"
|
||||||
aria-controls="DataTables_Table_0"
|
>
|
||||||
className="form-select form-select-sm"
|
<BuildingModel
|
||||||
value={selectedProject}
|
project={data}
|
||||||
onChange={(e)=>dispatch(setProjectId(e.target.value))}
|
onClose={closeBuildingModel}
|
||||||
aria-label=""
|
onSubmit={handleBuildingModelFormSubmit}
|
||||||
>
|
clearTrigger={clearFormTrigger}
|
||||||
{(project_listLoader || projects.length < 0) && <option value="Loading..." disabled>Loading...</option> }
|
onClearComplete={() => setClearFormTrigger(false)}
|
||||||
|
></BuildingModel>
|
||||||
{!project_listLoader && projects?.filter(project =>
|
</div>
|
||||||
LoggedUser?.projects?.map(Number).includes(project.id)).map((project)=>(
|
)}
|
||||||
<option value={project.id}>{project.name}</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{/* <div className={`col-12 text-end mb-1 ${!ManageInfra && 'd-none'} `} >
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="link-button link-button-sm m-1 "
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
data-bs-target="#building-model"
|
|
||||||
// onClick={() => openBuildingModel()}
|
|
||||||
>
|
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
|
||||||
Manage Building
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
className="link-button m-1"
|
|
||||||
data-bs-target="#floor-model"
|
|
||||||
// onClick={() => openFloorModel()}
|
|
||||||
>
|
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
|
||||||
Manage Floors
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
{isFloorModalOpen && (
|
||||||
type="button"
|
<div
|
||||||
data-bs-toggle="modal"
|
className={`modal fade `}
|
||||||
className="link-button m-1"
|
id="floor-model"
|
||||||
data-bs-target="#work-area-model"
|
tabIndex="-1"
|
||||||
// onClick={() => openWorkAreaModel()}
|
aria-hidden="true"
|
||||||
>
|
>
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
<FloorModel
|
||||||
Manage Work Areas
|
project={data}
|
||||||
</button>
|
// building={null}
|
||||||
<button
|
onClose={closeFloorModel}
|
||||||
type="button"
|
onSubmit={handleFloorModelFormSubmit}
|
||||||
data-bs-toggle="modal"
|
clearTrigger={clearFormTrigger}
|
||||||
className="link-button m-1"
|
onClearComplete={() => setClearFormTrigger(false)}
|
||||||
data-bs-target="#task-model"
|
></FloorModel>
|
||||||
// onClick={() => openTaskModel()}
|
</div>
|
||||||
>
|
)}
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
|
||||||
Manage Tasks
|
{isWorkAreaModelOpen && (
|
||||||
</button>
|
<div
|
||||||
</div> */}
|
className={`modal fade `}
|
||||||
</div>
|
id="work-area-model"
|
||||||
<div className="row ">
|
tabIndex="-1"
|
||||||
<InfraTable buildings={projects_Details?.buildings}/>
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<WorkAreaModel
|
||||||
|
project={data}
|
||||||
|
// building={null}
|
||||||
|
onClose={closeWorkAreaModel}
|
||||||
|
onSubmit={handleWorkAreaModelFormSubmit}
|
||||||
|
clearTrigger={clearFormTrigger}
|
||||||
|
onClearComplete={() => setClearFormTrigger(false)}
|
||||||
|
></WorkAreaModel>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isTaskModelOpen && (
|
||||||
|
<div
|
||||||
|
className={`modal fade `}
|
||||||
|
id="task-model"
|
||||||
|
tabIndex="-1"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<TaskModel
|
||||||
|
project={data}
|
||||||
|
activities={activityMaster}
|
||||||
|
onClose={closeTaskModel}
|
||||||
|
onSubmit={handleTaskModelFormSubmit}
|
||||||
|
clearTrigger={clearFormTrigger}
|
||||||
|
onClearComplete={() => setClearFormTrigger(false)}
|
||||||
|
></TaskModel>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
<div className="col-md-12 col-lg-12 col-xl-12 order-0 mb-4">
|
||||||
|
<div className="card">
|
||||||
|
{/* <div className="card-header pb-4"></div> */}
|
||||||
|
|
||||||
|
<div className="card-body" style={{ padding: "0.5rem" }}>
|
||||||
|
<div className="align-items-center">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12 text-end mb-1">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="link-button link-button-sm m-1"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#building-model"
|
||||||
|
onClick={() => openBuildingModel()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Manage Building
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
className="link-button m-1"
|
||||||
|
data-bs-target="#floor-model"
|
||||||
|
onClick={() => openFloorModel()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Manage Floors
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
className="link-button m-1"
|
||||||
|
data-bs-target="#work-area-model"
|
||||||
|
onClick={() => openWorkAreaModel()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Manage Work Areas
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
className="link-button m-1"
|
||||||
|
data-bs-target="#task-model"
|
||||||
|
onClick={() => openTaskModel()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Manage Tasks
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
{buildings && buildings.length > 0 && (
|
||||||
|
<table className="table table-bordered">
|
||||||
|
<tbody>
|
||||||
|
{buildings.map((building) => (
|
||||||
|
building.floors && building.floors.length > 0 && (
|
||||||
|
<React.Fragment key={building.id}>
|
||||||
|
<tr>
|
||||||
|
<td
|
||||||
|
colSpan="4"
|
||||||
|
className="text-start"
|
||||||
|
style={{
|
||||||
|
background: "#f0f0f0",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
onClick={() => toggleBuilding(building.id)}
|
||||||
|
>
|
||||||
|
<div className="row">
|
||||||
|
<h5 style={{ marginBottom: "0px" }}>
|
||||||
|
|
||||||
|
{ building.name}
|
||||||
|
{expandedBuildings.includes(building.id) ? (
|
||||||
|
<i className="bx bx-chevron-down"></i>
|
||||||
|
) : (
|
||||||
|
<i className="bx bx-chevron-right"></i>
|
||||||
|
)}
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{expandedBuildings.includes(building.id) && getContent(building)}
|
||||||
|
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,32 +1,20 @@
|
|||||||
import React, { useState,useEffect } from "react";
|
import React, { useState,useEffect } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { changeMaster } from "../../slices/localVariablesSlice";
|
import { changeMaster } from "../../slices/localVariablesSlice";
|
||||||
import useMaster from "../../hooks/masterHook/useMaster";
|
import useMaster from "../../hooks/masterHook/useMaster";
|
||||||
import { employee } from "../../data/masters";
|
import { employee } from "../../data/masters";
|
||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { getCachedData } from "../../slices/apiDataManager";
|
import { getCachedData } from "../../slices/apiDataManager";
|
||||||
import {useModal} from "../../ModalContext";
|
|
||||||
import {useProjects} from "../../hooks/useProjects";
|
|
||||||
import {useEmployeesAllOrByProjectId} from "../../hooks/useEmployees";
|
|
||||||
import {TasksRepository} from "../../repositories/ProjectRepository";
|
|
||||||
import showToast from "../../services/toastService";
|
|
||||||
|
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
selectedEmployees: z.array( z.number() ).min( 1, {message: "At least one employee must be selected"} ),
|
selectedEmployees: z.array(z.number()).min(1, {message:"At least one employee must be selected"}),
|
||||||
description: z.string().min( 1, {message: "description required"} ),
|
|
||||||
pannedTask: z.number()
|
|
||||||
.refine(value => value > 0, { message: "pannedTask should be greater than zero" })
|
|
||||||
.refine(value => value !== undefined, { message: "pannedTask is required" }),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
const AssignRoleModel = ( {assignData,onClose}) => {
|
const AssignRoleModel = ( {assignData,onClose}) => {
|
||||||
const { openModal, closeModal } = useModal()
|
const[target,setTraget] = useState("")
|
||||||
const selectedProject = useSelector((store)=>store.localVariables.projectId)
|
|
||||||
const {employees} = useEmployeesAllOrByProjectId( selectedProject )
|
|
||||||
|
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const {data,loading} = useMaster()
|
const {data,loading} = useMaster()
|
||||||
const jobRoleData = getCachedData("Job Role")
|
const jobRoleData = getCachedData("Job Role")
|
||||||
@ -38,8 +26,7 @@ const [selectedEmployees, setSelectedEmployees] = useState([]);
|
|||||||
|
|
||||||
const { handleSubmit, control, setValue, watch, formState: { errors } } = useForm({
|
const { handleSubmit, control, setValue, watch, formState: { errors } } = useForm({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
selectedEmployees: [],
|
selectedEmployees: []
|
||||||
description:""
|
|
||||||
},
|
},
|
||||||
resolver: (data) => {
|
resolver: (data) => {
|
||||||
const validation = schema.safeParse(data);
|
const validation = schema.safeParse(data);
|
||||||
@ -49,13 +36,13 @@ const { handleSubmit, control, setValue, watch, formState: { errors } } = useFor
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleRoleChange = (event) => {
|
const handleRoleChange = (event) => {
|
||||||
setSelectedRole(event.plannedTask.value);
|
setSelectedRole(event.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const filteredEmployees = selectedRole === "all"
|
const filteredEmployees = selectedRole === "all"
|
||||||
? employees
|
? employee
|
||||||
: employees.filter((emp) => emp.JobRoleId.toString() === selectedRole);
|
: employee.filter((emp) => emp.JobRoleId.toString() === selectedRole);
|
||||||
|
|
||||||
|
|
||||||
// not need currently for this fun
|
// not need currently for this fun
|
||||||
@ -69,7 +56,7 @@ const handleEmployeeSelection = (employeeId,field) => {
|
|||||||
} else {
|
} else {
|
||||||
updatedSelection = prevSelected.filter((id) => id !== employeeId);
|
updatedSelection = prevSelected.filter((id) => id !== employeeId);
|
||||||
}
|
}
|
||||||
field.onChange(updatedSelection);
|
field.onChange(updatedSelection); // Update form state with new selection
|
||||||
return updatedSelection;
|
return updatedSelection;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -78,34 +65,17 @@ const handleEmployeeSelection = (employeeId,field) => {
|
|||||||
const removeEmployee = (employeeId) => {
|
const removeEmployee = (employeeId) => {
|
||||||
setSelectedEmployees((prevSelected) => {
|
setSelectedEmployees((prevSelected) => {
|
||||||
const updatedSelection = prevSelected.filter((id) => id !== employeeId);
|
const updatedSelection = prevSelected.filter((id) => id !== employeeId);
|
||||||
setValue("selectedEmployees", updatedSelection);
|
setValue("selectedEmployees", updatedSelection); // Ensure form state is updated
|
||||||
return updatedSelection;
|
return updatedSelection;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const onSubmit = async(data) => {
|
const onSubmit = (data) => {
|
||||||
const formattedData = {
|
console.log( {...data.selectedEmployees,target});
|
||||||
taskTeam: data.selectedEmployees,
|
onClose()
|
||||||
plannedTask: parseInt( plannedTask, 10 ),
|
|
||||||
description: data.description,
|
|
||||||
assignmentDate: new Date().toISOString(),
|
|
||||||
workItemId:assignData?.workItem?.workItem.id
|
|
||||||
};
|
|
||||||
try
|
|
||||||
{
|
|
||||||
let response = await TasksRepository.assignTask( formattedData );
|
|
||||||
console.log( response )
|
|
||||||
showToast( "Task Successfully Assigend", "success" )
|
|
||||||
closeModal()
|
|
||||||
} catch ( error )
|
|
||||||
{
|
|
||||||
showToast("something wrong","error")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
console.log(assignData?.workItem?.workItem)
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
dispatch(changeMaster("Job Role"))
|
dispatch(changeMaster("Job Role"))
|
||||||
return ()=> setSelectedRole("all")
|
return ()=> setSelectedRole("all")
|
||||||
@ -114,7 +84,8 @@ useEffect(()=>{
|
|||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
|
|
||||||
<div className="container my-1">
|
|
||||||
|
<div className="container-fluid my-1">
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
<div className="bs-stepper wizard-numbered d-flex justify-content-center align-items-center flex-wrap">
|
<div className="bs-stepper wizard-numbered d-flex justify-content-center align-items-center flex-wrap">
|
||||||
{[
|
{[
|
||||||
@ -172,7 +143,7 @@ useEffect(()=>{
|
|||||||
<div className="col-sm-12">
|
<div className="col-sm-12">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
{filteredEmployees.map((emp) => {
|
{filteredEmployees.map((emp) => {
|
||||||
const jobRole = jobRoleData?.find((role) => role.id === emp.jobRoleId);
|
const jobRole = jobRoleData?.find((role) => role.id === emp.JobRoleId);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={emp.id} className="col-6 col-sm-4 col-md-4 col-lg-3 mb-1">
|
<div key={emp.id} className="col-6 col-sm-4 col-md-4 col-lg-3 mb-1">
|
||||||
@ -190,14 +161,18 @@ useEffect(()=>{
|
|||||||
value={emp.id}
|
value={emp.id}
|
||||||
checked={field.value.includes(emp.id)} // Ensure the checkbox reflects the current form state
|
checked={field.value.includes(emp.id)} // Ensure the checkbox reflects the current form state
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
handleEmployeeSelection( emp.id, field )
|
// Directly update the form value
|
||||||
|
handleEmployeeSelection(emp.id,field)
|
||||||
|
// const updatedSelection = field.value.includes(emp.id)
|
||||||
|
// ? field.value.filter((id) => id !== emp.id)
|
||||||
|
// : [...field.value, emp.id];
|
||||||
|
// field.onChange(updatedSelection); // Directly update form value
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<div className="list-content">
|
<div className="list-content">
|
||||||
<h6 className="mb-0">{emp.firstName
|
<h6 className="mb-0">{emp.FirtsName} {emp.LastName}</h6>
|
||||||
} {emp.lastName}</h6>
|
|
||||||
<small className="text-muted">
|
<small className="text-muted">
|
||||||
{loading && (<p className="skeleton para" style={{height:"7px"}}></p>)}
|
{loading && (<p className="skeleton para" style={{height:"7px"}}></p>)}
|
||||||
{data && !loading && (jobRole ? jobRole.name : 'Unknown Role')}
|
{data && !loading && (jobRole ? jobRole.name : 'Unknown Role')}
|
||||||
@ -212,15 +187,16 @@ useEffect(()=>{
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
{selectedEmployees.length > 0 && (
|
{selectedEmployees.length > 0 && (
|
||||||
<div className="mt-1">
|
<div className="mt-1">
|
||||||
<div className="text-start px-2">
|
<div className="text-start px-2">
|
||||||
{selectedEmployees.map((empId) => {
|
{selectedEmployees.map((empId) => {
|
||||||
const emp = employees.find((emp) => emp.id === empId);
|
const emp = employee.find((emp) => emp.id === empId);
|
||||||
return (
|
return (
|
||||||
<span key={empId} className="badge bg-label-primary d-inline-flex align-items-center gap-2 me-1 p-2 mb-2">
|
<span key={empId} className="badge bg-label-primary d-inline-flex align-items-center gap-2 me-1 p-2 mb-2">
|
||||||
{emp.firstName
|
{emp.FirtsName} {emp.LastName}
|
||||||
} {emp.lastName}
|
|
||||||
<p
|
<p
|
||||||
type="button"
|
type="button"
|
||||||
className=" btn-close-white p-0 m-0"
|
className=" btn-close-white p-0 m-0"
|
||||||
@ -236,47 +212,30 @@ useEffect(()=>{
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{errors.selectedEmployees && (
|
|
||||||
<div className="danger-text mt-1">
|
|
||||||
<p>{errors.selectedEmployees[0]}</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div class="col-md text-start mx-0 px-0">
|
<div class="col-md text-start mx-0 px-0">
|
||||||
<div class="form-check form-check-inline mt-4 px-1">
|
<div class="form-check form-check-inline mt-4 px-1">
|
||||||
<label className="form-text fs-6" for="inlineCheckbox1">Pending Work</label>
|
<label className="form-text fs-6" for="inlineCheckbox1">Pending Work</label>
|
||||||
<label className="form-check-label ms-2" for="inlineCheckbox1">{ assignData?.workItem?.workItem?.plannedWork - assignData?.workItem?.workItem?.completedWork}</label>
|
<label className="form-check-label ms-2" for="inlineCheckbox1">{ assignData?.workItem?.workItem?.plannedWork - assignData?.workItem?.workItem?.completedWork}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-check form-check-inline col-sm-2 col">
|
<div className="form-check form-check-inline col-sm-2 col">
|
||||||
<label for="defaultFormControlInput" className="form-label">Target</label>
|
<label for="defaultFormControlInput" className="form-label">Target</label>
|
||||||
<Controller name="pannedTask" control={control} render={( {field} ) => (
|
<input type="text" className="form-control form-control-sm " value={target} onChange={(e)=>setTraget(e.target.value)} id="defaultFormControlInput" aria-describedby="defaultFormControlHelp" />
|
||||||
<input type="text" className="form-control form-control-sm " {...field} />
|
</div>
|
||||||
)} />
|
</div>
|
||||||
{errors.pannedTask && (
|
|
||||||
<div className="danger-text">
|
|
||||||
<p>{errors.pannedTask.message}</p>
|
|
||||||
|
{errors.selectedEmployees && (
|
||||||
|
<div className="danger-text mt-2">
|
||||||
|
<p>{errors.selectedEmployees[0]}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
<div className="col-12 d-flex justify-content-center align-items-center gap-sm-6 gap-8 text-center">
|
||||||
<label for="exampleFormControlTextarea1" className="form-label">Description</label>
|
|
||||||
<Controller
|
|
||||||
name="description"
|
|
||||||
control={control}
|
|
||||||
render={({ field }) => (
|
|
||||||
<textarea
|
|
||||||
{...field}
|
|
||||||
className="form-control"
|
|
||||||
id="exampleFormControlTextarea1"
|
|
||||||
rows="3"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{errors.description && ( <div>{errors.description.message }</div>)}
|
|
||||||
|
|
||||||
<div className="col-12 d-flex justify-content-center align-items-center gap-sm-6 gap-8 text-center mt-1">
|
|
||||||
<button type="submit" className="btn btn-sm btn-primary ">Submit</button>
|
<button type="submit" className="btn btn-sm btn-primary ">Submit</button>
|
||||||
<button type="reset" className="btn btn-sm btn-label-secondary" data-bs-dismiss="modal" aria-label="Close" onClick={closeModal}>
|
<button type="reset" className="btn btn-sm btn-label-secondary" data-bs-dismiss="modal" aria-label="Close">
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
140
src/components/Project/BuildingModel.jsx
Normal file
140
src/components/Project/BuildingModel.jsx
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
|
const defaultModel = {
|
||||||
|
id: "",
|
||||||
|
name: "",
|
||||||
|
description: "",
|
||||||
|
projectId: "",
|
||||||
|
};
|
||||||
|
const BuildingModel = ({
|
||||||
|
project,
|
||||||
|
onClose,
|
||||||
|
onSubmit,
|
||||||
|
clearTrigger,
|
||||||
|
onClearComplete,
|
||||||
|
}) => {
|
||||||
|
const [formData, setFormData] = useState(defaultModel);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (clearTrigger) {
|
||||||
|
setFormData(defaultModel); // Clear form
|
||||||
|
onClearComplete(); // Notify parent that clearing is done
|
||||||
|
}
|
||||||
|
}, [clearTrigger, onClearComplete]);
|
||||||
|
|
||||||
|
// Handle input change
|
||||||
|
const handleChange = (e) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
setFormData({ ...formData, [name]: value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBuildigChange = (e) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
const building = project.buildings.find((b) => b.id === Number(value));
|
||||||
|
if (building) {
|
||||||
|
delete building.floors;
|
||||||
|
building.projectId = project.id;
|
||||||
|
setFormData(building);
|
||||||
|
} else
|
||||||
|
setFormData({
|
||||||
|
id: "",
|
||||||
|
name: "",
|
||||||
|
description: "",
|
||||||
|
projectId: project.id,
|
||||||
|
});
|
||||||
|
//setFormData({ ...formData, [name]: value });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle form submission
|
||||||
|
const handleSubmit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
formData.projectId = project.id;
|
||||||
|
|
||||||
|
onSubmit(formData); // Pass the updated data to the parent
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="modal-dialog modal-lg modal-simple modal-edit-user">
|
||||||
|
<div className="modal-content">
|
||||||
|
<div className="modal-body">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-close"
|
||||||
|
data-bs-dismiss="modal"
|
||||||
|
aria-label="Close"
|
||||||
|
></button>
|
||||||
|
<div className="text-center mb-2">
|
||||||
|
<h5 className="mb-2">Manage Buildings - {project.name}</h5>
|
||||||
|
</div>
|
||||||
|
<form className="row g-2" onSubmit={handleSubmit}>
|
||||||
|
<div className="col-12 col-md-12">
|
||||||
|
<label className="form-label" htmlFor="name">
|
||||||
|
Select Building
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="buildingId"
|
||||||
|
name="buildingId"
|
||||||
|
className="select2 form-select form-select-sm"
|
||||||
|
aria-label="Default select example"
|
||||||
|
onChange={handleBuildigChange}
|
||||||
|
value={formData.buildingId}
|
||||||
|
>
|
||||||
|
<option value="0">Add New Building</option>
|
||||||
|
{project.buildings.map((building) => (
|
||||||
|
<option key={building.id} value={building.id}>
|
||||||
|
{building.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="col-12 col-md-12">
|
||||||
|
<label className="form-label" htmlFor="name">
|
||||||
|
Building Name
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="name"
|
||||||
|
name="name"
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
placeholder="Building Name"
|
||||||
|
onChange={handleChange}
|
||||||
|
value={formData.name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="col-12 col-md-12">
|
||||||
|
<label className="form-label" htmlFor="description">
|
||||||
|
Description
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
type="text"
|
||||||
|
id="description"
|
||||||
|
rows="5"
|
||||||
|
name="description"
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
placeholder="Description"
|
||||||
|
onChange={handleChange}
|
||||||
|
value={formData.description}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 text-center">
|
||||||
|
<button type="submit" className="btn btn-primary me-3">
|
||||||
|
{formData.id ? "Edit Building" : "Add Building"}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="reset"
|
||||||
|
className="btn btn-label-secondary"
|
||||||
|
data-bs-dismiss="modal"
|
||||||
|
aria-label="Close"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BuildingModel;
|
||||||
@ -1,20 +1,10 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { z } from "zod";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
|
|
||||||
// Zod validation schema
|
|
||||||
const floorSchema = z.object({
|
|
||||||
buildingId: z.string().min(1, "Building is required"),
|
|
||||||
id: z.string().min(1, "Floor is required").optional(),
|
|
||||||
floorName: z.string().min(1, "Floor Name is required"),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Default model
|
|
||||||
const defaultModel = {
|
const defaultModel = {
|
||||||
id: "0",
|
id: "0",
|
||||||
floorName: "",
|
floorName: "",
|
||||||
buildingId: "0",
|
buildingId: "0",
|
||||||
|
projectId: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
const FloorModel = ({
|
const FloorModel = ({
|
||||||
@ -25,80 +15,67 @@ const FloorModel = ({
|
|||||||
onClearComplete,
|
onClearComplete,
|
||||||
}) => {
|
}) => {
|
||||||
const [formData, setFormData] = useState(defaultModel);
|
const [formData, setFormData] = useState(defaultModel);
|
||||||
|
|
||||||
const [selectedBuilding, setSelectedBuilding] = useState({});
|
const [selectedBuilding, setSelectedBuilding] = useState({});
|
||||||
|
|
||||||
// Initialize the form with React Hook Form
|
//if (floor && floor.id) setFormData(floor);
|
||||||
const {
|
|
||||||
register,
|
|
||||||
handleSubmit,
|
|
||||||
setValue,
|
|
||||||
reset,
|
|
||||||
formState: { errors },
|
|
||||||
} = useForm({
|
|
||||||
resolver: zodResolver(floorSchema),
|
|
||||||
defaultValues: defaultModel,
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (clearTrigger) {
|
if (clearTrigger) {
|
||||||
reset(defaultModel);
|
setFormData(defaultModel); // Clear form
|
||||||
onClearComplete();
|
onClearComplete(); // Notify parent that clearing is done
|
||||||
}
|
}
|
||||||
}, [clearTrigger, onClearComplete, reset]);
|
}, [clearTrigger, onClearComplete]);
|
||||||
|
|
||||||
// Handle building selection change
|
// Handle input change
|
||||||
const handleBuildigChange = (e) => {
|
const handleChange = (e) => {
|
||||||
const buildingId = e.target.value;
|
const { name, value } = e.target;
|
||||||
const building = project.buildings.find((b) => b.id === Number(buildingId));
|
setFormData({ ...formData, [name]: value });
|
||||||
if (building) {
|
|
||||||
setSelectedBuilding(building);
|
|
||||||
setFormData({
|
|
||||||
id: "",
|
|
||||||
floorName: "",
|
|
||||||
buildingId: building.id,
|
|
||||||
|
|
||||||
});
|
|
||||||
setValue("buildingId", building.id); // Set value for validation
|
|
||||||
setValue("id", "0"); // Reset floorId when changing building
|
|
||||||
} else {
|
|
||||||
setSelectedBuilding({});
|
|
||||||
setFormData({
|
|
||||||
id: "",
|
|
||||||
floorName: "",
|
|
||||||
buildingId: "0",
|
|
||||||
|
|
||||||
});
|
|
||||||
setValue("buildingId", "0");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle floor selection change
|
|
||||||
const handleFloorChange = (e) => {
|
const handleFloorChange = (e) => {
|
||||||
const id = e.target.value;
|
const { name, value } = e.target;
|
||||||
const floor = selectedBuilding.floors.find((b) => b.id === Number(id));
|
const floor = selectedBuilding.floors.find((b) => b.id === Number(value));
|
||||||
if (floor) {
|
if (floor) {
|
||||||
setFormData({
|
setFormData({
|
||||||
id: floor.id,
|
id: floor.id,
|
||||||
floorName: floor.floorName,
|
floorName: floor.floorName,
|
||||||
buildingId: selectedBuilding.id,
|
buildingId: selectedBuilding.id,
|
||||||
|
projectId: project.id,
|
||||||
});
|
});
|
||||||
setValue("floorName", floor.floorName); // Set floor name for form
|
} else
|
||||||
} else {
|
|
||||||
setFormData({
|
setFormData({
|
||||||
id: "0",
|
id: "0",
|
||||||
floorName: "",
|
floorName: "",
|
||||||
buildingId: selectedBuilding.id,
|
buildingId: selectedBuilding.id,
|
||||||
|
projectId: project.id,
|
||||||
});
|
});
|
||||||
setValue("floorName", "");
|
};
|
||||||
}
|
const handleBuildigChange = (e) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
const building = project.buildings.find((b) => b.id === Number(value));
|
||||||
|
if (building) {
|
||||||
|
setFormData({
|
||||||
|
id: "",
|
||||||
|
floorName: "",
|
||||||
|
buildingId: building.id,
|
||||||
|
projectId: project.id,
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
setFormData({
|
||||||
|
id: "",
|
||||||
|
floorName: "",
|
||||||
|
buildingId: "0",
|
||||||
|
projectId: project.id,
|
||||||
|
});
|
||||||
|
setSelectedBuilding(building);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle form submission
|
// Handle form submission
|
||||||
const onFormSubmit = (data) => {
|
const handleSubmit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
formData.projectId = project.id;
|
||||||
|
|
||||||
onSubmit(data);
|
onSubmit(formData); // Pass the updated data to the parent
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -115,20 +92,18 @@ const FloorModel = ({
|
|||||||
<div className="text-center mb-1">
|
<div className="text-center mb-1">
|
||||||
<h5 className="mb-1">Manage Floors - {project.name}</h5>
|
<h5 className="mb-1">Manage Floors - {project.name}</h5>
|
||||||
</div>
|
</div>
|
||||||
<form
|
<form className="row g-2" onSubmit={handleSubmit}>
|
||||||
className="row g-2"
|
|
||||||
onSubmit={handleSubmit(onFormSubmit)}
|
|
||||||
>
|
|
||||||
<div className="col-12 col-md-12">
|
<div className="col-12 col-md-12">
|
||||||
<label className="form-label" htmlFor="buildingId">
|
<label className="form-label" htmlFor="name">
|
||||||
Select Building
|
Select Building
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
id="buildingId"
|
id="buildingId"
|
||||||
|
name="buildingId"
|
||||||
className="select2 form-select form-select-sm"
|
className="select2 form-select form-select-sm"
|
||||||
aria-label="Select Building"
|
aria-label="Default select example"
|
||||||
{...register("buildingId")}
|
|
||||||
onChange={handleBuildigChange}
|
onChange={handleBuildigChange}
|
||||||
|
value={formData.buildingId}
|
||||||
>
|
>
|
||||||
<option value="0">Select Building</option>
|
<option value="0">Select Building</option>
|
||||||
{project.buildings.map((building) => (
|
{project.buildings.map((building) => (
|
||||||
@ -137,22 +112,20 @@ const FloorModel = ({
|
|||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
{errors.buildingId && (
|
|
||||||
<p className="text-danger">{errors.buildingId.message}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{formData.buildingId !== "0" && (
|
{formData.buildingId != "0" && (
|
||||||
<div className="col-12 col-md-12">
|
<div className="col-12 col-md-12">
|
||||||
<label className="form-label" >
|
<label className="form-label" htmlFor="floorId">
|
||||||
Select Floor
|
Select Floor
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
id="id"
|
id="floorId"
|
||||||
|
name="floorId"
|
||||||
className="select2 form-select form-select-sm"
|
className="select2 form-select form-select-sm"
|
||||||
aria-label="Select Floor"
|
aria-label="Default select example"
|
||||||
{...register("id")}
|
|
||||||
onChange={handleFloorChange}
|
onChange={handleFloorChange}
|
||||||
|
value={formData.floorId}
|
||||||
>
|
>
|
||||||
<option value="0">Add New Floor</option>
|
<option value="0">Add New Floor</option>
|
||||||
{selectedBuilding.floors.map((floor) => (
|
{selectedBuilding.floors.map((floor) => (
|
||||||
@ -161,33 +134,30 @@ const FloorModel = ({
|
|||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
{errors.id && (
|
|
||||||
<p className="text-danger">{errors.id.message}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{formData.buildingId != "0" && (
|
||||||
{formData.buildingId !== "0" && (
|
|
||||||
<div className="col-12 col-md-12">
|
<div className="col-12 col-md-12">
|
||||||
<label className="form-label" htmlFor="floorName">
|
{" "}
|
||||||
{formData.id !== "0" ? "Modify " : "Enter "} Floor Name
|
<label className="form-label" htmlFor="name">
|
||||||
|
{formData.id != "0" ? "Modify " : "Enter "} Floor Name
|
||||||
</label>
|
</label>
|
||||||
<input
|
<div className="input-group">
|
||||||
type="text"
|
<input
|
||||||
id="floorName"
|
type="text"
|
||||||
className="form-control form-control-sm me-2"
|
id="floorName"
|
||||||
placeholder="Floor Name"
|
name="floorName"
|
||||||
{...register("floorName")}
|
className="form-control form-control-sm me-2"
|
||||||
/>
|
placeholder="Floor Name"
|
||||||
{errors.floorName && (
|
onChange={handleChange}
|
||||||
<p className="text-danger">{errors.floorName.message}</p>
|
value={formData.floorName}
|
||||||
)}
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="col-12 text-center">
|
<div className="col-12 text-center">
|
||||||
<button type="submit" className="btn btn-primary me-3">
|
<button type="submit" className="btn btn-primary me-3">
|
||||||
{formData.id !== "0" && formData.id !== ""
|
{formData.id != "0" && formData.id != ""
|
||||||
? "Edit Floor"
|
? "Edit Floor"
|
||||||
: "Add Floor"}
|
: "Add Floor"}
|
||||||
</button>
|
</button>
|
||||||
@ -1,31 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
const Building = ( {building, toggleBuilding, expandedBuildings, getContent} ) =>
|
|
||||||
{
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment key={building.id}>
|
|
||||||
<tr className="overflow-auto">
|
|
||||||
<td
|
|
||||||
colSpan="4"
|
|
||||||
className="text-start"
|
|
||||||
style={{ background: "#f0f0f0", cursor: "pointer" }}
|
|
||||||
onClick={() => toggleBuilding(building.id)}
|
|
||||||
>
|
|
||||||
<div className="row table-responsive">
|
|
||||||
<h5 style={{ marginBottom: "0px" }}>
|
|
||||||
{building.name}
|
|
||||||
{expandedBuildings.includes(building.id) ? (
|
|
||||||
<i className="bx bx-chevron-down"></i>
|
|
||||||
) : (
|
|
||||||
<i className="bx bx-chevron-right"></i>
|
|
||||||
)}
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{expandedBuildings.includes(building.id) && getContent(building)}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default Building
|
|
||||||
@ -1,129 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { z } from "zod";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
import ProjectRepository from "../../../repositories/ProjectRepository";
|
|
||||||
|
|
||||||
// Zod validation schema
|
|
||||||
const buildingSchema = z.object({
|
|
||||||
Id: z.string().optional(),
|
|
||||||
name: z.string().min(1, "Building name is required"),
|
|
||||||
description: z
|
|
||||||
.string()
|
|
||||||
.min(1, "Description is required")
|
|
||||||
.max(160, "Description cannot exceed 160 characters"),
|
|
||||||
});
|
|
||||||
|
|
||||||
const BuildingModel = ({
|
|
||||||
project,
|
|
||||||
onSubmit,
|
|
||||||
clearTrigger,
|
|
||||||
onClearComplete,
|
|
||||||
editingBuilding = null,
|
|
||||||
}) => {
|
|
||||||
const [formData, setFormData] = useState({
|
|
||||||
id: "",
|
|
||||||
name: "",
|
|
||||||
description: "",
|
|
||||||
projectId: project.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Reset form data if clearTrigger is true, or if editing a building
|
|
||||||
useEffect(() => {
|
|
||||||
if (clearTrigger) {
|
|
||||||
setFormData({ id: "", name: "", description: "", projectId: project.id });
|
|
||||||
onClearComplete();
|
|
||||||
} else if (editingBuilding) {
|
|
||||||
setFormData({ ...editingBuilding, projectId: project.id });
|
|
||||||
}
|
|
||||||
}, [clearTrigger, onClearComplete, editingBuilding, project.id]);
|
|
||||||
|
|
||||||
const { register, handleSubmit, formState: { errors }, setValue } = useForm({
|
|
||||||
resolver: zodResolver(buildingSchema),
|
|
||||||
defaultValues: formData, // Set default values from formData state
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleBuildingChange = (e) => {
|
|
||||||
const selectedBuilding = project.buildings.find(b => b.id === +e.target.value);
|
|
||||||
if (selectedBuilding) {
|
|
||||||
setFormData({ ...selectedBuilding, projectId: project.id });
|
|
||||||
setValue("name", selectedBuilding.name); // Update name field
|
|
||||||
setValue("description", selectedBuilding.description); // Update description field
|
|
||||||
} else {
|
|
||||||
setFormData({ id: "", name: "", description: "", projectId: project.id });
|
|
||||||
setValue("name", "");
|
|
||||||
setValue("description", "");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmitHandler = async( data ) =>
|
|
||||||
{
|
|
||||||
onSubmit({ ...data, projectId: project.id });
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="modal-dialog modal-lg modal-simple modal-edit-user">
|
|
||||||
<div className="modal-content">
|
|
||||||
<div className="modal-body">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn-close"
|
|
||||||
data-bs-dismiss="modal"
|
|
||||||
aria-label="Close"
|
|
||||||
></button>
|
|
||||||
<h5 className="text-center mb-2">Manage Buildings - {project.name}</h5>
|
|
||||||
<form onSubmit={handleSubmit(onSubmitHandler)} className="row g-2">
|
|
||||||
<div className="col-12">
|
|
||||||
<label className="form-label">Select Building</label>
|
|
||||||
<select
|
|
||||||
{...register("Id")}
|
|
||||||
className="select2 form-select form-select-sm"
|
|
||||||
onChange={(e) => { handleBuildingChange(e); }}
|
|
||||||
>
|
|
||||||
<option value="0">Add New Building</option>
|
|
||||||
{project.buildings.map((building) => (
|
|
||||||
<option key={building.id} value={building.id}>{building.name}</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
{errors.Id && <span className="danger-text">{errors.Id.message}</span>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="col-12">
|
|
||||||
<label className="form-label">
|
|
||||||
{formData.id ? "Rename Building Name" : "New Building Name"}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
{...register("name")}
|
|
||||||
type="text"
|
|
||||||
className="form-control form-control-sm"
|
|
||||||
/>
|
|
||||||
{errors.name && <span className="danger-text">{errors.name.message}</span>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="col-12">
|
|
||||||
<label className="form-label">Description</label>
|
|
||||||
<textarea
|
|
||||||
{...register("description")}
|
|
||||||
maxLength="160"
|
|
||||||
rows="5"
|
|
||||||
className="form-control form-control-sm"
|
|
||||||
/>
|
|
||||||
{errors.description && <span className="danger-text">{errors.description.message}</span>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="col-12 text-center">
|
|
||||||
<button type="submit" className="btn btn-primary me-3">
|
|
||||||
{formData.id ? "Edit Building" : "Add Building"}
|
|
||||||
</button>
|
|
||||||
<button type="reset" className="btn btn-label-secondary" data-bs-dismiss="modal" aria-label="Close">
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default BuildingModel;
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import WorkArea from "./WorkArea";
|
|
||||||
const Floor = ( {floor, workAreas,forBuilding} ) =>
|
|
||||||
{
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment key={floor.id}>
|
|
||||||
{workAreas && workAreas.length > 0 ? (
|
|
||||||
workAreas.map((workArea) => (
|
|
||||||
<WorkArea forBuilding={forBuilding} key={workArea.id} workArea={workArea} floor={floor} />
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<tr>
|
|
||||||
<td colSpan="4" className="text-start">
|
|
||||||
<div className="row ps-2">
|
|
||||||
<div className="col-6">
|
|
||||||
<h6>
|
|
||||||
<span>{floor.floorName} </span>
|
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default Floor
|
|
||||||
@ -1,69 +0,0 @@
|
|||||||
import {useEffect, useState} from "react";
|
|
||||||
import Building from "./Building";
|
|
||||||
import Floor from "./Floor";
|
|
||||||
|
|
||||||
const InfraTable = ( {buildings,assign} ) =>
|
|
||||||
{
|
|
||||||
const [projectBuiling,setProjectBuilding] = useState([])
|
|
||||||
const [expandedBuildings, setExpandedBuildings] = useState([]);
|
|
||||||
|
|
||||||
const toggleBuilding = (buildingId) => {
|
|
||||||
setExpandedBuildings((prevExpanded) =>
|
|
||||||
prevExpanded.includes(buildingId)
|
|
||||||
? prevExpanded.filter((id) => id !== buildingId)
|
|
||||||
: [...prevExpanded, buildingId]
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const getContent = (building) => {
|
|
||||||
return building.floors.length > 0 ? (
|
|
||||||
building.floors.map((floor) => <Floor forBuilding={building} key={floor.id} floor={floor} workAreas={floor.workAreas} />)
|
|
||||||
) : (
|
|
||||||
<tr>
|
|
||||||
<td colSpan="4">
|
|
||||||
<div className="alert alert-warning text-center mb-0" role="alert">
|
|
||||||
<p>No floors have been added yet. Please add floors to start managing your building.</p>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-xs btn-primary"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
data-bs-target="#addFloorModal"
|
|
||||||
onClick={() => openModal('addFloor')}
|
|
||||||
>
|
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
|
||||||
Add Floors
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
useEffect( () =>
|
|
||||||
{
|
|
||||||
setProjectBuilding(buildings)
|
|
||||||
},[buildings])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="col-12 overflow-auto">
|
|
||||||
{projectBuiling && projectBuiling.length > 0 && (
|
|
||||||
<table className="table table-bordered">
|
|
||||||
<tbody>
|
|
||||||
{projectBuiling.map((building) => (
|
|
||||||
<Building
|
|
||||||
key={building.id}
|
|
||||||
building={building}
|
|
||||||
toggleBuilding={toggleBuilding}
|
|
||||||
expandedBuildings={expandedBuildings}
|
|
||||||
getContent={getContent}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default InfraTable
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import WorkItem from "./WorkItem";
|
|
||||||
|
|
||||||
const WorkArea = ({ workArea, floor,forBuilding }) => {
|
|
||||||
return (
|
|
||||||
<React.Fragment key={workArea.id}>
|
|
||||||
<tr>
|
|
||||||
<td colSpan="4" className="text-start table-cell">
|
|
||||||
<div className="row ps-2">
|
|
||||||
<div className="col-6">
|
|
||||||
<h6>
|
|
||||||
<span>
|
|
||||||
{floor.floorName} - {workArea.areaName}
|
|
||||||
</span>
|
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{workArea?.workItems && workArea.workItems.length > 0 ? (
|
|
||||||
<tr className="overflow-auto">
|
|
||||||
<td colSpan={4}>
|
|
||||||
<table className="table mx-1">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Activity</th>
|
|
||||||
<th>Planned</th>
|
|
||||||
<th>Completed</th>
|
|
||||||
<th>Progress</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody className="table-border-bottom-0">
|
|
||||||
{workArea.workItems.map((workItem) => (
|
|
||||||
<WorkItem key={workItem.workItemId} workItem={workItem} forBuilding={forBuilding} forFloor={floor} forWorkArea={workArea} />
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
) : null}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default WorkArea;
|
|
||||||
@ -1,218 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import { set, useForm } from "react-hook-form";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
// Zod schema for form validation
|
|
||||||
const workAreaSchema = z.object( {
|
|
||||||
id:z.string().nonempty("Floor is required"),
|
|
||||||
|
|
||||||
buildingId: z.string().nonempty("Building is required"),
|
|
||||||
floorId: z.string().nonempty("Floor is required"),
|
|
||||||
areaName: z.string().nonempty( "Work Area Name is required" ).min( 3, "Name must be at least 3 characters long" ),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Default form data
|
|
||||||
const defaultModel = {
|
|
||||||
id: "0",
|
|
||||||
areaName: "",
|
|
||||||
floorId: "0",
|
|
||||||
};
|
|
||||||
|
|
||||||
const WorkAreaModel = ({ project, onSubmit, clearTrigger, onClearComplete }) => {
|
|
||||||
const [selectedBuilding, setSelectedBuilding] = useState(null);
|
|
||||||
const [ selectedFloor, setSelectedFloor ] = useState( null );
|
|
||||||
const [selectdWorkArea,setWorkArea] = useState()
|
|
||||||
|
|
||||||
const { register, handleSubmit, formState: { errors }, setValue, reset, watch } = useForm({
|
|
||||||
resolver: zodResolver(workAreaSchema), // Use Zod resolver for validation
|
|
||||||
defaultValues: defaultModel,
|
|
||||||
});
|
|
||||||
|
|
||||||
const floorId = watch( "floorId" ); // Watch the floorId for conditional rendering
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (clearTrigger) {
|
|
||||||
reset(defaultModel); // Reset form to initial state
|
|
||||||
setSelectedBuilding(null);
|
|
||||||
setSelectedFloor(null);
|
|
||||||
onClearComplete();
|
|
||||||
}
|
|
||||||
}, [clearTrigger, onClearComplete, reset]);
|
|
||||||
|
|
||||||
const handleWorkAreaChange = ( e ) =>
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
const { value } = e.target;
|
|
||||||
|
|
||||||
if (value === "0") {
|
|
||||||
setValue("id", "0"); // Create New Work Area
|
|
||||||
setValue( "areaName", "" );
|
|
||||||
|
|
||||||
setWorkArea(String(0))
|
|
||||||
} else {
|
|
||||||
const workArea = selectedFloor?.workAreas.find((b) => b.id === Number(value));
|
|
||||||
if ( workArea )
|
|
||||||
{
|
|
||||||
setValue("id", String(workArea.id)); // Set id as a string
|
|
||||||
setValue("areaName", workArea.areaName);
|
|
||||||
setWorkArea(String(workArea.id))
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleFloorChange = (e) => {
|
|
||||||
const { value } = e.target;
|
|
||||||
const floor = selectedBuilding?.floors.find((b) => b.id === Number(value));
|
|
||||||
|
|
||||||
if (floor) {
|
|
||||||
setSelectedFloor(floor);
|
|
||||||
setValue("floorId", floor.id); // Update floorId
|
|
||||||
setValue("id", "0"); // Reset Work Area ID for new area creation
|
|
||||||
setValue("areaName", ""); // Reset Work Area Name when changing floor
|
|
||||||
} else {
|
|
||||||
setSelectedFloor(null);
|
|
||||||
setValue("floorId", "0");
|
|
||||||
setValue("id", "0"); // Reset Work Area ID
|
|
||||||
setValue("areaName", ""); // Reset Work Area Name
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleBuildingChange = (e) => {
|
|
||||||
const { value } = e.target;
|
|
||||||
const building = project.buildings.find((b) => b.id === Number(value));
|
|
||||||
setSelectedBuilding(building);
|
|
||||||
setSelectedFloor(null); // Reset selected floor on building change
|
|
||||||
reset(defaultModel); // Reset the form when a new building is selected
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmitForm = ( data ) =>
|
|
||||||
{
|
|
||||||
console.log(data)
|
|
||||||
let WorkArea = {
|
|
||||||
id: data.id,
|
|
||||||
areaName: data.areaName,
|
|
||||||
floorId: data.floorId,
|
|
||||||
buildingId:data.buildingId
|
|
||||||
}
|
|
||||||
onSubmit(WorkArea); // Send the final data to the parent
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCancel = () => {
|
|
||||||
reset(defaultModel); // Reset the form to initial state
|
|
||||||
setSelectedFloor(null);
|
|
||||||
setSelectedBuilding(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="modal-dialog modal-lg modal-simple modal-edit-user">
|
|
||||||
<div className="modal-content">
|
|
||||||
<div className="modal-body">
|
|
||||||
<div className="row">
|
|
||||||
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
<div className="text-center mb-1">
|
|
||||||
<h5 className="mb-1">Manage Work Area</h5>
|
|
||||||
</div>
|
|
||||||
<form className="row g-2" onSubmit={handleSubmit(onSubmitForm)}>
|
|
||||||
{/* Building Selection */}
|
|
||||||
<div className="col-6 col-md-6">
|
|
||||||
<label className="form-label" htmlFor="buildingId">Select Building</label>
|
|
||||||
<select
|
|
||||||
id="buildingId"
|
|
||||||
name="buildingId"
|
|
||||||
className="select2 form-select form-select-sm"
|
|
||||||
{...register("buildingId")}
|
|
||||||
onChange={handleBuildingChange}
|
|
||||||
>
|
|
||||||
<option value="0">Select Building</option>
|
|
||||||
{project.buildings.map((building) => (
|
|
||||||
<option key={building.id} value={building.id}>
|
|
||||||
{building.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
{errors.buildingId && <span>{errors.buildingId.message}</span>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Floor Selection */}
|
|
||||||
{selectedBuilding && selectedBuilding.buildingId !== "0" && (
|
|
||||||
<div className="col-6 col-md-6">
|
|
||||||
<label className="form-label" htmlFor="floorId">Select Floor</label>
|
|
||||||
<select
|
|
||||||
id="floorId"
|
|
||||||
name="floorId"
|
|
||||||
className="select2 form-select form-select-sm"
|
|
||||||
{...register("floorId")}
|
|
||||||
onChange={handleFloorChange}
|
|
||||||
>
|
|
||||||
<option value="0">Select Floor</option>
|
|
||||||
{selectedBuilding.floors.map((floor) => (
|
|
||||||
<option key={floor.id} value={floor.id}>
|
|
||||||
{floor.floorName}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
{errors.floorId && <span>{errors.floorId.message}</span>}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Work Area Selection or Creation */}
|
|
||||||
{floorId !== "0" && (
|
|
||||||
<>
|
|
||||||
<div className="col-12 col-md-12">
|
|
||||||
<label className="form-label" >Select Work Area</label>
|
|
||||||
<select
|
|
||||||
id="workAreaId"
|
|
||||||
name="workAreaId"
|
|
||||||
className="select2 form-select form-select-sm"
|
|
||||||
{...register("id")}
|
|
||||||
onChange={handleWorkAreaChange}
|
|
||||||
>
|
|
||||||
<option value="0">Create New Work Area</option>
|
|
||||||
{selectedFloor?.workAreas.map((workArea) => (
|
|
||||||
<option key={workArea.id} value={workArea.id}>
|
|
||||||
{workArea.areaName}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
{errors.id && <span>{errors.id.message}</span>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Work Area Name Input */}
|
|
||||||
<div className="col-12 col-md-12">
|
|
||||||
<label className="form-label" htmlFor="areaName">
|
|
||||||
{watch("id") === "0" ? "Enter Work Area Name" : "Modify Work Area Name"}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="areaName"
|
|
||||||
name="areaName"
|
|
||||||
className="form-control form-control-sm"
|
|
||||||
placeholder="Work Area"
|
|
||||||
{...register("areaName")}
|
|
||||||
/>
|
|
||||||
{errors.areaName && <span className="danger-text">{errors.areaName.message}</span>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Submit and Cancel Buttons */}
|
|
||||||
<div className="col-12 text-center">
|
|
||||||
<button type="submit" className="btn btn-primary me-3">
|
|
||||||
{watch("id") === "0" ? "Add Work Area" : "Edit Work Area"}
|
|
||||||
</button>
|
|
||||||
<button type="button" className="btn btn-label-secondary" onClick={handleCancel} data-bs-dismiss="modal" aria-label="Close">
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default WorkAreaModel;
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
import React, { useState } from "react";
|
|
||||||
import { useModal } from "../../../ModalContext";
|
|
||||||
import AssignRoleModel from "../AssignRole";
|
|
||||||
import {useParams} from "react-router-dom";
|
|
||||||
|
|
||||||
const WorkItem = ( {workItem, forBuilding, forFloor, forWorkArea} ) =>{
|
|
||||||
const {projectId} = useParams()
|
|
||||||
const { openModal ,closedModal} = useModal();
|
|
||||||
const [itemName, setItemName] = useState('');
|
|
||||||
const getProgress = (planned, completed) => {
|
|
||||||
return (completed * 100) / planned + "%";
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleAssignTask = () => {
|
|
||||||
console.log("Item Created:", itemName);
|
|
||||||
setItemName('');
|
|
||||||
};
|
|
||||||
|
|
||||||
const showCreateItemModal = (modalData) => {
|
|
||||||
openModal(
|
|
||||||
<AssignRoleModel assignData={modalData} onClose={closedModal} />,
|
|
||||||
handleAssignTask ,"lg"
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
let assigndata = {
|
|
||||||
building: forBuilding,
|
|
||||||
floor: forFloor,
|
|
||||||
workArea: forWorkArea,
|
|
||||||
workItem
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<tr>
|
|
||||||
<td className="text-start table-cell-small">
|
|
||||||
<i className="bx bx-right-arrow-alt"></i>
|
|
||||||
<span className="fw-medium">
|
|
||||||
{workItem.workItem.activityMaster
|
|
||||||
? workItem.workItem.activityMaster.activityName
|
|
||||||
: "NA"}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td className="text-center">
|
|
||||||
{workItem.workItem ? workItem.workItem.plannedWork : "NA"}
|
|
||||||
</td>
|
|
||||||
<td className="text-center">
|
|
||||||
{workItem.workItem ? workItem.workItem.completedWork : "NA"}
|
|
||||||
</td>
|
|
||||||
<td className="text-center" style={{ width: "15%" }}>
|
|
||||||
<div className="progress p-0">
|
|
||||||
<div
|
|
||||||
className="progress-bar"
|
|
||||||
role="progressbar"
|
|
||||||
style={{
|
|
||||||
width: getProgress(workItem.workItem.plannedWork, workItem.workItem.completedWork),
|
|
||||||
height: "10px",
|
|
||||||
}}
|
|
||||||
aria-valuenow={workItem.workItem ? workItem.workItem.completedWork : 0}
|
|
||||||
aria-valuemin="0"
|
|
||||||
aria-valuemax={workItem.workItem ? workItem.workItem.plannedWork : 0}
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div className="dropdown">
|
|
||||||
{!projectId && ( <button
|
|
||||||
aria-label="Modify"
|
|
||||||
type="button"
|
|
||||||
className="btn p-0"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
data-bs-target="#project-modal"
|
|
||||||
onClick={() =>
|
|
||||||
{
|
|
||||||
showCreateItemModal(assigndata)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span className="badge bg-label-primary me-1">Assign</span>
|
|
||||||
</button>)}
|
|
||||||
<button
|
|
||||||
aria-label="Modify"
|
|
||||||
type="button"
|
|
||||||
className="btn p-0 dropdown-toggle hide-arrow"
|
|
||||||
>
|
|
||||||
<i className="bx bxs-edit me-2 text-primary"></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
aria-label="Delete"
|
|
||||||
type="button"
|
|
||||||
className="btn p-0 dropdown-toggle hide-arrow"
|
|
||||||
>
|
|
||||||
<i className="bx bx-trash me-1 text-danger"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default WorkItem;
|
|
||||||
@ -1,20 +1,18 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import "./ProjectInfra.css";
|
import "./ProjectInfra.css";
|
||||||
import BuildingModel from "./Infrastructure/BuildingModel";
|
import BuildingModel from "./BuildingModel";
|
||||||
import FloorModel from "./Infrastructure/FloorModel";
|
import FloorModel from "./FloorModel";
|
||||||
import showToast from "../../services/toastService";
|
import showToast from "../../services/toastService";
|
||||||
import WorkAreaModel from "./Infrastructure/WorkAreaModel";
|
import WorkAreaModel from "./WorkAreaModel";
|
||||||
import TaskModel from "./Infrastructure/TaskModel";
|
import TaskModel from "./TaskModel";
|
||||||
import ProjectRepository, {TasksRepository} from "../../repositories/ProjectRepository";
|
import ProjectRepository from "../../repositories/ProjectRepository";
|
||||||
import ProjectModal from "./ProjectModal";
|
import ProjectModal from "./ProjectModal";
|
||||||
import {useHasUserPermission} from "../../hooks/useHasUserPermission";
|
import {useHasUserPermission} from "../../hooks/useHasUserPermission";
|
||||||
import {MANAGE_PROJECT_INFRA} from "../../utils/constants";
|
import {MANAGE_PROJECT_INFRA} from "../../utils/constants";
|
||||||
import InfraTable from "./Infrastructure/InfraTable";
|
// import AssignRoleModel from "./AssignRoleModel";
|
||||||
import {cacheData} from "../../slices/apiDataManager";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) => {
|
const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) => {
|
||||||
|
|
||||||
const [expandedBuildings, setExpandedBuildings] = useState([]);
|
const [expandedBuildings, setExpandedBuildings] = useState([]);
|
||||||
const [project, setProject] = useState(data);
|
const [project, setProject] = useState(data);
|
||||||
const[modalConfig,setModalConfig] = useState({type:null,data:null});
|
const[modalConfig,setModalConfig] = useState({type:null,data:null});
|
||||||
@ -29,8 +27,7 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
const [isAssignRoleModal,setIsAssingRoleModal] = useState(false)
|
const [isAssignRoleModal,setIsAssingRoleModal] = useState(false)
|
||||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||||
const [clearFormTrigger, setClearFormTrigger] = useState(false);
|
const [clearFormTrigger, setClearFormTrigger] = useState(false);
|
||||||
const [ CurrentBuilding, setCurrentBuilding ] = useState( "" )
|
const [CurrentBuilding,setCurrentBuilding] = useState("")
|
||||||
const [showModal, setShowModal] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setProject(data);
|
setProject(data);
|
||||||
@ -53,188 +50,6 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
setIsAssingRoleModal(true)
|
setIsAssingRoleModal(true)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const openBuildingModel = (projectData) => {
|
|
||||||
setIsBuildingModalOpen(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const submitData = async (infraObject) => {
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
console.log(infraObject)
|
|
||||||
let response = await ProjectRepository.manageProjectInfra( infraObject );
|
|
||||||
const entity = response.data;
|
|
||||||
|
|
||||||
const updatedProject = { ...project };
|
|
||||||
// Handle the building data
|
|
||||||
if (entity.building) {
|
|
||||||
const { id, name, description } = entity.building;
|
|
||||||
const updatedBuildings = updatedProject.buildings.map((building) =>
|
|
||||||
building.id === id
|
|
||||||
? { ...building, name, description }
|
|
||||||
: building
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add building if it doesn't exist
|
|
||||||
if (!updatedProject.buildings.some((building) => building.id === id)) {
|
|
||||||
updatedBuildings.push({
|
|
||||||
id: id,
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
floor: [],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
updatedProject.buildings = updatedBuildings;
|
|
||||||
|
|
||||||
// Update the cache for buildings
|
|
||||||
cacheData( "projectInfo", {projectId: updatedProject.id, data: updatedProject} );
|
|
||||||
setProject(updatedProject)
|
|
||||||
}
|
|
||||||
// Handle the floor data
|
|
||||||
else if ( entity.floor )
|
|
||||||
{
|
|
||||||
const { buildingId, id, floorName } = entity.floor;
|
|
||||||
const updatedBuildings = updatedProject.buildings.map((building) =>
|
|
||||||
building.id == buildingId
|
|
||||||
? {
|
|
||||||
...building,
|
|
||||||
floors: building.floors.map( ( floor ) =>
|
|
||||||
|
|
||||||
floor.id === id
|
|
||||||
? {
|
|
||||||
...floor,
|
|
||||||
floorName, // Update the floor name only
|
|
||||||
// Keep other properties as they are (including workArea)
|
|
||||||
}
|
|
||||||
: floor
|
|
||||||
)
|
|
||||||
// Add the new floor if it doesn't already exist
|
|
||||||
.concat(
|
|
||||||
!building.floors.some((floor) => floor.id === id)
|
|
||||||
? [{ id: id, floorName, workArea: null }] // New floor added with workArea set to null
|
|
||||||
: []
|
|
||||||
),
|
|
||||||
}
|
|
||||||
: building
|
|
||||||
);
|
|
||||||
|
|
||||||
updatedProject.buildings = updatedBuildings;
|
|
||||||
|
|
||||||
// Cache the updated project
|
|
||||||
cacheData( "projectInfo", {projectId: updatedProject.id, data: updatedProject} );
|
|
||||||
setProject(updatedProject)
|
|
||||||
}
|
|
||||||
// Handle the work area data
|
|
||||||
else if ( entity.workArea )
|
|
||||||
{
|
|
||||||
debugger
|
|
||||||
|
|
||||||
let buildingId = infraObject[0].workArea.buildingId
|
|
||||||
|
|
||||||
const { floorId, areaName, id } = entity.workArea;
|
|
||||||
// Check if the workArea exists, otherwise create a new one
|
|
||||||
const updatedBuildings = updatedProject.buildings.map((building) =>
|
|
||||||
building.id == buildingId
|
|
||||||
? {
|
|
||||||
...building,
|
|
||||||
floors: building.floors.map((floor) =>
|
|
||||||
floor.id == floorId
|
|
||||||
? {
|
|
||||||
...floor,
|
|
||||||
workAreas: floor.workAreas.some((workArea) => workArea.id === id)
|
|
||||||
? floor.workAreas.map((workArea) =>
|
|
||||||
workArea.id === id
|
|
||||||
? { ...workArea, areaName }
|
|
||||||
: workArea
|
|
||||||
)
|
|
||||||
: [
|
|
||||||
...floor.workAreas,
|
|
||||||
{ id, areaName, workItems: null },
|
|
||||||
],
|
|
||||||
}
|
|
||||||
: floor
|
|
||||||
),
|
|
||||||
}
|
|
||||||
: building
|
|
||||||
);
|
|
||||||
|
|
||||||
updatedProject.buildings = updatedBuildings;
|
|
||||||
|
|
||||||
// Update the cache for work areas
|
|
||||||
cacheData( "projectInfo", {projectId: updatedProject.id, data: updatedProject} );
|
|
||||||
setProject(updatedProject)
|
|
||||||
}
|
|
||||||
// Handle the task (workItem) data
|
|
||||||
else if (entity.workItem) {
|
|
||||||
const { buildingId, floorId, workAreaId, name, description } = entity.workItem;
|
|
||||||
const updatedBuildings = updatedProject.buildings.map((building) =>
|
|
||||||
building.id === buildingId
|
|
||||||
? {
|
|
||||||
...building,
|
|
||||||
floors: building.floors.map((floor) =>
|
|
||||||
floor.id === floorId
|
|
||||||
? {
|
|
||||||
...floor,
|
|
||||||
workAreas: floor.workAreas.map((workArea) =>
|
|
||||||
workArea.id === workAreaId
|
|
||||||
? {
|
|
||||||
...workArea,
|
|
||||||
tasks: workArea.tasks.map((task) =>
|
|
||||||
task.id === entity.workItem.id ? { ...task, name, description } : task
|
|
||||||
),
|
|
||||||
}
|
|
||||||
: workArea
|
|
||||||
),
|
|
||||||
}
|
|
||||||
: floor
|
|
||||||
),
|
|
||||||
}
|
|
||||||
: building
|
|
||||||
);
|
|
||||||
|
|
||||||
updatedProject.buildings = updatedBuildings;
|
|
||||||
|
|
||||||
|
|
||||||
cacheData("projectInfo", { projectId: updatedProject.id, data: updatedProject });
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
console.error("Unsupported data type for submitData", entity);
|
|
||||||
}
|
|
||||||
} catch ( Err )
|
|
||||||
{
|
|
||||||
showToast("Somthing wrong","error")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
handleClose()
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const closeBuildingModel = () => {
|
|
||||||
setIsBuildingModalOpen(false);
|
|
||||||
};
|
|
||||||
const handleBuildingModelFormSubmit = (buildingmodel) => {
|
|
||||||
if (buildingmodel.id == "" || buildingmodel.id == 0)
|
|
||||||
delete buildingmodel.id;
|
|
||||||
let data = [
|
|
||||||
{
|
|
||||||
building: buildingmodel,
|
|
||||||
floor: null,
|
|
||||||
workArea: null,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
submitData(data);
|
|
||||||
};
|
|
||||||
const handleFloorModelFormSubmit = (updatedFloor) => {
|
const handleFloorModelFormSubmit = (updatedFloor) => {
|
||||||
if (updatedFloor.id == "") delete updatedFloor.id;
|
if (updatedFloor.id == "") delete updatedFloor.id;
|
||||||
|
|
||||||
@ -247,13 +62,49 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const submitData = (infraObject) => {
|
||||||
|
ProjectRepository.manageProjectInfra(infraObject)
|
||||||
|
.then((response) => {
|
||||||
|
fetchData();
|
||||||
|
onDataChange("building-change");
|
||||||
|
showToast("Details updated successfully.", "success");
|
||||||
|
setClearFormTrigger(true); // Set trigger to true
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
showToast(error.message, "error");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const openBuildingModel = (projectData) => {
|
||||||
|
setIsBuildingModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeBuildingModel = () => {
|
||||||
|
setIsBuildingModalOpen(false);
|
||||||
|
};
|
||||||
|
const handleBuildingModelFormSubmit = (buildingmodel) => {
|
||||||
|
if (buildingmodel.id == "" || buildingmodel.id == 0)
|
||||||
|
delete buildingmodel.id;
|
||||||
|
|
||||||
|
let data = [
|
||||||
|
{
|
||||||
|
building: buildingmodel,
|
||||||
|
floor: null,
|
||||||
|
workArea: null,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
submitData(data);
|
||||||
|
};
|
||||||
|
|
||||||
const openWorkAreaModel = (projectData) => {
|
const openWorkAreaModel = (projectData) => {
|
||||||
setIsWorkAreaModalOpen(true);
|
setIsWorkAreaModalOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeWorkAreaModel = () => {
|
const closeWorkAreaModel = () => {
|
||||||
setIsWorkAreaModalOpen(false);
|
setIsWorkAreaModalOpen(false);
|
||||||
|
// const modalBackdrop = document.querySelector(".modal-backdrop");
|
||||||
|
// if (modalBackdrop) modalBackdrop.remove();
|
||||||
};
|
};
|
||||||
const handleWorkAreaModelFormSubmit = (updatedModel) => {
|
const handleWorkAreaModelFormSubmit = (updatedModel) => {
|
||||||
if (updatedModel.id == "") delete updatedModel.id;
|
if (updatedModel.id == "") delete updatedModel.id;
|
||||||
@ -273,18 +124,19 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
|
|
||||||
const closeTaskModel = () => {
|
const closeTaskModel = () => {
|
||||||
setIsTaskModalOpen(false);
|
setIsTaskModalOpen(false);
|
||||||
|
// const modalBackdrop = document.querySelector(".modal-backdrop");
|
||||||
|
// if (modalBackdrop) modalBackdrop.remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTaskModelFormSubmit = (updatedModel) => {
|
const handleTaskModelFormSubmit = (updatedModel) => {
|
||||||
if (updatedModel.id == "") updatedModel.id = 0;
|
if (updatedModel.id == "") updatedModel.id = 0;
|
||||||
|
|
||||||
|
//console.log("Form submitted:", updatedModel); // Replace this with an API call or state update
|
||||||
ProjectRepository.manageProjectTasks([updatedModel])
|
ProjectRepository.manageProjectTasks([updatedModel])
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
onDataChange("task-change");
|
onDataChange("task-change");
|
||||||
showToast("Details updated successfully.", "success");
|
showToast("Details updated successfully.", "success");
|
||||||
setClearFormTrigger(true);
|
setClearFormTrigger(true); // Set trigger to true
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
showToast(error.message, "error");
|
showToast(error.message, "error");
|
||||||
@ -297,54 +149,297 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getContent = (building) => {
|
||||||
|
let hasFloors =
|
||||||
|
building.floors && building.floors.length > 0 ? true : false;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{(() => {
|
||||||
|
if (hasFloors) {
|
||||||
|
return building.floors.map((floor) => (
|
||||||
|
<React.Fragment key={floor.id}>
|
||||||
|
|
||||||
|
{floor.workAreas.length > 0 ? (
|
||||||
|
floor.workAreas.map((workArea) => (
|
||||||
|
<React.Fragment key={workArea.id}>
|
||||||
|
<tr>
|
||||||
|
<td colSpan="4" className="text-start table-cell">
|
||||||
|
<div className="row ps-2">
|
||||||
|
<div className="col-6">
|
||||||
|
{" "}
|
||||||
|
<h6>
|
||||||
|
<span>
|
||||||
|
{" "}
|
||||||
|
{floor.floorName} - {workArea.areaName} {" "}
|
||||||
|
</span>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div className="col-6 text-end">
|
||||||
|
{/* <a
|
||||||
|
type="button"
|
||||||
|
className="text-end me-2"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#floor-model"
|
||||||
|
onClick={() => openFloorModel()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-edit-alt me-2"></i>
|
||||||
|
Edit Floor
|
||||||
|
</a> */}
|
||||||
|
|
||||||
|
{/* <a
|
||||||
|
type="button"
|
||||||
|
className="text-end"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#editproject"
|
||||||
|
onClick={() => openModal()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Add Activities
|
||||||
|
</a> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{workArea.workItems.length > 0 ? (
|
||||||
|
<tr className="overflow-auto" >
|
||||||
|
{" "}
|
||||||
|
<td colSpan={4} >
|
||||||
|
<table
|
||||||
|
className="table mx-1"
|
||||||
|
|
||||||
|
>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Activity</th>
|
||||||
|
<th>Planned</th>
|
||||||
|
<th>Complated</th>
|
||||||
|
<th>Progress</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="table-border-bottom-0">
|
||||||
|
{workArea.workItems.map((workItem) => (
|
||||||
|
<React.Fragment key={workItem.workItemId}>
|
||||||
|
<tr>
|
||||||
|
<td className="text-start table-cell-small">
|
||||||
|
<i className="bx bx-right-arrow-alt"></i>
|
||||||
|
<span className="fw-medium">
|
||||||
|
{workItem.workItem.activityMaster
|
||||||
|
? workItem.workItem.activityMaster
|
||||||
|
.activityName
|
||||||
|
: "NA"}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td className="text-center">
|
||||||
|
{workItem.workItem
|
||||||
|
? workItem.workItem.plannedWork
|
||||||
|
: "NA"}
|
||||||
|
</td>
|
||||||
|
<td className="text-center">
|
||||||
|
{workItem.workItem
|
||||||
|
? workItem.workItem.completedWork
|
||||||
|
: "NA"}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td
|
||||||
|
className="text-center"
|
||||||
|
style={{ width: "15%" }}
|
||||||
|
>
|
||||||
|
<div className="progress p-0">
|
||||||
|
<div
|
||||||
|
className="progress-bar"
|
||||||
|
role="progressbar"
|
||||||
|
style={{
|
||||||
|
width: getProgress(
|
||||||
|
workItem.workItem.plannedWork,
|
||||||
|
workItem.workItem.completedWork
|
||||||
|
),
|
||||||
|
height: "10px",
|
||||||
|
}}
|
||||||
|
aria-valuenow={
|
||||||
|
workItem.workItem
|
||||||
|
? workItem.workItem
|
||||||
|
.completedWork
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuemax={
|
||||||
|
workItem.workItem
|
||||||
|
? workItem.workItem.plannedWork
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div className="dropdown">
|
||||||
|
<button
|
||||||
|
aria-label="Modify"
|
||||||
|
type="button"
|
||||||
|
className="btn p-0 "
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#project-modal"
|
||||||
|
onClick={()=>{
|
||||||
|
// setModalConfig({type:"assignRole",data:{building,floor,workArea,workItem}})
|
||||||
|
handleModalData("assignRole",{building,floor,workArea,workItem})
|
||||||
|
// openAssignModel({building,floor,workArea,workItem})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="badge bg-label-primary me-1">Assign</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
aria-label="Modify"
|
||||||
|
type="button"
|
||||||
|
className="btn p-0 dropdown-toggle hide-arrow"
|
||||||
|
>
|
||||||
|
<i class="bx bxs-edit me-2 text-primary"></i>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
aria-label="Delete"
|
||||||
|
type="button"
|
||||||
|
className="btn p-0 dropdown-toggle hide-arrow"
|
||||||
|
>
|
||||||
|
<i className="bx bx-trash me-1 text-danger"></i>{" "}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>{" "}
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>{" "}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
) : (
|
||||||
|
<span></span>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<React.Fragment key={building.id + floor.id}>
|
||||||
|
<tr>
|
||||||
|
<td colSpan="4" className="text-start table-cell">
|
||||||
|
<div className="row ps-2">
|
||||||
|
<div className="col-6">
|
||||||
|
{" "}
|
||||||
|
<h6>
|
||||||
|
<span> {floor.floorName} </span>
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div className="col-6 text-end">
|
||||||
|
{/* <a
|
||||||
|
type="button"
|
||||||
|
className="text-end me-2"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#floor-model"
|
||||||
|
onClick={() => openFloorModel()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-edit-alt me-2"></i>
|
||||||
|
Edit Floor
|
||||||
|
</a> */}
|
||||||
|
|
||||||
|
{/* <a
|
||||||
|
type="button"
|
||||||
|
className="text-end"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#editproject"
|
||||||
|
onClick={() => openModal()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Add Work Area
|
||||||
|
</a> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</React.Fragment>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<p>No Floors Added, Please add them</p>
|
||||||
|
{/* <p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
className="btn btn-sm btn-danger m-1"
|
||||||
|
data-bs-target="#editproject"
|
||||||
|
onClick={() => openModal()}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Add Floors
|
||||||
|
</button>
|
||||||
|
</p> */}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})()}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getProgress = (planned, completed) => {
|
||||||
|
return (completed * 100) / planned + "%";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// common modal
|
||||||
|
|
||||||
const handleModalData = (type,modaldata)=>{
|
const handleModalData = (type,modaldata)=>{
|
||||||
setModalConfig({type:type,data:modaldata})
|
setModalConfig({type:type,data:modaldata})
|
||||||
}
|
}
|
||||||
const openModal = () => {
|
const openModal = () => {
|
||||||
const modalElement = document.getElementById('building-model');
|
setIsModalOpen(true);
|
||||||
const modal = new Modal(modalElement, {
|
|
||||||
backdrop: false,
|
|
||||||
keyboard: true,
|
|
||||||
focus: true
|
|
||||||
});
|
|
||||||
modal.show()
|
|
||||||
};
|
};
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
setIsModalOpen(false);
|
setIsModalOpen(false);
|
||||||
setModalConfig(null)
|
setModalConfig(null)
|
||||||
|
|
||||||
|
|
||||||
const modalElement = document.getElementById('building-model');
|
const modalElement = document.getElementById('project-modal');
|
||||||
if (modalElement) {
|
if (modalElement) {
|
||||||
modalElement.classList.remove('show'); // Remove modal visibility class
|
modalElement.classList.remove('show');
|
||||||
modalElement.style.display = 'none'; // Hide the modal element
|
modalElement.style.display = 'none'; // Hide modal visually
|
||||||
|
document.body.classList.remove('modal-open'); // Unlock body scroll
|
||||||
|
|
||||||
|
|
||||||
|
const backdropElement = document.querySelector('.modal-backdrop');
|
||||||
|
if (backdropElement) {
|
||||||
|
backdropElement.classList.remove('modal-backdrop'); // Remove backdrop class
|
||||||
|
backdropElement.style.display = 'none'; // Hide the backdrop element
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
const modalBackdropElement = document.querySelector('.modal-backdrop');
|
||||||
document.body.classList.remove('modal-open'); // Remove modal-open class from body
|
if (modalBackdropElement) {
|
||||||
|
modalBackdropElement.remove();
|
||||||
// Remove the modal backdrop
|
|
||||||
const backdropElement = document.querySelector('.modal-backdrop');
|
|
||||||
if (backdropElement) {
|
|
||||||
backdropElement.classList.remove('modal-backdrop'); // Remove backdrop class
|
|
||||||
backdropElement.style.display = 'none'; // Hide the backdrop element
|
|
||||||
}
|
}
|
||||||
document.body.style.overflow = 'auto';
|
document.body.style.overflow = 'auto';
|
||||||
|
|
||||||
};
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
if (modalConfig !== null) {
|
||||||
|
openModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [modalConfig,isModalOpen]);
|
||||||
|
|
||||||
const handleShow = () => setShowModal(true);
|
|
||||||
const handleClose = () => setShowModal( false );
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{isBuildingModalOpen && (
|
||||||
<div
|
<div
|
||||||
className={`modal fade ${showModal ? 'show' : ''}`}
|
className={`modal fade `}
|
||||||
tabIndex="-1"
|
id="building-model"
|
||||||
role="dialog"
|
tabIndex="-1"
|
||||||
style={{ display: showModal ? 'block' : 'none' }}
|
aria-hidden="true"
|
||||||
aria-hidden={!showModal}
|
>
|
||||||
>
|
|
||||||
<BuildingModel
|
<BuildingModel
|
||||||
project={data}
|
project={data}
|
||||||
onClose={closeBuildingModel}
|
onClose={closeBuildingModel}
|
||||||
@ -353,7 +448,7 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
onClearComplete={() => setClearFormTrigger(false)}
|
onClearComplete={() => setClearFormTrigger(false)}
|
||||||
></BuildingModel>
|
></BuildingModel>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{isFloorModalOpen && (
|
{isFloorModalOpen && (
|
||||||
<div
|
<div
|
||||||
@ -364,6 +459,7 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
>
|
>
|
||||||
<FloorModel
|
<FloorModel
|
||||||
project={data}
|
project={data}
|
||||||
|
// building={null}
|
||||||
onClose={closeFloorModel}
|
onClose={closeFloorModel}
|
||||||
onSubmit={handleFloorModelFormSubmit}
|
onSubmit={handleFloorModelFormSubmit}
|
||||||
clearTrigger={clearFormTrigger}
|
clearTrigger={clearFormTrigger}
|
||||||
@ -408,13 +504,16 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{/* common Modal */}
|
||||||
{isModalOpen && (
|
{isModalOpen && (
|
||||||
<ProjectModal modalConfig={modalConfig} closeModal={closeModal} />
|
<ProjectModal modalConfig={modalConfig} closeModal={closeModal} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="col-md-12 col-lg-12 col-xl-12 order-0 mb-4">
|
<div className="col-md-12 col-lg-12 col-xl-12 order-0 mb-4">
|
||||||
<div className="card">
|
<div className="card">
|
||||||
|
{/* <div className="card-header pb-4"></div> */}
|
||||||
|
|
||||||
<div className="card-body" style={{ padding: "0.5rem" }}>
|
<div className="card-body" style={{ padding: "0.5rem" }}>
|
||||||
<div className="align-items-center">
|
<div className="align-items-center">
|
||||||
@ -423,12 +522,14 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="link-button link-button-sm m-1 "
|
className="link-button link-button-sm m-1 "
|
||||||
|
data-bs-toggle="modal"
|
||||||
onClick={handleShow}
|
data-bs-target="#building-model"
|
||||||
|
onClick={() => openBuildingModel()}
|
||||||
>
|
>
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
Manage Building
|
Manage Building
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
@ -463,7 +564,48 @@ const ProjectInfra = ({ data, activityMaster, onDataChange,eachSiteEngineer }) =
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="row ">
|
<div className="row ">
|
||||||
<InfraTable buildings={project.buildings}/>
|
<div className="col-12 overflow-auto">
|
||||||
|
{buildings && buildings.length > 0 && (
|
||||||
|
<table className="table table-bordered ">
|
||||||
|
<tbody>
|
||||||
|
{buildings.map((building) => (
|
||||||
|
|
||||||
|
building.floors && building.floors.length > 0 && (
|
||||||
|
<React.Fragment key={building.id}>
|
||||||
|
<tr className="overflow-auto">
|
||||||
|
<td
|
||||||
|
colSpan="4"
|
||||||
|
className="text-start "
|
||||||
|
style={{
|
||||||
|
background: "#f0f0f0",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
onClick={() => toggleBuilding(building.id)}
|
||||||
|
>
|
||||||
|
<div className="row table-responsive">
|
||||||
|
<h5 style={{ marginBottom: "0px" }}>
|
||||||
|
|
||||||
|
{ building.name}
|
||||||
|
{expandedBuildings.includes(building.id) ? (
|
||||||
|
<i className="bx bx-chevron-down"></i>
|
||||||
|
) : (
|
||||||
|
<i className="bx bx-chevron-right"></i>
|
||||||
|
)}
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{expandedBuildings.includes(building.id) && getContent(building)}
|
||||||
|
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -25,8 +25,7 @@ const ProjectModal = ({modalConfig,closeModal}) => {
|
|||||||
|
|
||||||
{/* Modal Component */}
|
{/* Modal Component */}
|
||||||
|
|
||||||
{modalConfig?.type === "assignRole" && <AssignRole assignData={modalConfig?.data} onClose={closeModal} />}
|
{modalConfig?.type === "assignRole" && <AssignRole assignData={modalConfig?.data} onClose={closeModal} />}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -35,7 +35,7 @@ const ProjectNav = ( {onPillClick, activePill} ) =>
|
|||||||
<i className="bx bx-group bx-sm me-1_5"></i> Teams
|
<i className="bx bx-group bx-sm me-1_5"></i> Teams
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li className={`nav-item ${!HasViewInfraStructure && 'd-none'} `}>
|
<li className={`nav-item ${HasViewInfraStructure ? "":"d-none"} `}>
|
||||||
<a
|
<a
|
||||||
className={`nav-link ${activePill === "infra" ? "active" : ""}`}
|
className={`nav-link ${activePill === "infra" ? "active" : ""}`}
|
||||||
href="#"
|
href="#"
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import {useEmployeesByProjectAllocated} from "../../hooks/useProjects";
|
|||||||
|
|
||||||
const ProjectOverview = ({project}) =>
|
const ProjectOverview = ({project}) =>
|
||||||
{
|
{
|
||||||
const {projectEmployees} = useEmployeesByProjectAllocated( project?.id );
|
const {projectEmployees} = useEmployeesByProjectAllocated( project.id );
|
||||||
let teamSize = projectEmployees.filter( ( emp ) => emp.isActive )
|
let teamSize = projectEmployees.filter( ( emp ) => emp.isActive )
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -14,10 +14,9 @@ const TaskModel = ({
|
|||||||
onSubmit,
|
onSubmit,
|
||||||
clearTrigger,
|
clearTrigger,
|
||||||
onClearComplete,
|
onClearComplete,
|
||||||
} ) =>
|
}) => {
|
||||||
{
|
|
||||||
|
|
||||||
const [formData, setFormData] = useState(defaultModel);
|
const [formData, setFormData] = useState(defaultModel);
|
||||||
|
|
||||||
const [selectedBuilding, setSelectedBuilding] = useState(null);
|
const [selectedBuilding, setSelectedBuilding] = useState(null);
|
||||||
const [selectedFloor, setSelectedFloor] = useState(null);
|
const [selectedFloor, setSelectedFloor] = useState(null);
|
||||||
const [selectedWorkArea, setSelectedWorkArea] = useState(null);
|
const [selectedWorkArea, setSelectedWorkArea] = useState(null);
|
||||||
@ -48,8 +47,8 @@ const TaskModel = ({
|
|||||||
if (clearTrigger) {
|
if (clearTrigger) {
|
||||||
let model = defaultModel;
|
let model = defaultModel;
|
||||||
model.floorId = selectedFloor.id;
|
model.floorId = selectedFloor.id;
|
||||||
setFormData(defaultModel);
|
setFormData(defaultModel); // Clear form
|
||||||
onClearComplete();
|
onClearComplete(); // Notify parent that clearing is done
|
||||||
}
|
}
|
||||||
}, [clearTrigger, onClearComplete]);
|
}, [clearTrigger, onClearComplete]);
|
||||||
|
|
||||||
@ -111,8 +110,7 @@ const TaskModel = ({
|
|||||||
const handleSubmit = (e) => {
|
const handleSubmit = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// onSubmit( formData ); // Pass the updated data to the parent
|
onSubmit(formData); // Pass the updated data to the parent
|
||||||
console.log(formData)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
230
src/components/Project/WorkAreaModel.jsx
Normal file
230
src/components/Project/WorkAreaModel.jsx
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
|
const defaultModel = {
|
||||||
|
id: "0",
|
||||||
|
areaName: "",
|
||||||
|
floorId: "0",
|
||||||
|
};
|
||||||
|
|
||||||
|
const WorkAreaModel = ({
|
||||||
|
project,
|
||||||
|
onSubmit,
|
||||||
|
clearTrigger,
|
||||||
|
onClearComplete,
|
||||||
|
}) => {
|
||||||
|
const [formData, setFormData] = useState(defaultModel);
|
||||||
|
|
||||||
|
const [selectedBuilding, setSelectedBuilding] = useState(null);
|
||||||
|
const [selectedFloor, setSelectedFloor] = useState(null);
|
||||||
|
|
||||||
|
//if (floor && floor.id) setFormData(floor);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedBuilding) {
|
||||||
|
let building = project.buildings.find(
|
||||||
|
(b) => b.id === selectedBuilding.id
|
||||||
|
);
|
||||||
|
setSelectedBuilding(building);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedFloor) {
|
||||||
|
let floor = selectedBuilding.floors.find(
|
||||||
|
(b) => b.id === Number(selectedFloor.id)
|
||||||
|
);
|
||||||
|
setSelectedFloor(floor);
|
||||||
|
}
|
||||||
|
}, [project]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (clearTrigger) {
|
||||||
|
let model = defaultModel;
|
||||||
|
model.floorId = selectedFloor.id;
|
||||||
|
setFormData(defaultModel); // Clear form
|
||||||
|
onClearComplete(); // Notify parent that clearing is done
|
||||||
|
}
|
||||||
|
}, [clearTrigger, onClearComplete]);
|
||||||
|
|
||||||
|
// Handle input change
|
||||||
|
const handleChange = (e) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
setFormData({ ...formData, [name]: value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleWorkAreaChange = (e) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
const workArea = selectedFloor.workAreas.find(
|
||||||
|
(b) => b.id === Number(value)
|
||||||
|
);
|
||||||
|
if (workArea) {
|
||||||
|
setFormData({
|
||||||
|
id: workArea.id,
|
||||||
|
floorId: workArea.floorId,
|
||||||
|
areaName: workArea.areaName,
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
setFormData({
|
||||||
|
id: "0",
|
||||||
|
floorId: selectedFloor.id,
|
||||||
|
areaName: "",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFloorChange = (e) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
const floor = selectedBuilding.floors.find((b) => b.id === Number(value));
|
||||||
|
setSelectedFloor(floor);
|
||||||
|
if (floor) {
|
||||||
|
setFormData({
|
||||||
|
id: "0",
|
||||||
|
floorId: floor.id,
|
||||||
|
areaName: "",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setSelectedFloor(null);
|
||||||
|
setFormData({
|
||||||
|
id: "0",
|
||||||
|
floorId: "0",
|
||||||
|
areaName: "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleBuildigChange = (e) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
const building = project.buildings.find((b) => b.id === Number(value));
|
||||||
|
setSelectedBuilding(building);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle form submission
|
||||||
|
const handleSubmit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
formData.projectId = project.id;
|
||||||
|
|
||||||
|
onSubmit(formData); // Pass the updated data to the parent
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="modal-dialog modal-lg modal-simple modal-edit-user">
|
||||||
|
<div className="modal-content">
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="row">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-close"
|
||||||
|
data-bs-dismiss="modal"
|
||||||
|
aria-label="Close"
|
||||||
|
></button>
|
||||||
|
<div className="text-center mb-1">
|
||||||
|
<h5 className="mb-1">Manage Work Area</h5>
|
||||||
|
</div>
|
||||||
|
<form className="row g-2" onSubmit={handleSubmit}>
|
||||||
|
<div className="col-6 col-md-6">
|
||||||
|
<label className="form-label" htmlFor="name">
|
||||||
|
Select Building
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="buildingId"
|
||||||
|
name="buildingId"
|
||||||
|
className="select2 form-select form-select-sm"
|
||||||
|
aria-label="Default select example"
|
||||||
|
onChange={handleBuildigChange}
|
||||||
|
value={formData.buildingId}
|
||||||
|
>
|
||||||
|
<option value="0">Select Building</option>
|
||||||
|
{project.buildings.map((building) => (
|
||||||
|
<option key={building.id} value={building.id}>
|
||||||
|
{building.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{selectedBuilding && selectedBuilding.buildingId != "0" && (
|
||||||
|
<div className="col-6 col-md-6">
|
||||||
|
<label className="form-label" htmlFor="floorId">
|
||||||
|
Select Floor
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="floorId"
|
||||||
|
name="floorId"
|
||||||
|
className="select2 form-select form-select-sm"
|
||||||
|
aria-label="Default select example"
|
||||||
|
onChange={handleFloorChange}
|
||||||
|
value={formData.floorId}
|
||||||
|
>
|
||||||
|
<option value="0">Select Floor</option>
|
||||||
|
{selectedBuilding.floors.map((floor) => (
|
||||||
|
<option key={floor.id} value={floor.id}>
|
||||||
|
{floor.floorName}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{formData.floorId != "0" && (
|
||||||
|
<div className="col-12 col-md-12">
|
||||||
|
<label className="form-label" htmlFor="floorId">
|
||||||
|
Select Work Area
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="floorId"
|
||||||
|
name="floorId"
|
||||||
|
className="select2 form-select form-select-sm"
|
||||||
|
aria-label="Default select example"
|
||||||
|
onChange={handleWorkAreaChange}
|
||||||
|
value={formData.floorId}
|
||||||
|
>
|
||||||
|
<option value="0">Create New Work Area</option>
|
||||||
|
{selectedFloor.workAreas.map((workArea) => (
|
||||||
|
<option key={workArea.id} value={workArea.id}>
|
||||||
|
{workArea.areaName}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{formData.floorId != "0" && (
|
||||||
|
<div className="col-12 col-md-12">
|
||||||
|
{" "}
|
||||||
|
<label className="form-label" htmlFor="areaName">
|
||||||
|
{formData.id != "0" ? "Modify " : "Enter "} Work Area Name
|
||||||
|
</label>
|
||||||
|
<div className="input-group">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="areaName"
|
||||||
|
name="areaName"
|
||||||
|
className="form-control form-control-sm me-2"
|
||||||
|
placeholder="Work Area"
|
||||||
|
onChange={handleChange}
|
||||||
|
value={formData.areaName}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="col-12 text-center">
|
||||||
|
{formData.floorId != "0" && (
|
||||||
|
<button type="submit" className="btn btn-primary me-3">
|
||||||
|
{formData.id != "0" && formData.id != ""
|
||||||
|
? "Edit Work Area"
|
||||||
|
: "Add Work Area"}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
type="reset"
|
||||||
|
className="btn btn-label-secondary"
|
||||||
|
data-bs-dismiss="modal"
|
||||||
|
aria-label="Close"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WorkAreaModel;
|
||||||
@ -41,7 +41,6 @@ const useMaster = () => {
|
|||||||
break;
|
break;
|
||||||
case "Job Role":
|
case "Job Role":
|
||||||
response = await MasterRespository.getJobRole();
|
response = await MasterRespository.getJobRole();
|
||||||
response = response.data
|
|
||||||
break;
|
break;
|
||||||
case "Module":
|
case "Module":
|
||||||
response = [{description: null,module:"Module 1",featurePermission: null,id: "08dd4761-363c-49ed-8851-3d2489a3e98d"},{description: null,module:"Module 2",featurePermission: null,id: "08dy9761-363c-49ed-8851-3d2489a3e98d"},{description: null,module:"Module 3",featurePermission: null,id: "08dy7761-263c-49ed-8851-3d2489a3e98d"}];
|
response = [{description: null,module:"Module 1",featurePermission: null,id: "08dd4761-363c-49ed-8851-3d2489a3e98d"},{description: null,module:"Module 2",featurePermission: null,id: "08dy9761-363c-49ed-8851-3d2489a3e98d"},{description: null,module:"Module 3",featurePermission: null,id: "08dy7761-263c-49ed-8851-3d2489a3e98d"}];
|
||||||
|
|||||||
@ -16,9 +16,9 @@ export const useMasterRole =()=>{
|
|||||||
if (!features_cache) {
|
if (!features_cache) {
|
||||||
MasterRespository.getRoles()
|
MasterRespository.getRoles()
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setMasterRole(response.data);
|
setMasterRole(response);
|
||||||
|
|
||||||
cacheData("masterRole", response.data);
|
cacheData("masterRole", response);
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@ -55,9 +55,9 @@ export const useFeatures =()=> {
|
|||||||
if (!features_cache) {
|
if (!features_cache) {
|
||||||
MasterRespository.getFeatures()
|
MasterRespository.getFeatures()
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setMasterFeatures(response.data);
|
setMasterFeatures(response);
|
||||||
|
|
||||||
cacheData("features", response.data);
|
cacheData("features", response);
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
|||||||
@ -18,8 +18,8 @@ export const useProfile = () =>
|
|||||||
{
|
{
|
||||||
setLoading( true )
|
setLoading( true )
|
||||||
let response = await AuthRepository.profile();
|
let response = await AuthRepository.profile();
|
||||||
setProfile( response.data )
|
setProfile( response )
|
||||||
cacheProfileData( response.data )
|
cacheProfileData( response )
|
||||||
setLoading( false );
|
setLoading( false );
|
||||||
|
|
||||||
} catch ( error )
|
} catch ( error )
|
||||||
|
|||||||
@ -5,10 +5,9 @@ import {
|
|||||||
} from "../slices/apiDataManager"
|
} from "../slices/apiDataManager"
|
||||||
import ProjectRepository from "../repositories/ProjectRepository";
|
import ProjectRepository from "../repositories/ProjectRepository";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const useProjects =()=>{
|
export const useProjects =()=>{
|
||||||
|
|
||||||
const [projects, setProjects] = useState([]);
|
const [projects, setProjects] = useState([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
@ -20,9 +19,9 @@ export const useProjects =()=>{
|
|||||||
setLoading(true)
|
setLoading(true)
|
||||||
ProjectRepository.getProjectList()
|
ProjectRepository.getProjectList()
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setProjects(response.data);
|
setProjects(response);
|
||||||
|
|
||||||
cacheData("projectslist", response.data);
|
cacheData("projectslist", response);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@ -37,8 +36,7 @@ export const useProjects =()=>{
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
fetchData()
|
fetchData()
|
||||||
|
|
||||||
},[])
|
},[])
|
||||||
|
|
||||||
return { projects,loading,error,refetch:fetchData}
|
return { projects,loading,error,refetch:fetchData}
|
||||||
@ -86,18 +84,18 @@ export const useEmployeesByProjectAllocated = ( selectedProject ) =>
|
|||||||
export const useProjectDetails =(projectId)=>{
|
export const useProjectDetails =(projectId)=>{
|
||||||
|
|
||||||
const [projects_Details, setProject_Details] = useState(null);
|
const [projects_Details, setProject_Details] = useState(null);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
const project_cache = getCachedData("projectInfo");
|
const project_cache = getCachedData(`projectinfo-${projectId}`);
|
||||||
if (!project_cache || project_cache?.projectId !== projectId) {
|
if (!project_cache) {
|
||||||
ProjectRepository.getProjectByprojectId(projectId)
|
ProjectRepository.getProjectByprojectId(projectId)
|
||||||
.then( ( response ) =>
|
.then( ( response ) =>
|
||||||
{
|
{
|
||||||
setProject_Details( response.data );
|
setProject_Details(response);
|
||||||
cacheData("projectInfo", {projectId,data: response.data} );
|
cacheData( `projectinfo-${ projectId }`, response );
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@ -106,17 +104,15 @@ export const useProjectDetails =(projectId)=>{
|
|||||||
setLoading(false)
|
setLoading(false)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setProject_Details( project_cache.data );
|
setProject_Details( project_cache );
|
||||||
|
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};;
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if ( projectId )
|
fetchData()
|
||||||
{
|
|
||||||
fetchData()
|
|
||||||
}
|
|
||||||
},[projectId])
|
},[projectId])
|
||||||
|
|
||||||
return { projects_Details,loading,error,refetch:fetchData}
|
return { projects_Details,loading,error,refetch:fetchData}
|
||||||
|
|||||||
@ -6,17 +6,14 @@ import App from './App.tsx'
|
|||||||
|
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { store } from './store/store';
|
import { store } from './store/store';
|
||||||
import { ModalProvider } from './ModalContext.jsx';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
// <StrictMode>
|
// <StrictMode>
|
||||||
// <MasterDataProvider>
|
// <MasterDataProvider>
|
||||||
<Provider store={ store }>
|
<Provider store={store}>
|
||||||
<ModalProvider>
|
<App />
|
||||||
<App />
|
|
||||||
</ModalProvider>
|
|
||||||
</Provider>
|
</Provider>
|
||||||
// </MasterDataProvider>
|
// </MasterDataProvider>
|
||||||
|
|
||||||
|
|||||||
@ -91,11 +91,8 @@ const AttendancePage = () =>
|
|||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
setAttendances(attendance)
|
setAttendances(attendance)
|
||||||
},[attendance])
|
},[attendance])
|
||||||
useEffect( () =>
|
|
||||||
{
|
|
||||||
dispatch(setProjectId(projects[0]?.id))
|
|
||||||
},[projects])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isCreateModalOpen && modelConfig && (
|
{isCreateModalOpen && modelConfig && (
|
||||||
|
|||||||
@ -14,6 +14,18 @@ const DailyTask =()=>{
|
|||||||
<div className="card card-action mb-6">
|
<div className="card card-action mb-6">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
|
{/* <div className="col-12 text-end mb-1">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="link-button link-button-sm m-1"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#user-model"
|
||||||
|
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Assign Employee
|
||||||
|
</button>
|
||||||
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
<div className="table-responsive text-nowrap">
|
<div className="table-responsive text-nowrap">
|
||||||
{/* {employees && employees.length > 0 ? ( */}
|
{/* {employees && employees.length > 0 ? ( */}
|
||||||
|
|||||||
@ -25,12 +25,22 @@ const TaskPlannng = () => {
|
|||||||
if (!activities_cache) {
|
if (!activities_cache) {
|
||||||
ActivityeRepository.getActivities()
|
ActivityeRepository.getActivities()
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setActivities(response.data);
|
setActivities(response);
|
||||||
cacheData("activitiesMaster", response.data);
|
cacheData("activitiesMaster", response);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
setError("Failed to fetch data.");
|
setError("Failed to fetch data.");
|
||||||
});
|
});
|
||||||
|
// api
|
||||||
|
// .get("/api/task/activities")
|
||||||
|
// .then((data) => {
|
||||||
|
// setActivities(data);
|
||||||
|
// dispatch(cacheApiResponse({ key: "activitiesMaster", data: data }));
|
||||||
|
// })
|
||||||
|
// .catch((error) => {
|
||||||
|
// console.error(error);
|
||||||
|
// setError("Failed to fetch data.");
|
||||||
|
// });
|
||||||
} else {
|
} else {
|
||||||
setActivities(activities_cache);
|
setActivities(activities_cache);
|
||||||
}
|
}
|
||||||
@ -58,6 +68,21 @@ const TaskPlannng = () => {
|
|||||||
} else {
|
} else {
|
||||||
setProjectDetails(project_cache);
|
setProjectDetails(project_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// api
|
||||||
|
// .get(`/api/project/details/${projectId}`)
|
||||||
|
// .then((data) => {
|
||||||
|
// setProjectDetails(data);
|
||||||
|
// setProject(data);
|
||||||
|
// dispatch(
|
||||||
|
// cacheApiResponse({ key: `projectinfo-${projectId}`, data: data })
|
||||||
|
// );
|
||||||
|
// setLoading(false);
|
||||||
|
// })
|
||||||
|
// .catch((error) => {
|
||||||
|
// console.error(error);
|
||||||
|
// setError("Failed to fetch data.");
|
||||||
|
// });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
setError("Failed to fetch data.");
|
setError("Failed to fetch data.");
|
||||||
@ -96,7 +121,7 @@ const TaskPlannng = () => {
|
|||||||
<InfraPlanning
|
<InfraPlanning
|
||||||
data={projectDetails}
|
data={projectDetails}
|
||||||
activityMaster={activities}
|
activityMaster={activities}
|
||||||
onDataChange={handleDataChange}
|
onDataChange={handleDataChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -4,55 +4,45 @@ import { AuthWrapper } from "./AuthWrapper"
|
|||||||
import "./page-auth.css";
|
import "./page-auth.css";
|
||||||
import AuthRepository from "../../repositories/AuthRepository";
|
import AuthRepository from "../../repositories/AuthRepository";
|
||||||
import showToast from "../../services/toastService";
|
import showToast from "../../services/toastService";
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
import {z} from "zod";
|
|
||||||
|
|
||||||
|
|
||||||
const forgotPassSceham = z.object( {
|
|
||||||
email: z.string().email(),
|
|
||||||
} )
|
|
||||||
|
|
||||||
const ForgotPasswordPage = () => {
|
const ForgotPasswordPage = () => {
|
||||||
|
const [ email, setEmail ] = useState( "" );
|
||||||
const[loding,setLoading] = useState(false)
|
const[loding,setLoading] = useState(false)
|
||||||
|
|
||||||
const {register,
|
const handleChange = (e) => {
|
||||||
handleSubmit,
|
setEmail(e.target.value);
|
||||||
formState: { errors },
|
};
|
||||||
reset,
|
|
||||||
getValues } = useForm( {
|
|
||||||
resolver: zodResolver( forgotPassSceham ),
|
|
||||||
defaultValues: {
|
|
||||||
email:""
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const onSubmit = async (data) =>
|
const handleSubmit = async ( e ) =>
|
||||||
{
|
{
|
||||||
|
setLoading(true)
|
||||||
|
e.preventDefault();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
setLoading(true)
|
const response = await AuthRepository.forgotPassword({email})
|
||||||
const response = await AuthRepository.forgotPassword(data)
|
|
||||||
if ( response.data && response.success )
|
if ( response.data && response.success )
|
||||||
|
{
|
||||||
showToast( response.message, "success" )
|
showToast( response.message, "success" )
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
showToast( response.message, "warning" )
|
||||||
|
}
|
||||||
setLoading( false )
|
setLoading( false )
|
||||||
setEmail( "" )
|
setEmail("")
|
||||||
console.log(response)
|
} catch ( error )
|
||||||
} catch ( err )
|
|
||||||
{
|
{
|
||||||
|
showToast( "User Not Found", "error" )
|
||||||
showToast( err.message, "error" )
|
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
return (
|
return (
|
||||||
<AuthWrapper>
|
<AuthWrapper>
|
||||||
<h4 className="mb-2">Forgot Password? 🔒</h4>
|
<h4 className="mb-2">Forgot Password? 🔒</h4>
|
||||||
<p className="mb-4">
|
<p className="mb-4">
|
||||||
Enter your email and we'll send you instructions to reset your password
|
Enter your email and we'll send you instructions to reset your password
|
||||||
</p>
|
</p>
|
||||||
<form id="formAuthentication" className="mb-3" onSubmit={handleSubmit(onSubmit)}>
|
<form id="formAuthentication" className="mb-3" onSubmit={handleSubmit}>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="email" className="form-label">
|
<label htmlFor="email" className="form-label">
|
||||||
Email
|
Email
|
||||||
@ -62,18 +52,11 @@ const ForgotPasswordPage = () => {
|
|||||||
className="form-control"
|
className="form-control"
|
||||||
id="email"
|
id="email"
|
||||||
name="email"
|
name="email"
|
||||||
{...register("email")}
|
value={email}
|
||||||
|
onChange={handleChange}
|
||||||
placeholder="Enter your email"
|
placeholder="Enter your email"
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
{errors.email && (
|
|
||||||
<div
|
|
||||||
className="danger-text text-start"
|
|
||||||
style={{ fontSize: "12px" }}
|
|
||||||
>
|
|
||||||
{errors.email.message}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<button aria-label="Click me" className="btn btn-primary d-grid w-100">
|
<button aria-label="Click me" className="btn btn-primary d-grid w-100">
|
||||||
{loding ? "Please Wait...":"Send Reset Link"}
|
{loding ? "Please Wait...":"Send Reset Link"}
|
||||||
|
|||||||
@ -5,40 +5,39 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import "./page-auth.css";
|
import "./page-auth.css";
|
||||||
import AuthRepository from "../../repositories/AuthRepository";
|
import AuthRepository from "../../repositories/AuthRepository";
|
||||||
import showToast from "../../services/toastService";
|
import showToast from "../../services/toastService";
|
||||||
import { useForm } from "react-hook-form";
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
|
||||||
import {z} from "zod"
|
|
||||||
|
|
||||||
const loginScheam = z.object( {
|
|
||||||
username: z.string().email(),
|
|
||||||
password: z.string().min( 1, {message: "Password required"} ),
|
|
||||||
rememberMe: z.boolean(),
|
|
||||||
} )
|
|
||||||
|
|
||||||
const LoginPage = () => {
|
const LoginPage = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const {register,
|
const [formData, setFormData] = useState({
|
||||||
handleSubmit,
|
password: "",
|
||||||
formState: { errors },
|
username: "",
|
||||||
reset,
|
rememberMe: false,
|
||||||
getValues } = useForm( {
|
});
|
||||||
resolver: zodResolver( loginScheam ),
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
const onSubmit = async ( data ) =>
|
const handleChange = (e) => {
|
||||||
{
|
const { name, value, type, checked } = e.target;
|
||||||
|
|
||||||
|
setFormData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
[name]: type === "checkbox" ? checked : value,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async ( e ) =>
|
||||||
|
{
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
let data = {
|
||||||
let userCredential = {
|
username: formData.username,
|
||||||
username: data.username,
|
password: formData.password,
|
||||||
password:data.password
|
};
|
||||||
}
|
|
||||||
const response = await AuthRepository.login(userCredential);
|
const response = await AuthRepository.login(data);
|
||||||
localStorage.setItem("jwtToken", response.data.token);
|
localStorage.setItem("jwtToken", response.data.token);
|
||||||
localStorage.setItem( "refreshToken", response.data.refreshToken );
|
localStorage.setItem( "refreshToken", response.data.refreshToken );
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@ -46,9 +45,9 @@ const LoginPage = () => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("Unable to proceed. Please try again.");
|
console.log("Unable to proceed. Please try again.");
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthWrapper>
|
<AuthWrapper>
|
||||||
<h4 className="mb-2">Welcome to PMS!</h4>
|
<h4 className="mb-2">Welcome to PMS!</h4>
|
||||||
@ -56,7 +55,7 @@ const LoginPage = () => {
|
|||||||
Please sign-in to your account and start the adventure
|
Please sign-in to your account and start the adventure
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<form id="formAuthentication" className="mb-3" onSubmit={handleSubmit(onSubmit)}>
|
<form id="formAuthentication" className="mb-3" onSubmit={handleSubmit}>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label htmlFor="username" className="form-label">
|
<label htmlFor="username" className="form-label">
|
||||||
Email or Username
|
Email or Username
|
||||||
@ -65,19 +64,12 @@ const LoginPage = () => {
|
|||||||
type="text"
|
type="text"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
id="username"
|
id="username"
|
||||||
{...register("username")}
|
value={formData.name}
|
||||||
|
onChange={handleChange}
|
||||||
name="username"
|
name="username"
|
||||||
placeholder="Enter your email or username"
|
placeholder="Enter your email or username"
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
{errors.username && (
|
|
||||||
<div
|
|
||||||
className="danger-text text-start"
|
|
||||||
style={{ fontSize: "12px" }}
|
|
||||||
>
|
|
||||||
{errors.username.message}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 form-password-toggle">
|
<div className="mb-3 form-password-toggle">
|
||||||
<div className="d-flex justify-content-between">
|
<div className="d-flex justify-content-between">
|
||||||
@ -96,7 +88,8 @@ const LoginPage = () => {
|
|||||||
type="password"
|
type="password"
|
||||||
autoComplete="true"
|
autoComplete="true"
|
||||||
id="password"
|
id="password"
|
||||||
{...register("password")}
|
value={formData.password}
|
||||||
|
onChange={handleChange}
|
||||||
className="form-control"
|
className="form-control"
|
||||||
name="password"
|
name="password"
|
||||||
placeholder="············"
|
placeholder="············"
|
||||||
@ -104,14 +97,6 @@ const LoginPage = () => {
|
|||||||
/>
|
/>
|
||||||
<span className="input-group-text cursor-pointer"></span>
|
<span className="input-group-text cursor-pointer"></span>
|
||||||
</div>
|
</div>
|
||||||
{errors.password && (
|
|
||||||
<div
|
|
||||||
className="danger-text text-start"
|
|
||||||
style={{ fontSize: "12px" }}
|
|
||||||
>
|
|
||||||
{errors.password.message}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<div className="form-check">
|
<div className="form-check">
|
||||||
@ -120,7 +105,8 @@ const LoginPage = () => {
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="remember-me"
|
id="remember-me"
|
||||||
name="rememberMe"
|
name="rememberMe"
|
||||||
{...register("rememberMe")}
|
checked={formData.rememberMe}
|
||||||
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label" htmlFor="remember-me">
|
<label className="form-check-label" htmlFor="remember-me">
|
||||||
{" "}
|
{" "}
|
||||||
|
|||||||
@ -16,19 +16,18 @@ import ProjectRepository from "../../repositories/ProjectRepository";
|
|||||||
import { ActivityeRepository } from "../../repositories/MastersRepository";
|
import { ActivityeRepository } from "../../repositories/MastersRepository";
|
||||||
|
|
||||||
import "./ProjectDetails.css";
|
import "./ProjectDetails.css";
|
||||||
import {useEmployeesByProjectAllocated, useProjectDetails} from "../../hooks/useProjects";
|
import {useEmployeesByProjectAllocated} from "../../hooks/useProjects";
|
||||||
|
|
||||||
|
|
||||||
const ProjectDetails = () => {
|
const ProjectDetails = () => {
|
||||||
let {projectId} = useParams();
|
let { projectId } = useParams();
|
||||||
const {projects_Details,loading:projectLoading,error:ProjectError} = useProjectDetails(projectId)
|
|
||||||
|
|
||||||
const [project, setProject] = useState(null);
|
const [project, setProject] = useState(null);
|
||||||
const [ projectDetails, setProjectDetails ] = useState( null );
|
const [ projectDetails, setProjectDetails ] = useState( null );
|
||||||
const [activities, setActivities] = useState(null);
|
const [activities, setActivities] = useState(null);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [ error, setError ] = useState( "" );
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
const fetchActivities = async () => {
|
const fetchActivities = async () => {
|
||||||
|
|
||||||
const activities_cache = getCachedData("activitiesMaster");
|
const activities_cache = getCachedData("activitiesMaster");
|
||||||
@ -36,8 +35,8 @@ const ProjectDetails = () => {
|
|||||||
if (!activities_cache) {
|
if (!activities_cache) {
|
||||||
ActivityeRepository.getActivities()
|
ActivityeRepository.getActivities()
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setActivities(response.data);
|
setActivities(response);
|
||||||
cacheData("activitiesMaster", response.data);
|
cacheData("activitiesMaster", response);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
setError("Failed to fetch data.");
|
setError("Failed to fetch data.");
|
||||||
@ -51,14 +50,14 @@ const ProjectDetails = () => {
|
|||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
|
||||||
const project_cache = getCachedData("projectInfo");
|
const project_cache = getCachedData(`projectinfo-${projectId}`);
|
||||||
if (!project_cache || project_cache?.projectId !== projectId) {
|
if (!project_cache) {
|
||||||
ProjectRepository.getProjectByprojectId(projectId)
|
ProjectRepository.getProjectByprojectId(projectId)
|
||||||
.then( ( response ) =>
|
.then( ( response ) =>
|
||||||
{
|
{
|
||||||
setProjectDetails( response.data );
|
setProjectDetails(response);
|
||||||
setProject( response.data );
|
setProject(response);
|
||||||
cacheData("projectInfo", {projectId,data: response.data} );
|
cacheData( `projectinfo-${ projectId }`, response );
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@ -67,14 +66,13 @@ const ProjectDetails = () => {
|
|||||||
setLoading(false)
|
setLoading(false)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setProjectDetails( project_cache.data );
|
setProjectDetails( project_cache );
|
||||||
setProject( project_cache.data );
|
setProject( project_cache );
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const [activePill, setActivePill] = useState("profile");
|
const [activePill, setActivePill] = useState("profile");
|
||||||
|
|
||||||
|
|
||||||
@ -88,7 +86,7 @@ const ProjectDetails = () => {
|
|||||||
|
|
||||||
|
|
||||||
const renderContent = () => {
|
const renderContent = () => {
|
||||||
if (projectLoading) return <Loader></Loader>;
|
if (loading) return <Loader></Loader>;
|
||||||
switch (activePill) {
|
switch (activePill) {
|
||||||
case "profile": {
|
case "profile": {
|
||||||
return (
|
return (
|
||||||
@ -154,16 +152,13 @@ const ProjectDetails = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// fetchData();
|
fetchData();
|
||||||
setProject( projects_Details )
|
|
||||||
setProjectDetails(projects_Details)
|
|
||||||
fetchActivities();
|
fetchActivities();
|
||||||
}, [projects_Details]);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<>
|
<>
|
||||||
{}
|
|
||||||
<div className="container-xxl flex-grow-1 container-p-y">
|
<div className="container-xxl flex-grow-1 container-p-y">
|
||||||
<Breadcrumb
|
<Breadcrumb
|
||||||
data={[
|
data={[
|
||||||
@ -174,8 +169,8 @@ const ProjectDetails = () => {
|
|||||||
></Breadcrumb>
|
></Breadcrumb>
|
||||||
|
|
||||||
<div className="row">
|
<div className="row">
|
||||||
{projectLoading && <p>Loading....</p>}
|
{loading && <p>Loading....</p>}
|
||||||
{(!projectLoading && project) && <ProjectBanner project_data={project} ></ProjectBanner>}
|
{!loading && <ProjectBanner project_data={project} ></ProjectBanner>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="row">
|
<div className="row">
|
||||||
|
|||||||
@ -118,7 +118,11 @@ const ProjectList = () =>
|
|||||||
{" "}
|
{" "}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`btn btn-sm btn-primary ${!HasManageProject && 'd-none' }`}
|
className={`btn btn-sm btn-primary ${
|
||||||
|
HasManageProject
|
||||||
|
? ""
|
||||||
|
: "d-none"
|
||||||
|
}`}
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#create-project-model"
|
data-bs-target="#create-project-model"
|
||||||
onClick={handleShow}
|
onClick={handleShow}
|
||||||
|
|||||||
@ -13,8 +13,7 @@ const ProjectRepository = {
|
|||||||
manageProject: (data) => api.post("/api/project", data),
|
manageProject: (data) => api.post("/api/project", data),
|
||||||
// updateProject: (data) => api.post("/api/project/update", data),
|
// updateProject: (data) => api.post("/api/project/update", data),
|
||||||
|
|
||||||
manageProjectAllocation: ( data ) => api.post( "/api/project/allocation", data ),
|
manageProjectAllocation: (data) => api.post("/api/project/allocation", data),
|
||||||
|
|
||||||
manageProjectInfra: (data) => api.post("/api/project/manage-infra", data),
|
manageProjectInfra: (data) => api.post("/api/project/manage-infra", data),
|
||||||
manageProjectTasks: (data) => api.post("/api/project/manage-infra", data),
|
manageProjectTasks: (data) => api.post("/api/project/manage-infra", data),
|
||||||
|
|
||||||
@ -22,8 +21,4 @@ const ProjectRepository = {
|
|||||||
deleteProject: (id) => api.delete(`/projects/${id}`),
|
deleteProject: (id) => api.delete(`/projects/${id}`),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TasksRepository = {
|
|
||||||
assignTask: ( data ) => api.post( "/api/task/assign", data ),
|
|
||||||
reportTak:(data)=>api.post("/api/task/report",data)
|
|
||||||
}
|
|
||||||
export default ProjectRepository;
|
export default ProjectRepository;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ const localVariablesSlice = createSlice({
|
|||||||
initialState: {
|
initialState: {
|
||||||
selectedMaster:"Role",
|
selectedMaster:"Role",
|
||||||
regularizationCount:0,
|
regularizationCount:0,
|
||||||
projectId:1,
|
projectId:5,
|
||||||
|
|
||||||
},
|
},
|
||||||
reducers: {
|
reducers: {
|
||||||
|
|||||||
@ -54,8 +54,8 @@ axiosClient.interceptors.response.use(
|
|||||||
console.error("Request timed out.");
|
console.error("Request timed out.");
|
||||||
showToast("The request took too long. Please try again later.", "error");
|
showToast("The request took too long. Please try again later.", "error");
|
||||||
} else if (error.response) {
|
} else if (error.response) {
|
||||||
showToast(error.response.data.message,"error")
|
console.error("Error response:", error.response.status, error.response.data);
|
||||||
|
|
||||||
if (error.response.status === 401 && !originalRequest._retry) {
|
if (error.response.status === 401 && !originalRequest._retry) {
|
||||||
originalRequest._retry = true;
|
originalRequest._retry = true;
|
||||||
|
|
||||||
@ -89,9 +89,7 @@ axiosClient.interceptors.response.use(
|
|||||||
redirectToLogin();
|
redirectToLogin();
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
{
|
|
||||||
|
|
||||||
showToast(error.response.data?.message || "An error occurred. Please try again.", "error");
|
showToast(error.response.data?.message || "An error occurred. Please try again.", "error");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -5,8 +5,6 @@ export const MANAGE_MASTER = "588a8824-f924-4955-82d8-fc51956cf323";
|
|||||||
|
|
||||||
export const MANAGE_PROJECT = "172fc9b6-755b-4f62-ab26-55c34a330614"
|
export const MANAGE_PROJECT = "172fc9b6-755b-4f62-ab26-55c34a330614"
|
||||||
|
|
||||||
export const VIEW_PROJECTS = "6ea44136-987e-44ba-9e5d-1cf8f5837ebc"
|
|
||||||
|
|
||||||
export const MANAGE_EMPLOYEES = "a97d366a-c2bb-448d-be93-402bd2324566"
|
export const MANAGE_EMPLOYEES = "a97d366a-c2bb-448d-be93-402bd2324566"
|
||||||
|
|
||||||
export const MANAGE_PROJECT_INFRA = "f2aee20a-b754-4537-8166-f9507b44585b"
|
export const MANAGE_PROJECT_INFRA = "f2aee20a-b754-4537-8166-f9507b44585b"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user