Merge branch 'Organization_Management' of https://git.marcoaiot.com/admin/marco.pms.web into Organization_Management
This commit is contained in:
commit
158c934a9f
@ -55,7 +55,7 @@ const InfraPlanning = () => {
|
|||||||
|
|
||||||
if (isFetched && (!projectInfra || projectInfra.length === 0)) {
|
if (isFetched && (!projectInfra || projectInfra.length === 0)) {
|
||||||
return (
|
return (
|
||||||
<div className="card text-center">
|
<div className="text-center">
|
||||||
<p className="my-3">No Result Found</p>
|
<p className="my-3">No Result Found</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -63,11 +63,9 @@ const InfraPlanning = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<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-body" style={{ padding: "0.5rem" }}>
|
<div className="card-body" style={{ padding: "0.5rem" }}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<InfraTable buildings={projectInfra} projectId={selectedProject} />
|
<InfraTable buildings={projectInfra} projectId={selectedProject} />
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -143,7 +143,7 @@ const InfraTable = ({ buildings, projectId}) => {
|
|||||||
// }, [handler]);
|
// }, [handler]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="px-6">
|
||||||
{projectBuilding && projectBuilding.length > 0 && (
|
{projectBuilding && projectBuilding.length > 0 && (
|
||||||
<table className="table table-bordered">
|
<table className="table table-bordered">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -6,9 +6,10 @@ import {
|
|||||||
useActivitiesMaster,
|
useActivitiesMaster,
|
||||||
useWorkCategoriesMaster,
|
useWorkCategoriesMaster,
|
||||||
} from "../../../hooks/masterHook/useMaster";
|
} from "../../../hooks/masterHook/useMaster";
|
||||||
import { useManageTask } from "../../../hooks/useProjects";
|
import { useManageTask, useProjectAssignedServices } from "../../../hooks/useProjects";
|
||||||
import showToast from "../../../services/toastService";
|
import showToast from "../../../services/toastService";
|
||||||
import Label from "../../common/Label";
|
import Label from "../../common/Label";
|
||||||
|
import { useSelectedProject } from "../../../slices/apiDataManager";
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
buildingID: z.string().min(1, "Building is required"),
|
buildingID: z.string().min(1, "Building is required"),
|
||||||
@ -37,6 +38,15 @@ const TaskModel = ({ project, onSubmit, onClose }) => {
|
|||||||
const { activities, loading: activityLoading } = useActivitiesMaster();
|
const { activities, loading: activityLoading } = useActivitiesMaster();
|
||||||
const { categories, categoryLoading } = useWorkCategoriesMaster();
|
const { categories, categoryLoading } = useWorkCategoriesMaster();
|
||||||
|
|
||||||
|
const projectId = useSelectedProject();
|
||||||
|
|
||||||
|
const { data: assignedServices, isLoading: servicesLoading } = useProjectAssignedServices(projectId);
|
||||||
|
|
||||||
|
const [selectedService, setSelectedService] = useState("");
|
||||||
|
|
||||||
|
const handleServiceChange = (e) => {
|
||||||
|
setSelectedService(e.target.value);
|
||||||
|
};
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@ -96,10 +106,12 @@ const TaskModel = ({ project, onSubmit, onClose }) => {
|
|||||||
}, [categories]);
|
}, [categories]);
|
||||||
|
|
||||||
const onSubmitForm = async (data) => {
|
const onSubmitForm = async (data) => {
|
||||||
const payload = [data];
|
const payload = [data];
|
||||||
CreateTask({payload:payload,buildingId: data.buildingID,
|
CreateTask({
|
||||||
|
payload: payload, buildingId: data.buildingID,
|
||||||
floorId: data.floorId,
|
floorId: data.floorId,
|
||||||
workAreaId: data.workAreaId, PreviousPlannedWork:0,previousCompletedWork:0});
|
workAreaId: data.workAreaId, PreviousPlannedWork: 0, previousCompletedWork: 0
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -150,6 +162,7 @@ const TaskModel = ({ project, onSubmit, onClose }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Work Area Selection */}
|
||||||
{selectedFloor && (
|
{selectedFloor && (
|
||||||
<div className="col-12 text-start">
|
<div className="col-12 text-start">
|
||||||
<Label className="form-label" required>Select Work Area</Label>
|
<Label className="form-label" required>Select Work Area</Label>
|
||||||
@ -172,6 +185,32 @@ const TaskModel = ({ project, onSubmit, onClose }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Services Selection */}
|
||||||
|
{selectedWorkArea && (
|
||||||
|
<div className="col-12 text-start">
|
||||||
|
<Label className="form-label">Select Services</Label>
|
||||||
|
<select
|
||||||
|
name="DataTables_Table_0_length"
|
||||||
|
aria-controls="DataTables_Table_0"
|
||||||
|
className="form-select form-select-sm"
|
||||||
|
aria-label="Select Service"
|
||||||
|
value={selectedService}
|
||||||
|
onChange={handleServiceChange}
|
||||||
|
>
|
||||||
|
{servicesLoading && <option>Loading...</option>}
|
||||||
|
{assignedServices?.map((service) => (
|
||||||
|
<option key={service.id} value={service.id}>
|
||||||
|
{service.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
{errors.buildingID && (
|
||||||
|
<p className="danger-text">{errors.buildingID.message}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Activity Selection */}
|
||||||
{selectedWorkArea && (
|
{selectedWorkArea && (
|
||||||
<div className="col-12 text-start">
|
<div className="col-12 text-start">
|
||||||
<Label className="form-label" required>Select Activity</Label>
|
<Label className="form-label" required>Select Activity</Label>
|
||||||
@ -192,6 +231,7 @@ const TaskModel = ({ project, onSubmit, onClose }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
{selectedWorkArea && (
|
{selectedWorkArea && (
|
||||||
<div className="col-12 text-start">
|
<div className="col-12 text-start">
|
||||||
<label className="form-label">Select Work Category</label>
|
<label className="form-label">Select Work Category</label>
|
||||||
@ -261,7 +301,7 @@ const TaskModel = ({ project, onSubmit, onClose }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="col-12 text-end mt-5">
|
<div className="col-12 text-end mt-5">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-sm btn-label-secondary me-3"
|
className="btn btn-sm btn-label-secondary me-3"
|
||||||
|
@ -17,22 +17,21 @@ import {
|
|||||||
getCachedData,
|
getCachedData,
|
||||||
useSelectedProject,
|
useSelectedProject,
|
||||||
} from "../../slices/apiDataManager";
|
} from "../../slices/apiDataManager";
|
||||||
import { useProjectDetails, useProjectInfra } from "../../hooks/useProjects";
|
import { useProjectAssignedServices, useProjectDetails, useProjectInfra } from "../../hooks/useProjects";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { refreshData } from "../../slices/localVariablesSlice";
|
import { refreshData } from "../../slices/localVariablesSlice";
|
||||||
import eventBus from "../../services/eventBus";
|
import eventBus from "../../services/eventBus";
|
||||||
import {useParams} from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import GlobalModel from "../common/GlobalModel";
|
import GlobalModel from "../common/GlobalModel";
|
||||||
|
|
||||||
const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
|
const ProjectInfra = ({ data, onDataChange, eachSiteEngineer }) => {
|
||||||
{
|
|
||||||
// const projectId = useSelector((store)=>store.localVariables.projectId)
|
// const projectId = useSelector((store)=>store.localVariables.projectId)
|
||||||
const projectId = useSelectedProject();
|
const projectId = useSelectedProject();
|
||||||
const reloadedData = useSelector((store) => store.localVariables.reload);
|
const reloadedData = useSelector((store) => store.localVariables.reload);
|
||||||
const [ expandedBuildings, setExpandedBuildings ] = useState( [] );
|
const [expandedBuildings, setExpandedBuildings] = useState([]);
|
||||||
const {projectInfra,isLoading,error} = useProjectInfra(projectId)
|
const { projectInfra, isLoading, error } = useProjectInfra(projectId)
|
||||||
const { projects_Details, refetch, loading } = useProjectDetails(data?.id);
|
const { projects_Details, refetch, loading } = useProjectDetails(data?.id);
|
||||||
const [ project, setProject ] = useState( projects_Details );
|
const [project, setProject] = useState(projects_Details);
|
||||||
const ManageInfra = useHasUserPermission(MANAGE_PROJECT_INFRA);
|
const ManageInfra = useHasUserPermission(MANAGE_PROJECT_INFRA);
|
||||||
const ManageTask = useHasUserPermission(MANAGE_TASK)
|
const ManageTask = useHasUserPermission(MANAGE_TASK)
|
||||||
const [showModalFloor, setshowModalFloor] = useState(false);
|
const [showModalFloor, setshowModalFloor] = useState(false);
|
||||||
@ -40,47 +39,46 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
|
|||||||
const [showModalTask, setshowModalTask] = useState(false);
|
const [showModalTask, setshowModalTask] = useState(false);
|
||||||
const [showModalBuilding, setshowModalBuilding] = useState(false);
|
const [showModalBuilding, setshowModalBuilding] = useState(false);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const { data: assignedServices, isLoading: servicesLoading } = useProjectAssignedServices(projectId);
|
||||||
|
|
||||||
|
const [selectedService, setSelectedService] = useState("");
|
||||||
|
const handleServiceChange = (e) => {
|
||||||
|
setSelectedService(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setProject(projectInfra);
|
setProject(projectInfra);
|
||||||
}, [data, projects_Details]);
|
}, [data, projects_Details]);
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (reloadedData) {
|
|
||||||
// refetch();
|
|
||||||
// dispatch(refreshData(false));
|
|
||||||
// }
|
|
||||||
// }, [reloadedData]);
|
|
||||||
|
|
||||||
const signalRHandler = (response) => {
|
const signalRHandler = (response) => {
|
||||||
setProject(response);
|
setProject(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{showModalBuilding && <GlobalModel isOpen={showModalBuilding} size="md" closeModal={() => setshowModalBuilding( false )}>
|
{showModalBuilding && <GlobalModel isOpen={showModalBuilding} size="md" closeModal={() => setshowModalBuilding(false)}>
|
||||||
<BuildingModel
|
<BuildingModel
|
||||||
project={projectInfra}
|
project={projectInfra}
|
||||||
onClose={() => setshowModalBuilding( false )}
|
onClose={() => setshowModalBuilding(false)}
|
||||||
/>
|
/>
|
||||||
</GlobalModel>}
|
</GlobalModel>}
|
||||||
{showModalFloor && <GlobalModel isOpen={showModalFloor} size="md" closeModal={()=>setshowModalFloor(false)}>
|
{showModalFloor && <GlobalModel isOpen={showModalFloor} size="md" closeModal={() => setshowModalFloor(false)}>
|
||||||
<FloorModel
|
<FloorModel
|
||||||
project={projectInfra}
|
project={projectInfra}
|
||||||
onClose={()=>setshowModalFloor(false)}
|
onClose={() => setshowModalFloor(false)}
|
||||||
/>
|
/>
|
||||||
</GlobalModel>}
|
</GlobalModel>}
|
||||||
{showModalWorkArea && <GlobalModel isOpen={showModalWorkArea} size="lg" closeModal={()=>setshowModalWorkArea(false)} >
|
{showModalWorkArea && <GlobalModel isOpen={showModalWorkArea} size="lg" closeModal={() => setshowModalWorkArea(false)} >
|
||||||
<WorkAreaModel
|
<WorkAreaModel
|
||||||
project={projectInfra}
|
project={projectInfra}
|
||||||
onClose={()=>setshowModalWorkArea(false)}
|
onClose={() => setshowModalWorkArea(false)}
|
||||||
/>
|
/>
|
||||||
</GlobalModel>}
|
</GlobalModel>}
|
||||||
{showModalTask && ( <GlobalModel isOpen={showModalTask} size="lg" closeModal={()=>setshowModalTask(false)}>
|
{showModalTask && (<GlobalModel isOpen={showModalTask} size="lg" closeModal={() => setshowModalTask(false)}>
|
||||||
<TaskModel
|
<TaskModel
|
||||||
project={projectInfra}
|
project={projectInfra}
|
||||||
onClose={()=>setshowModalTask(false)}
|
onClose={() => setshowModalTask(false)}
|
||||||
/>
|
/>
|
||||||
</GlobalModel>)}
|
</GlobalModel>)}
|
||||||
<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">
|
||||||
@ -88,38 +86,73 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
|
|||||||
<div className="align-items-center">
|
<div className="align-items-center">
|
||||||
<div className="row ">
|
<div className="row ">
|
||||||
<div
|
<div
|
||||||
className={`col-12 text-end mb-1 `}
|
className="dataTables_length text-start py-2 px-6 col-md-4 col-12"
|
||||||
|
id="DataTables_Table_0_length"
|
||||||
>
|
>
|
||||||
{ManageInfra && (<>
|
{servicesLoading ? (
|
||||||
<button
|
<span></span>
|
||||||
type="button"
|
) : assignedServices?.length > 1 ? (
|
||||||
className="link-button btn btn-xs rounded-md link-button-sm m-1 btn-primary"
|
<label>
|
||||||
onClick={()=>setshowModalBuilding(true)}
|
<select
|
||||||
>
|
name="DataTables_Table_0_length"
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
aria-controls="DataTables_Table_0"
|
||||||
Manage Building
|
className="form-select form-select-sm"
|
||||||
</button>
|
aria-label="Select Service"
|
||||||
<button
|
value={selectedService}
|
||||||
type="button"
|
onChange={handleServiceChange}
|
||||||
className="link-button btn btn-xs rounded-md m-1 btn-primary"
|
>
|
||||||
onClick={()=>setshowModalFloor(true)}
|
{assignedServices.map((service) => (
|
||||||
>
|
<option key={service.id} value={service.id}>
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
{service.name}
|
||||||
Manage Floors
|
</option>
|
||||||
</button>
|
))}
|
||||||
<button
|
</select>
|
||||||
type="button"
|
</label>
|
||||||
className="link-button btn btn-xs rounded-md m-1 btn-primary"
|
) : (
|
||||||
onClick={() => setshowModalWorkArea(true)}
|
<div
|
||||||
>
|
style={{
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
|
||||||
Manage Work Areas
|
}}
|
||||||
</button></>)}
|
>
|
||||||
|
{assignedServices?.length === 1
|
||||||
|
? <h5>{ assignedServices[0].name}</h5>
|
||||||
|
: "No service available"}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{/* Buttons Section (aligned to right) */}
|
||||||
|
<div className="col-md-8 col-12 text-end mb-1">
|
||||||
|
{ManageInfra && (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="link-button btn btn-xs rounded-md link-button-sm m-1 btn-primary"
|
||||||
|
onClick={() => setshowModalBuilding(true)}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Manage Building
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="link-button btn btn-xs rounded-md m-1 btn-primary"
|
||||||
|
onClick={() => setshowModalFloor(true)}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Manage Floors
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="link-button btn btn-xs rounded-md m-1 btn-primary"
|
||||||
|
onClick={() => setshowModalWorkArea(true)}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
Manage Work Areas
|
||||||
|
</button></>)}
|
||||||
|
|
||||||
{(ManageTask || ManageInfra) && (<button
|
{(ManageTask || ManageInfra) && (<button
|
||||||
type="button"
|
type="button"
|
||||||
className="link-button btn btn-xs rounded-md m-1 btn-primary"
|
className="link-button btn btn-xs rounded-md m-1 btn-primary"
|
||||||
onClick={()=>setshowModalTask(true)}
|
onClick={() => setshowModalTask(true)}
|
||||||
>
|
>
|
||||||
<i className="bx bx-plus-circle me-2"></i>
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
Create Tasks
|
Create Tasks
|
||||||
@ -129,11 +162,11 @@ const ProjectInfra = ( {data, onDataChange, eachSiteEngineer} ) =>
|
|||||||
<div className="row ">
|
<div className="row ">
|
||||||
{isLoading && <p>Loading....</p>}
|
{isLoading && <p>Loading....</p>}
|
||||||
{projectInfra && projectInfra?.length > 0 && (
|
{projectInfra && projectInfra?.length > 0 && (
|
||||||
<InfraTable
|
<InfraTable
|
||||||
buildings={projectInfra}
|
buildings={projectInfra}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
// handleFloor={submitData}
|
// handleFloor={submitData}
|
||||||
// signalRHandler ={signalRHandler}
|
// signalRHandler ={signalRHandler}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!isLoading && projectInfra?.length == 0 && <div className="mt-5"><p>No Infra Avaiable</p></div>}
|
{!isLoading && projectInfra?.length == 0 && <div className="mt-5"><p>No Infra Avaiable</p></div>}
|
||||||
|
@ -17,12 +17,11 @@ import eventBus from "../../services/eventBus";
|
|||||||
import {
|
import {
|
||||||
useEmployeesByProjectAllocated,
|
useEmployeesByProjectAllocated,
|
||||||
useManageProjectAllocation,
|
useManageProjectAllocation,
|
||||||
|
useProjectAssignedServices,
|
||||||
} from "../../hooks/useProjects";
|
} from "../../hooks/useProjects";
|
||||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||||
|
|
||||||
const Teams = () => {
|
const Teams = () => {
|
||||||
// const {projectId} = useParams()
|
|
||||||
// const projectId = useSelector((store)=>store.localVariables.projectId)
|
|
||||||
const projectId = useSelectedProject();
|
const projectId = useSelectedProject();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
@ -37,6 +36,14 @@ const Teams = () => {
|
|||||||
const [activeEmployee, setActiveEmployee] = useState(true);
|
const [activeEmployee, setActiveEmployee] = useState(true);
|
||||||
const [deleteEmployee, setDeleteEmplyee] = useState(null);
|
const [deleteEmployee, setDeleteEmplyee] = useState(null);
|
||||||
const [searchTerm, setSearchTerm] = useState(""); // State for search term
|
const [searchTerm, setSearchTerm] = useState(""); // State for search term
|
||||||
|
const { data: assignedServices, isLoading: servicesLoading } = useProjectAssignedServices(projectId);
|
||||||
|
const handleToggleActive = e => setActiveEmployee(e.target.checked);
|
||||||
|
|
||||||
|
const [selectedService, setSelectedService] = useState("");
|
||||||
|
|
||||||
|
const handleServiceChange = (e) => {
|
||||||
|
setSelectedService(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -136,7 +143,6 @@ const Teams = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (projectEmployees) {
|
if (projectEmployees) {
|
||||||
setEmployees(projectEmployees);
|
setEmployees(projectEmployees);
|
||||||
//setFilteredEmployees(projectEmployees?.filter((emp) => emp.isActive));
|
|
||||||
const filtered = projectEmployees.filter((emp) => emp.isActive);
|
const filtered = projectEmployees.filter((emp) => emp.isActive);
|
||||||
setFilteredEmployees(filtered);
|
setFilteredEmployees(filtered);
|
||||||
}
|
}
|
||||||
@ -179,13 +185,6 @@ const Teams = () => {
|
|||||||
|
|
||||||
const handleFilterEmployee = (e) => {
|
const handleFilterEmployee = (e) => {
|
||||||
const filterValue = e.target.value;
|
const filterValue = e.target.value;
|
||||||
// if (filterValue === "true") {
|
|
||||||
// setActiveEmployee(true);
|
|
||||||
// setFilteredEmployees(employees.filter((emp) => emp.isActive));
|
|
||||||
// } else {
|
|
||||||
// setFilteredEmployees(employees.filter((emp) => !emp.isActive));
|
|
||||||
// setActiveEmployee(false);
|
|
||||||
// }
|
|
||||||
setActiveEmployee(filterValue === "true");
|
setActiveEmployee(filterValue === "true");
|
||||||
setSearchTerm("");
|
setSearchTerm("");
|
||||||
};
|
};
|
||||||
@ -264,6 +263,66 @@ const Teams = () => {
|
|||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="row d-flex justify-content-between mb-4">
|
<div className="row d-flex justify-content-between mb-4">
|
||||||
<div className="col-md-6 col-12 d-flex align-items-center">
|
<div className="col-md-6 col-12 d-flex align-items-center">
|
||||||
|
<div className="dataTables_length text-start py-1 px-0 col-md-4 col-12">
|
||||||
|
{servicesLoading ? (
|
||||||
|
<span></span>
|
||||||
|
) : assignedServices?.length > 1 ? (
|
||||||
|
<label>
|
||||||
|
<select
|
||||||
|
name="DataTables_Table_0_length"
|
||||||
|
aria-controls="DataTables_Table_0"
|
||||||
|
className="form-select form-select-sm"
|
||||||
|
aria-label="Select Service"
|
||||||
|
value={selectedService}
|
||||||
|
onChange={handleServiceChange}
|
||||||
|
style={{ fontSize: "0.875rem", height: "32px", width: "190px" }}
|
||||||
|
>
|
||||||
|
{assignedServices.map((service) => (
|
||||||
|
<option key={service.id} value={service.id}>
|
||||||
|
{service.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* fier fitting */}
|
||||||
|
{assignedServices?.length === 1
|
||||||
|
?<h5>{ assignedServices[0].name}</h5>
|
||||||
|
: "No service available"}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className="dataTables_filter d-inline-flex align-items-center ms-2">
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
className="form-control form-control-sm me-4"
|
||||||
|
placeholder="Search by Name or Role"
|
||||||
|
aria-controls="DataTables_Table_0"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={handleSearch}
|
||||||
|
/>
|
||||||
|
</div> */}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6 col-12 d-flex justify-content-end align-items-center">
|
||||||
|
<div className="form-check form-switch me-2 mt-2">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="form-check-input"
|
||||||
|
checked={activeEmployee}
|
||||||
|
onChange={handleToggleActive}
|
||||||
|
id="activeEmployeeSwitch"
|
||||||
|
/>
|
||||||
|
<label className="form-check-label ms-0 " htmlFor="activeEmployeeSwitch">
|
||||||
|
{activeEmployee ? "Active Employees" : "Inactive Employees"}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div className="dataTables_filter d-inline-flex align-items-center ms-2">
|
<div className="dataTables_filter d-inline-flex align-items-center ms-2">
|
||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
@ -274,32 +333,11 @@ const Teams = () => {
|
|||||||
onChange={handleSearch}
|
onChange={handleSearch}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div className="col-md-6 col-12 d-flex justify-content-end align-items-center">
|
|
||||||
<div
|
|
||||||
className="dataTables_length text-start py-2 px-2"
|
|
||||||
id="DataTables_Table_0_length"
|
|
||||||
>
|
|
||||||
<label>
|
|
||||||
<select
|
|
||||||
name="DataTables_Table_0_length"
|
|
||||||
aria-controls="DataTables_Table_0"
|
|
||||||
className="form-select form-select-sm"
|
|
||||||
onChange={handleFilterEmployee}
|
|
||||||
// value={false}
|
|
||||||
aria-label=""
|
|
||||||
defaultValue="true"
|
|
||||||
>
|
|
||||||
<option value="true">Active Employee</option>
|
|
||||||
<option value="false">In-Active Employee</option>
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`link-button btn-primary btn-sm ${
|
className={`link-button btn-primary btn-sm ${HasAssignUserPermission ? "" : "d-none"
|
||||||
HasAssignUserPermission ? "" : "d-none"
|
}`}
|
||||||
}`}
|
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#user-model"
|
data-bs-target="#user-model"
|
||||||
>
|
>
|
||||||
@ -319,6 +357,7 @@ const Teams = () => {
|
|||||||
<th>
|
<th>
|
||||||
<div className="text-start ms-5">Name</div>
|
<div className="text-start ms-5">Name</div>
|
||||||
</th>
|
</th>
|
||||||
|
<th>Organization</th>
|
||||||
<th>Assigned Date</th>
|
<th>Assigned Date</th>
|
||||||
{!activeEmployee && <th>Release Date</th>}
|
{!activeEmployee && <th>Release Date</th>}
|
||||||
<th>Project Role</th>
|
<th>Project Role</th>
|
||||||
@ -334,7 +373,7 @@ const Teams = () => {
|
|||||||
<Avatar
|
<Avatar
|
||||||
firstName={item.firstName}
|
firstName={item.firstName}
|
||||||
lastName={item.lastName}
|
lastName={item.lastName}
|
||||||
></Avatar>
|
/>
|
||||||
<div className="d-flex flex-column">
|
<div className="d-flex flex-column">
|
||||||
<a
|
<a
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@ -352,18 +391,16 @@ const Teams = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
<td>{item.organizationName || "N/A"}</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
{" "}
|
{moment(item.allocationDate).format("DD-MMM-YYYY")}
|
||||||
{moment(item.allocationDate).format(
|
|
||||||
"DD-MMM-YYYY"
|
|
||||||
)}{" "}
|
|
||||||
</td>
|
</td>
|
||||||
{!activeEmployee && (
|
{!activeEmployee && (
|
||||||
<td>
|
<td>
|
||||||
{item.reAllocationDate
|
{item.reAllocationDate
|
||||||
? moment(item.reAllocationDate).format(
|
? moment(item.reAllocationDate).format("DD-MMM-YYYY")
|
||||||
"DD-MMM-YYYY"
|
|
||||||
)
|
|
||||||
: "Present"}
|
: "Present"}
|
||||||
</td>
|
</td>
|
||||||
)}
|
)}
|
||||||
@ -373,7 +410,7 @@ const Teams = () => {
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{item.isActive && (
|
{item.isActive ? (
|
||||||
<button
|
<button
|
||||||
aria-label="Delete"
|
aria-label="Delete"
|
||||||
type="button"
|
type="button"
|
||||||
@ -381,27 +418,26 @@ const Teams = () => {
|
|||||||
className="btn p-0 dropdown-toggle hide-arrow"
|
className="btn p-0 dropdown-toggle hide-arrow"
|
||||||
onClick={() => deleteModalOpen(item)}
|
onClick={() => deleteModalOpen(item)}
|
||||||
>
|
>
|
||||||
{" "}
|
|
||||||
{removingEmployeeId === item.id ? (
|
{removingEmployeeId === item.id ? (
|
||||||
<div
|
<div
|
||||||
className="spinner-border spinner-border-sm text-primary"
|
className="spinner-border spinner-border-sm text-primary"
|
||||||
role="status"
|
role="status"
|
||||||
>
|
>
|
||||||
<span className="visually-hidden">
|
<span className="visually-hidden">Loading...</span>
|
||||||
Loading...
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<i className="bx bx-trash me-1 text-danger"></i>
|
<i className="bx bx-trash me-1 text-danger"></i>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
) : (
|
||||||
|
<span>Not in project</span>
|
||||||
)}
|
)}
|
||||||
{!item.isActive && <span>Not in project</span>}
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
{!employeeLodaing && filteredEmployees.length === 0 && (
|
{!employeeLodaing && filteredEmployees.length === 0 && (
|
||||||
<div className="text-center text-muted py-3">
|
<div className="text-center text-muted py-3">
|
||||||
|
@ -203,7 +203,7 @@ const FilterIcon = ({
|
|||||||
<>
|
<>
|
||||||
<li><hr className="my-1" /></li>
|
<li><hr className="my-1" /></li>
|
||||||
<li>
|
<li>
|
||||||
<div className="fw-bold text-dark mb-1">Floors</div>
|
<div className="fw-bold text-dark mb-2 mt-2">Floors</div>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
{uniqueFloors.length > 0 ? (
|
{uniqueFloors.length > 0 ? (
|
||||||
uniqueFloors.map((floor, idx) => (
|
uniqueFloors.map((floor, idx) => (
|
||||||
@ -235,7 +235,7 @@ const FilterIcon = ({
|
|||||||
<>
|
<>
|
||||||
<li><hr className="my-1" /></li>
|
<li><hr className="my-1" /></li>
|
||||||
<li>
|
<li>
|
||||||
<div className="fw-bold text-dark mb-1">Activities</div>
|
<div className="fw-bold text-dark mb-2 mt-2">Activities</div>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
{uniqueActivities.length > 0 ? (
|
{uniqueActivities.length > 0 ? (
|
||||||
uniqueActivities.map((activity, idx) => (
|
uniqueActivities.map((activity, idx) => (
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect, useMemo, useState } from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { useTaskList } from "../../hooks/useTasks";
|
import { useTaskList } from "../../hooks/useTasks";
|
||||||
import { useProjectName } from "../../hooks/useProjects";
|
import { useProjectAssignedServices, useProjectName } from "../../hooks/useProjects";
|
||||||
import { setProjectId } from "../../slices/localVariablesSlice";
|
import { setProjectId } from "../../slices/localVariablesSlice";
|
||||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||||
import DateRangePicker from "../../components/common/DateRangePicker";
|
import DateRangePicker from "../../components/common/DateRangePicker";
|
||||||
@ -24,6 +24,14 @@ const DailyTask = () => {
|
|||||||
const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK);
|
const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK);
|
||||||
const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK);
|
const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK);
|
||||||
|
|
||||||
|
const { data: assignedServices, isLoading: servicesLoading } = useProjectAssignedServices(selectedProject);
|
||||||
|
|
||||||
|
const [selectedService, setSelectedService] = useState("");
|
||||||
|
|
||||||
|
const handleServiceChange = (e) => {
|
||||||
|
setSelectedService(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
const [filters, setFilters] = useState({
|
const [filters, setFilters] = useState({
|
||||||
selectedBuilding: "",
|
selectedBuilding: "",
|
||||||
selectedFloors: [],
|
selectedFloors: [],
|
||||||
@ -38,7 +46,6 @@ const DailyTask = () => {
|
|||||||
dateRange?.endDate || null
|
dateRange?.endDate || null
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ensure project is set
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectedProject && projectNames.length > 0) {
|
if (!selectedProject && projectNames.length > 0) {
|
||||||
debugger
|
debugger
|
||||||
@ -46,7 +53,6 @@ const DailyTask = () => {
|
|||||||
}
|
}
|
||||||
}, [selectedProject, projectNames, dispatch]);
|
}, [selectedProject, projectNames, dispatch]);
|
||||||
|
|
||||||
// 🔹 Reset filters when project changes
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setFilters({
|
setFilters({
|
||||||
selectedBuilding: "",
|
selectedBuilding: "",
|
||||||
@ -55,7 +61,6 @@ const DailyTask = () => {
|
|||||||
});
|
});
|
||||||
}, [selectedProject]);
|
}, [selectedProject]);
|
||||||
|
|
||||||
// Memoized filtering
|
|
||||||
const filteredTasks = useMemo(() => {
|
const filteredTasks = useMemo(() => {
|
||||||
if (!TaskList) return [];
|
if (!TaskList) return [];
|
||||||
return TaskList.filter((task) => {
|
return TaskList.filter((task) => {
|
||||||
@ -69,7 +74,6 @@ const DailyTask = () => {
|
|||||||
});
|
});
|
||||||
}, [TaskList, filters]);
|
}, [TaskList, filters]);
|
||||||
|
|
||||||
// Memoized dates
|
|
||||||
const groupedTasks = useMemo(() => {
|
const groupedTasks = useMemo(() => {
|
||||||
const groups = {};
|
const groups = {};
|
||||||
filteredTasks.forEach((task) => {
|
filteredTasks.forEach((task) => {
|
||||||
@ -82,13 +86,11 @@ const DailyTask = () => {
|
|||||||
.map((date) => ({ date, tasks: groups[date] }));
|
.map((date) => ({ date, tasks: groups[date] }));
|
||||||
}, [filteredTasks]);
|
}, [filteredTasks]);
|
||||||
|
|
||||||
// --- Modal State
|
|
||||||
const [modal, setModal] = useState({ type: null, data: null });
|
const [modal, setModal] = useState({ type: null, data: null });
|
||||||
|
|
||||||
const openModal = (type, data = null) => setModal({ type, data });
|
const openModal = (type, data = null) => setModal({ type, data });
|
||||||
const closeModal = () => setModal({ type: null, data: null });
|
const closeModal = () => setModal({ type: null, data: null });
|
||||||
|
|
||||||
// --- Render helpers
|
|
||||||
const renderTeamMembers = (task, refIndex) => (
|
const renderTeamMembers = (task, refIndex) => (
|
||||||
<div
|
<div
|
||||||
key={refIndex}
|
key={refIndex}
|
||||||
@ -133,7 +135,6 @@ const DailyTask = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* --- Modals --- */}
|
|
||||||
{modal.type === "report" && (
|
{modal.type === "report" && (
|
||||||
<GlobalModel isOpen size="md" closeModal={closeModal}>
|
<GlobalModel isOpen size="md" closeModal={closeModal}>
|
||||||
<ReportTask report={modal.data} closeModal={closeModal} />
|
<ReportTask report={modal.data} closeModal={closeModal} />
|
||||||
@ -161,22 +162,71 @@ const DailyTask = () => {
|
|||||||
<div className="container-fluid">
|
<div className="container-fluid">
|
||||||
<Breadcrumb data={[{ label: "Home", link: "/dashboard" }, { label: "Daily Progress Report" }]} />
|
<Breadcrumb data={[{ label: "Home", link: "/dashboard" }, { label: "Daily Progress Report" }]} />
|
||||||
|
|
||||||
<div className="card card-action mb-6">
|
<div className="card card-action mb-6 p-5">
|
||||||
<div className="card-body p-1 p-sm-2">
|
<div className="card-body p-1 p-sm-2">
|
||||||
{!selectedProject && (<div className="text-center text-muted">Please Select Project</div>)}
|
{!selectedProject && (<div className="text-center text-muted">Please Select Project</div>)}
|
||||||
{/* --- Filters --- */}
|
|
||||||
<div className="d-flex align-items-center mb-2">
|
|
||||||
<DateRangePicker onRangeChange={setDateRange} endDateMode="today" DateDifference="6" dateFormat="DD-MM-YYYY" />
|
|
||||||
<FilterIcon
|
|
||||||
taskListData={TaskList}
|
|
||||||
onApplyFilters={setFilters}
|
|
||||||
currentSelectedBuilding={filters.selectedBuilding}
|
|
||||||
currentSelectedFloors={filters.selectedFloors}
|
|
||||||
currentSelectedActivities={filters.selectedActivities}
|
|
||||||
selectedProject={selectedProject}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div className="d-flex align-items-center justify-content-between mb-2">
|
||||||
|
|
||||||
|
{/* --- Left: Service Dropdown + Filter Icon --- */}
|
||||||
|
<div className="d-flex align-items-center gap-6">
|
||||||
|
<div className="me-3">
|
||||||
|
{servicesLoading ? (
|
||||||
|
<span></span>
|
||||||
|
) : assignedServices?.length > 1 ? (
|
||||||
|
<select
|
||||||
|
name="serviceSelect"
|
||||||
|
className="form-select form-select-sm"
|
||||||
|
value={selectedService}
|
||||||
|
onChange={handleServiceChange}
|
||||||
|
style={{ fontSize: "0.875rem", height: "32px", minWidth: "190px" }}
|
||||||
|
>
|
||||||
|
{assignedServices.map((service) => (
|
||||||
|
<option key={service.id} value={service.id}>
|
||||||
|
{service.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
className="ms-4 mt-2"
|
||||||
|
>
|
||||||
|
{assignedServices?.length === 1
|
||||||
|
? <h5>{assignedServices[0].name}</h5>
|
||||||
|
: "No service available"}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <FilterIcon
|
||||||
|
taskListData={TaskList}
|
||||||
|
onApplyFilters={setFilters}
|
||||||
|
currentSelectedBuilding={filters.selectedBuilding}
|
||||||
|
currentSelectedFloors={filters.selectedFloors}
|
||||||
|
currentSelectedActivities={filters.selectedActivities}
|
||||||
|
selectedProject={selectedProject}
|
||||||
|
/> */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* --- Right: DateRangePicker --- */}
|
||||||
|
<div className="d-flex justify-content-end align-items-center gap-3 me-3">
|
||||||
|
<FilterIcon
|
||||||
|
taskListData={TaskList}
|
||||||
|
onApplyFilters={setFilters}
|
||||||
|
currentSelectedBuilding={filters.selectedBuilding}
|
||||||
|
currentSelectedFloors={filters.selectedFloors}
|
||||||
|
currentSelectedActivities={filters.selectedActivities}
|
||||||
|
selectedProject={selectedProject}
|
||||||
|
/>
|
||||||
|
<DateRangePicker
|
||||||
|
onRangeChange={setDateRange}
|
||||||
|
endDateMode="today"
|
||||||
|
DateDifference="6"
|
||||||
|
dateFormat="DD-MM-YYYY"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
{/* --- Table --- */}
|
{/* --- Table --- */}
|
||||||
<div className="table-responsive text-nowrap mt-3" style={{ minHeight: "200px" }}>
|
<div className="table-responsive text-nowrap mt-3" style={{ minHeight: "200px" }}>
|
||||||
<table className="table">
|
<table className="table">
|
||||||
@ -248,4 +298,4 @@ const DailyTask = () => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default DailyTask;
|
export default DailyTask;
|
@ -1,22 +1,31 @@
|
|||||||
import React,{useEffect,useRef} from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||||
import InfraPlanning from "../../components/Activities/InfraPlanning";
|
import InfraPlanning from "../../components/Activities/InfraPlanning";
|
||||||
import { useProjectName } from "../../hooks/useProjects";
|
import { useProjectName } from "../../hooks/useProjects";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { setProjectId } from "../../slices/localVariablesSlice";
|
import { setProjectId } from "../../slices/localVariablesSlice";
|
||||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||||
|
import { useProjectAssignedServices } from "../../hooks/useProjects";
|
||||||
|
|
||||||
const TaskPlannng = () => {
|
const TaskPlannng = () => {
|
||||||
const selectedProject = useSelectedProject();
|
const selectedProject = useSelectedProject();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { projectNames = [], loading: projectLoading } = useProjectName();
|
const { projectNames = [], loading: projectLoading } = useProjectName();
|
||||||
|
|
||||||
useEffect(() => {
|
// Service dropdown state
|
||||||
if (!selectedProject) {
|
const { data: assignedServices, isLoading: servicesLoading } =
|
||||||
dispatch(setProjectId(projectNames[0]?.id));
|
useProjectAssignedServices(selectedProject);
|
||||||
}
|
const [selectedService, setSelectedService] = useState("");
|
||||||
}, [projectNames, selectedProject?.id, dispatch]);
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!selectedProject && projectNames?.length > 0) {
|
||||||
|
dispatch(setProjectId(projectNames[0]?.id));
|
||||||
|
}
|
||||||
|
}, [projectNames, selectedProject, dispatch]);
|
||||||
|
|
||||||
|
const handleServiceChange = (e) => {
|
||||||
|
setSelectedService(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container-fluid">
|
<div className="container-fluid">
|
||||||
@ -26,11 +35,45 @@ useEffect(() => {
|
|||||||
{ label: "Daily Task Planning" },
|
{ label: "Daily Task Planning" },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
{selectedProject ? (
|
|
||||||
<InfraPlanning />
|
<div className="card">
|
||||||
) : (
|
<div className="card-body">
|
||||||
<div className="text-center">Please Select Project</div>
|
{/* Service Dropdown */}
|
||||||
)}
|
<div className="mb-1 ms-2">
|
||||||
|
{assignedServices?.length > 1 ? (
|
||||||
|
<select
|
||||||
|
id="serviceSelect"
|
||||||
|
className="form-select"
|
||||||
|
value={selectedService}
|
||||||
|
onChange={handleServiceChange}
|
||||||
|
style={{ fontSize: "0.875rem", height: "35px", width: "190px" }}
|
||||||
|
>
|
||||||
|
{assignedServices.map((service) => (
|
||||||
|
<option key={service.id} value={service.id}>
|
||||||
|
{service.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
className="text-start"
|
||||||
|
>
|
||||||
|
{assignedServices?.length === 1
|
||||||
|
? <h5>{ assignedServices[0].name}</h5>
|
||||||
|
: "No service available"}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{/* Infra Planning Component */}
|
||||||
|
{selectedProject ? (
|
||||||
|
<InfraPlanning selectedService={selectedService} />
|
||||||
|
) : (
|
||||||
|
<div className="text-center">Please Select Project</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user