From 80d64c87c6e47954c9bd18599ef08ed600eb8ad5 Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Sat, 3 May 2025 11:07:57 +0530 Subject: [PATCH] Improve safety and sorting for building dropdown - Added optional chaining to safely access project.buildings and prevent errors if undefined. - Filtered out buildings with invalid or missing 'name' properties. - Implemented safe sorting using localeCompare, with a fallback to empty string for undefined 'name' values. - Added fallback message "No buildings found" when there are no valid buildings in the list. --- .../Project/Infrastructure/BuildingModel.jsx | 59 ++++++++++--------- .../Project/Infrastructure/FloorModel.jsx | 32 +++++++--- .../Project/Infrastructure/TaskModel.jsx | 38 +++++++++--- .../Project/Infrastructure/WorkAreaModel.jsx | 52 ++++++++++++---- 4 files changed, 127 insertions(+), 54 deletions(-) diff --git a/src/components/Project/Infrastructure/BuildingModel.jsx b/src/components/Project/Infrastructure/BuildingModel.jsx index 374c7719..5af33168 100644 --- a/src/components/Project/Infrastructure/BuildingModel.jsx +++ b/src/components/Project/Infrastructure/BuildingModel.jsx @@ -5,7 +5,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; import ProjectRepository from "../../../repositories/ProjectRepository"; import { useSelector } from "react-redux"; import { useProjectDetails } from "../../../hooks/useProjects"; -import {getCachedData} from "../../../slices/apiDataManager"; +import { getCachedData } from "../../../slices/apiDataManager"; import showToast from "../../../services/toastService"; // Zod validation schema @@ -29,8 +29,8 @@ const BuildingModel = ({ const selectedProject = useSelector( (store) => store.localVariables.projectId ); - const [buildings ,setBuildings] = useState([]) - const projects_Details = getCachedData("projectInfo") + const [buildings, setBuildings] = useState([]); + const projects_Details = getCachedData("projectInfo"); const [formData, setFormData] = useState({ id: "", name: "", @@ -80,24 +80,21 @@ const BuildingModel = ({ const onSubmitHandler = async (data) => { onSubmit({ ...data, projectId: project.id }); - reset( { - Id:"0", + reset({ + Id: "0", name: "", description: "", - } ); - if ( data.Id !== "0" ) - { - showToast( "Building updated successfully.", "success" ); - } else - { - showToast( "Building created successfully.", "success" ); - } + }); + if (data.Id !== "0") { + showToast("Building updated successfully.", "success"); + } else { + showToast("Building created successfully.", "success"); + } }; - useEffect( () => - { - setBuildings(projects_Details.data?.buildings) - },[projects_Details]) + useEffect(() => { + setBuildings(projects_Details.data?.buildings); + }, [projects_Details]); return (
@@ -122,16 +119,24 @@ const BuildingModel = ({ handleBuildingChange(e); }} > - - - - {project && - project?.buildings?.length > 0 && - project?.buildings.map((building) => ( - - ))} + + + {project?.buildings?.length > 0 ? ( + project.buildings + .filter((building) => building?.name) + .sort((a, b) => { + const nameA = a.name || ""; + const nameB = b.name || ""; + return nameA?.localeCompare(nameB); + }) + .map((building) => ( + + )) + ) : ( + + )} {errors.Id && ( {errors.Id.message} diff --git a/src/components/Project/Infrastructure/FloorModel.jsx b/src/components/Project/Infrastructure/FloorModel.jsx index 2d64c275..00d2aff1 100644 --- a/src/components/Project/Infrastructure/FloorModel.jsx +++ b/src/components/Project/Infrastructure/FloorModel.jsx @@ -135,16 +135,23 @@ const FloorModel = ({ onChange={handleBuildigChange} > - {buildings && - buildings?.length > 0 && + {buildings?.length > 0 && buildings - ?.slice() - ?.sort((a, b) => a.name.localeCompare(b.name)) - ?.map((building) => ( + .filter((building) => building?.name) + .sort((a, b) => { + const nameA = a.name || ""; + const nameB = b.name || ""; + return nameA?.localeCompare(nameB); + }) + .map((building) => ( ))} + + {buildings?.length === 0 && ( + + )} {errors.buildingId && (

{errors.buildingId.message}

@@ -169,14 +176,23 @@ const FloorModel = ({ ) )} */} {selectedBuilding && - selectedBuilding.floors.length > 0 && + selectedBuilding.floors?.length > 0 && [...selectedBuilding.floors] - ?.sort((a, b) => a.floorName.localeCompare(b.floorName)) - ?.map((floor) => ( + .filter((floor) => floor?.floorName) + .sort((a, b) => { + const nameA = a.floorName || ""; + const nameB = b.floorName || ""; + return nameA?.localeCompare(nameB); + }) + .map((floor) => ( ))} + + {selectedBuilding?.floors?.length === 0 && ( + + )} {errors.id && (

{errors.id.message}

diff --git a/src/components/Project/Infrastructure/TaskModel.jsx b/src/components/Project/Infrastructure/TaskModel.jsx index ee3c1ff1..e69a6434 100644 --- a/src/components/Project/Infrastructure/TaskModel.jsx +++ b/src/components/Project/Infrastructure/TaskModel.jsx @@ -163,13 +163,18 @@ const TaskModel = ({ > {project.buildings - ?.slice() - ?.sort((a, b) => a.name.localeCompare(b.name)) + ?.filter((building) => building?.name) // Ensure valid name + ?.sort((a, b) => a.name?.localeCompare(b.name)) ?.map((building) => ( ))} + + {project.buildings?.filter((building) => building?.name) + .length === 0 && ( + + )} {errors.buildingID && (

{errors.buildingID.message}

@@ -190,7 +195,10 @@ const TaskModel = ({ > {selectedBuilding.floors - ?.slice() + ?.filter( + (floor) => + floor?.floorName && Array.isArray(floor.workAreas) + ) ?.sort((a, b) => a.floorName.localeCompare(b.floorName)) ?.map((floor) => ( ))} + + {selectedBuilding.floors?.filter( + (floor) => + floor?.floorName && Array.isArray(floor.workAreas) + ).length === 0 && } {errors.floorId && (

{errors.floorId.message}

@@ -219,13 +232,19 @@ const TaskModel = ({ > {selectedFloor.workAreas - ?.slice() - ?.sort((a, b) => a.areaName.localeCompare(b.areaName)) + ?.filter((workArea) => workArea?.areaName) + ?.sort((a, b) => a.areaName.localeCompare(b.areaName)) ?.map((workArea) => ( ))} + + {selectedFloor.workAreas?.filter( + (workArea) => workArea?.areaName + ).length === 0 && ( + + )} {errors.workAreaId && (

{errors.workAreaId.message}

@@ -248,15 +267,18 @@ const TaskModel = ({ {activities ?.slice() - ?.sort((a, b) => - a.activityName.localeCompare(b.activityName) - ) + ?.sort((a, b) => { + const nameA = a?.activityName || ""; + const nameB = b?.activityName || ""; + return nameA.localeCompare(nameB); + }) ?.map((activity) => ( ))} + {errors.activityID && (

{errors.activityID.message}

)} diff --git a/src/components/Project/Infrastructure/WorkAreaModel.jsx b/src/components/Project/Infrastructure/WorkAreaModel.jsx index f6beaddd..e9d93375 100644 --- a/src/components/Project/Infrastructure/WorkAreaModel.jsx +++ b/src/components/Project/Infrastructure/WorkAreaModel.jsx @@ -158,13 +158,22 @@ const WorkAreaModel = ({ > {project?.buildings - ?.slice() - .sort((a, b) => a.name.localeCompare(b.name)) - .map((building) => ( + ?.filter((building) => building?.name) + ?.sort((a, b) => { + const nameA = a.name || ""; + const nameB = b.name || ""; + return nameA?.localeCompare(nameB); + }) + ?.map((building) => ( ))} + + {project?.buildings?.filter((building) => building?.name) + .length === 0 && ( + + )} {errors.buildingId && {errors.buildingId.message}}
@@ -184,13 +193,21 @@ const WorkAreaModel = ({ > {selectedBuilding.floors - ?.slice() - .sort((a, b) => a.floorName.localeCompare(b.floorName)) - .map((floor) => ( + ?.filter((floor) => floor?.floorName) + ?.sort((a, b) => { + const nameA = a.floorName || ""; + const nameB = b.floorName || ""; + return nameA.localeCompare(nameB); + }) + ?.map((floor) => ( ))} + + {selectedBuilding.floors?.filter( + (floor) => floor?.floorName + ).length === 0 && } {errors.floorId && {errors.floorId.message}}
@@ -209,11 +226,24 @@ const WorkAreaModel = ({ onChange={handleWorkAreaChange} > - {selectedFloor?.workAreas?.map((workArea) => ( - - ))} + {selectedFloor?.workAreas + ?.filter((workArea) => workArea?.areaName) + ?.sort((a, b) => { + const nameA = a.areaName || ""; + const nameB = b.areaName || ""; + return nameA.localeCompare(nameB); + }) + ?.map((workArea) => ( + + ))} + + {selectedFloor?.workAreas?.filter( + (workArea) => workArea?.areaName + ).length === 0 && ( + + )} {errors.id && {errors.id.message}}