diff --git a/app/src/components/layout/sidebarLeft/Outline.tsx b/app/src/components/layout/sidebarLeft/Outline.tsx index 3fbede7..c459925 100644 --- a/app/src/components/layout/sidebarLeft/Outline.tsx +++ b/app/src/components/layout/sidebarLeft/Outline.tsx @@ -1,23 +1,62 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import Search from "../../ui/inputs/Search"; import DropDownList from "../../ui/list/DropDownList"; +import { useSceneContext } from "../../../modules/scene/sceneContext"; +import { isPointInsidePolygon } from "../../../functions/isPointInsidePolygon"; + +interface ZoneData { + id: string; + name: string; + assets: { id: string; name: string; position?: []; rotation?: {} }[]; +} const Outline: React.FC = () => { const [searchValue, setSearchValue] = useState(""); + const [zoneDataList, setZoneDataList] = useState([]); + const [buildingsList, setBuildingsList] = useState<{ id: string; name: string }[]>([]); + const [isLayersOpen, setIsLayersOpen] = useState(true); + const [isBuildingsOpen, setIsBuildingsOpen] = useState(false); + const [isZonesOpen, setIsZonesOpen] = useState(false); + const { assetStore, zoneStore } = useSceneContext(); + const { assets } = assetStore(); + const { zones } = zoneStore(); + + + useEffect(() => { + const updatedZoneList: ZoneData[] = zones?.map((zone: any) => { + const polygon2D = zone.points.map((p: [number, number, number]) => [p[0], p[2],]); + + const assetsInZone = assets.filter((item: any) => { + const [x, , z] = item.position; + return isPointInsidePolygon([x, z], polygon2D as [number, number][]); + }) + .map((item: any) => ({ + id: item.modelUuid, + name: item.modelName, + position: item.position, + rotation: item.rotation, + })); + + return { + id: zone.zoneUuid, + name: zone.zoneName, + assets: assetsInZone, + }; + }); + + setZoneDataList(updatedZoneList); + }, [zones, assets]); const handleSearchChange = (value: string) => { setSearchValue(value); - // console.log(value); // Log the search value if needed }; - const dropdownItems = [ - { id: "1", name: "Ground Floor", active: true }, - // { id: "2", name: "Floor 1" }, - ]; // Example dropdown items + const dropdownItems = [{ id: "1", name: "Ground Floor" }]; return (
+ {searchValue ? (

Results for "{searchValue}"

@@ -28,7 +67,8 @@ const Outline: React.FC = () => { setIsLayersOpen((prev) => !prev)} showKebabMenu={false} showFocusIcon={true} remove @@ -36,10 +76,18 @@ const Outline: React.FC = () => {
setIsBuildingsOpen((prev) => !prev)} + showKebabMenu={false} + showAddIcon={false} + /> + setIsZonesOpen((prev) => !prev)} showKebabMenu={false} showAddIcon={false} /> diff --git a/app/src/components/ui/list/DropDownList.tsx b/app/src/components/ui/list/DropDownList.tsx index b158c80..bbf386d 100644 --- a/app/src/components/ui/list/DropDownList.tsx +++ b/app/src/components/ui/list/DropDownList.tsx @@ -1,30 +1,18 @@ -import React, { useEffect, useState } from "react"; +import React from "react"; import List from "./List"; import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons"; import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect"; -import { useSceneContext } from "../../../modules/scene/sceneContext"; interface DropDownListProps { - value?: string; // Value to display in the DropDownList - items?: { id: string; name: string }[]; // Items to display in the dropdown list - showFocusIcon?: boolean; // Determines if the FocusIcon should be displayed - showAddIcon?: boolean; // Determines if the AddIcon should be displayed - showKebabMenu?: boolean; // Determines if the KebabMenuList should be displayed - kebabMenuItems?: { id: string; name: string }[]; // Items for the KebabMenuList - defaultOpen?: boolean; // Determines if the dropdown list should be open by default - listType?: string; // Type of list to display + value?: string; + items?: { id: string; name: string }[]; + showFocusIcon?: boolean; + showAddIcon?: boolean; + showKebabMenu?: boolean; + kebabMenuItems?: { id: string; name: string }[]; remove?: boolean; -} - -interface Zone { - zoneUuid: string; - zoneName: string; - points: [number, number, number][]; // polygon vertices -} -interface ZoneData { - id: string; - name: string; - assets: { id: string; name: string; position?: []; rotation?: {} }[]; + isOpen: boolean; + onToggle: () => void; } const DropDownList: React.FC = ({ @@ -38,76 +26,13 @@ const DropDownList: React.FC = ({ { id: "Paths", name: "Paths" }, { id: "Zones", name: "Zones" }, ], - defaultOpen = false, - listType = "default", remove, + isOpen, + onToggle, }) => { - const [isOpen, setIsOpen] = useState(defaultOpen); - - const handleToggle = () => { - setIsOpen((prev) => !prev); // Toggle the state - }; - - const [zoneDataList, setZoneDataList] = useState([]); - const { assetStore, zoneStore } = useSceneContext(); - const { assets } = assetStore(); - const { zones } = zoneStore() - - - const isPointInsidePolygon = ( - point: [number, number], - polygon: [number, number][] - ) => { - let inside = false; - for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { - const xi = polygon[i][0], - zi = polygon[i][1]; - const xj = polygon[j][0], - zj = polygon[j][1]; - - const intersect = - // eslint-disable-next-line no-mixed-operators - zi > point[1] !== zj > point[1] && - point[0] < ((xj - xi) * (point[1] - zi)) / (zj - zi + 0.000001) + xi; - - if (intersect) inside = !inside; - } - return inside; - }; - - useEffect(() => { - const updatedZoneList: ZoneData[] = zones?.map((zone: any) => { - const polygon2D = zone.points.map((p: [number, number, number]) => [ - p[0], - p[2], - ]); - - const assetsInZone = assets - .filter((item: any) => { - const [x, , z] = item.position; - return isPointInsidePolygon([x, z], polygon2D as [number, number][]); - }) - .map((item: any) => ({ - id: item.modelUuid, - name: item.modelName, - position: item.position, - rotation: item.rotation, - })); - - return { - id: zone.zoneUuid, - name: zone.zoneName, - assets: assetsInZone, - }; - }); - - setZoneDataList(updatedZoneList); - }, [zones, assets]); - return (
- {/* eslint-disable-next-line */} -
+
{value}
{showFocusIcon && ( @@ -130,31 +55,15 @@ const DropDownList: React.FC = ({ title="collapse-btn" className="collapse-icon option" style={{ transform: isOpen ? "rotate(0deg)" : "rotate(-90deg)" }} - // onClick={handleToggle} >
+ {isOpen && (
- {listType === "default" && } - {listType === "outline" && ( - <> - - - - )} +
)}
diff --git a/app/src/functions/isPointInsidePolygon.ts b/app/src/functions/isPointInsidePolygon.ts new file mode 100644 index 0000000..7fa1846 --- /dev/null +++ b/app/src/functions/isPointInsidePolygon.ts @@ -0,0 +1,20 @@ +export const isPointInsidePolygon = ( + point: [number, number], + polygon: [number, number][] +) => { + let inside = false; + for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { + const xi = polygon[i][0], + zi = polygon[i][1]; + const xj = polygon[j][0], + zj = polygon[j][1]; + + const intersect = + // eslint-disable-next-line no-mixed-operators + zi > point[1] !== zj > point[1] && + point[0] < ((xj - xi) * (point[1] - zi)) / (zj - zi + 0.000001) + xi; + + if (intersect) inside = !inside; + } + return inside; +}; \ No newline at end of file