added market placeCards

This commit is contained in:
Nalvazhuthi 2025-03-26 12:32:09 +05:30
commit 9a358bc1c0
23 changed files with 967 additions and 671 deletions

57
app/.gitignore vendored
View File

@ -1,28 +1,29 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies # dependencies
/node_modules /node_modules
/.pnp /package-lock.json
.pnp.js /.pnp
.pnp.js
# testing
/coverage # testing
/coverage
# production
/build # production
/build
# misc
.DS_Store # misc
.env.local .DS_Store
.env.development.local .env.local
.env.test.local .env.development.local
.env.production.local .env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log* npm-debug.log*
yarn-error.log* yarn-debug.log*
yarn-error.log*
# remove zip
*.zip # remove zip
**/temp/ *.zip
**/temp/

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -107,7 +107,7 @@ export function StockIncreseIcon() {
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<g clip-path="url(#clip0_3050_69519)"> <g clipPath="url(#clip0_3050_69519)">
<path <path
d="M7.80766 6.99219H1.17811C0.752382 6.99219 0.407227 7.33734 0.407227 7.76307C0.407227 8.18879 0.752382 8.53395 1.17811 8.53395H7.80766C8.23339 8.53395 8.57854 8.18879 8.57854 7.76307C8.57854 7.33733 8.23339 6.99219 7.80766 6.99219Z" d="M7.80766 6.99219H1.17811C0.752382 6.99219 0.407227 7.33734 0.407227 7.76307C0.407227 8.18879 0.752382 8.53395 1.17811 8.53395H7.80766C8.23339 8.53395 8.57854 8.18879 8.57854 7.76307C8.57854 7.33733 8.23339 6.99219 7.80766 6.99219Z"
fill="white" fill="white"
@ -142,8 +142,8 @@ export function StockIncreseIcon() {
y2="8.53122" y2="8.53122"
gradientUnits="userSpaceOnUse" gradientUnits="userSpaceOnUse"
> >
<stop stop-color="#31B2B9" /> <stop stopColor="#31B2B9" />
<stop offset="1" stop-color="#FBD8B8" /> <stop offset="1" stopColor="#FBD8B8" />
</linearGradient> </linearGradient>
<clipPath id="clip0_3050_69519"> <clipPath id="clip0_3050_69519">
<rect <rect

View File

@ -44,23 +44,23 @@ export function DownloadIcon() {
export function EyeIconBig() { export function EyeIconBig() {
return ( return (
<svg <svg
width="20" width="22"
height="20" height="22"
viewBox="0 0 20 20" viewBox="0 0 22 22"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<path <path
fill-rule="evenodd" d="M2.75 11.918C6.05 4.58464 15.95 4.58464 19.25 11.918"
clip-rule="evenodd" stroke="#2B3344"
d="M2.5 11.875C2.84518 11.875 3.125 12.1548 3.125 12.5C3.125 13.6962 3.12633 14.5304 3.21096 15.1599C3.29317 15.7714 3.44354 16.0952 3.67418 16.3258C3.90481 16.5565 4.22863 16.7068 4.8401 16.7891C5.46956 16.8737 6.30383 16.875 7.5 16.875H12.5C13.6962 16.875 14.5304 16.8737 15.1599 16.7891C15.7714 16.7068 16.0952 16.5565 16.3258 16.3258C16.5565 16.0952 16.7068 15.7714 16.7891 15.1599C16.8737 14.5304 16.875 13.6962 16.875 12.5C16.875 12.1548 17.1548 11.875 17.5 11.875C17.8452 11.875 18.125 12.1548 18.125 12.5V12.5458C18.125 13.6854 18.125 14.604 18.0279 15.3265C17.9271 16.0766 17.7113 16.7081 17.2097 17.2097C16.7081 17.7113 16.0766 17.9271 15.3265 18.0279C14.604 18.125 13.6854 18.125 12.5458 18.125H7.45428C6.31462 18.125 5.39602 18.125 4.67354 18.0279C3.92345 17.9271 3.29189 17.7113 2.79029 17.2097C2.28869 16.7081 2.07295 16.0766 1.9721 15.3265C1.87497 14.604 1.87498 13.6854 1.875 12.5458C1.875 12.5305 1.875 12.5152 1.875 12.5C1.875 12.1548 2.15483 11.875 2.5 11.875Z" stroke-linecap="round"
fill="#FCFDFD" stroke-linejoin="round"
/> />
<path <path
fill-rule="evenodd" d="M11 15.5859C10.6389 15.5859 10.2813 15.5148 9.94762 15.3766C9.61398 15.2384 9.31082 15.0358 9.05546 14.7805C8.80009 14.5251 8.59753 14.222 8.45933 13.8883C8.32113 13.5547 8.25 13.1971 8.25 12.8359C8.25 12.4748 8.32113 12.1172 8.45933 11.7836C8.59753 11.4499 8.80009 11.1468 9.05546 10.8914C9.31082 10.636 9.61398 10.4335 9.94762 10.2953C10.2813 10.1571 10.6389 10.0859 11 10.0859C11.7293 10.0859 12.4288 10.3757 12.9445 10.8914C13.4603 11.4071 13.75 12.1066 13.75 12.8359C13.75 13.5653 13.4603 14.2648 12.9445 14.7805C12.4288 15.2962 11.7293 15.5859 11 15.5859Z"
clip-rule="evenodd" stroke="#2B3344"
d="M10.0003 13.9583C10.1758 13.9583 10.3432 13.8846 10.4616 13.7551L13.7949 10.1093C14.0278 9.8545 14.0102 9.45917 13.7554 9.22625C13.5007 8.99333 13.1053 9.011 12.8724 9.26575L10.6253 11.7235V2.5C10.6253 2.15483 10.3455 1.875 10.0003 1.875C9.65516 1.875 9.37533 2.15483 9.37533 2.5V11.7235L7.12827 9.26575C6.89535 9.011 6.50002 8.99333 6.24527 9.22625C5.99052 9.45917 5.97281 9.8545 6.20573 10.1093L9.53908 13.7551C9.65749 13.8846 9.82483 13.9583 10.0003 13.9583Z" stroke-linecap="round"
fill="#FCFDFD" stroke-linejoin="round"
/> />
</svg> </svg>
); );

View File

@ -3,9 +3,12 @@ import { ToggleSidebarIcon } from "../../icons/HeaderIcons";
import { LogoIcon } from "../../icons/Logo"; import { LogoIcon } from "../../icons/Logo";
import FileMenu from "../../ui/FileMenu"; import FileMenu from "../../ui/FileMenu";
import useToggleStore from "../../../store/useUIToggleStore"; import useToggleStore from "../../../store/useUIToggleStore";
import useModuleStore from "../../../store/useModuleStore";
const Header: React.FC = () => { const Header: React.FC = () => {
const { toggleUI, setToggleUI } = useToggleStore(); const { toggleUI, setToggleUI } = useToggleStore();
const { activeModule } = useModuleStore();
return ( return (
<div className="header-container"> <div className="header-container">
<div className="header-content"> <div className="header-content">
@ -19,7 +22,7 @@ const Header: React.FC = () => {
<div <div
className={`toggle-sidebar-ui-button ${!toggleUI ? "active" : ""}`} className={`toggle-sidebar-ui-button ${!toggleUI ? "active" : ""}`}
onClick={() => { onClick={() => {
setToggleUI(!toggleUI); if (activeModule !== "market") setToggleUI(!toggleUI);
}} }}
> >
<ToggleSidebarIcon /> <ToggleSidebarIcon />

View File

@ -1,6 +1,8 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Header from "./Header"; import Header from "./Header";
import useModuleStore from "../../../store/useModuleStore"; import useModuleStore, {
useSubModuleStore,
} from "../../../store/useModuleStore";
import { import {
AnalysisIcon, AnalysisIcon,
MechanicsIcon, MechanicsIcon,
@ -14,15 +16,19 @@ import GlobalProperties from "./properties/GlobalProperties";
import AsstePropertiies from "./properties/AssetProperties"; import AsstePropertiies from "./properties/AssetProperties";
import Analysis from "./analysis/Analysis"; import Analysis from "./analysis/Analysis";
import Simulations from "./simulation/Simulations"; import Simulations from "./simulation/Simulations";
import { useSelectedActionSphere } from "../../../store/store";
import ZoneProperties from "./properties/ZoneProperties";
const SideBarRight: React.FC = () => { const SideBarRight: React.FC = () => {
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const [activeList, setActiveList] = useState("properties"); const [activeList] = useState("properties");
const { toggleUI } = useToggleStore(); const { toggleUI } = useToggleStore();
const { selectedActionSphere } = useSelectedActionSphere();
const { subModule, setSubModule } = useSubModuleStore();
// Reset activeList whenever activeModule changes // Reset activeList whenever activeModule changes
useEffect(() => { useEffect(() => {
setActiveList("properties"); if (activeModule !== "simulation") setSubModule("properties");
if (activeModule === "simulation") setSubModule("mechanics");
}, [activeModule]); }, [activeModule]);
return ( return (
@ -30,37 +36,39 @@ const SideBarRight: React.FC = () => {
<Header /> <Header />
{toggleUI && ( {toggleUI && (
<div className="sidebar-actions-container"> <div className="sidebar-actions-container">
{/* {activeModule === "builder" && ( */}
<div <div
className={`sidebar-action-list ${ className={`sidebar-action-list ${
activeList === "properties" ? "active" : "" subModule === "properties" ? "active" : ""
}`} }`}
onClick={() => setActiveList("properties")} onClick={() => setSubModule("properties")}
> >
<PropertiesIcon isActive={activeList === "properties"} /> <PropertiesIcon isActive={subModule === "properties"} />
</div> </div>
{/* )} */}
{activeModule === "simulation" && ( {activeModule === "simulation" && (
<> <>
<div <div
className={`sidebar-action-list ${ className={`sidebar-action-list ${
activeList === "mechanics" ? "active" : "" subModule === "mechanics" ? "active" : ""
}`} }`}
onClick={() => setActiveList("mechanics")} onClick={() => setSubModule("mechanics")}
> >
<MechanicsIcon isActive={activeList === "mechanics"} /> <MechanicsIcon isActive={activeList === "mechanics"} />
</div> </div>
<div <div
className={`sidebar-action-list ${ className={`sidebar-action-list ${
activeList === "simulations" ? "active" : "" subModule === "simulations" ? "active" : ""
}`} }`}
onClick={() => setActiveList("simulations")} onClick={() => setSubModule("simulations")}
> >
<SimulationIcon isActive={activeList === "simulations"} /> <SimulationIcon isActive={activeList === "simulations"} />
</div> </div>
<div <div
className={`sidebar-action-list ${ className={`sidebar-action-list ${
activeList === "analysis" ? "active" : "" subModule === "analysis" ? "active" : ""
}`} }`}
onClick={() => setActiveList("analysis")} onClick={() => setSubModule("analysis")}
> >
<AnalysisIcon isActive={activeList === "analysis"} /> <AnalysisIcon isActive={activeList === "analysis"} />
</div> </div>
@ -75,6 +83,7 @@ const SideBarRight: React.FC = () => {
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
<GlobalProperties /> <GlobalProperties />
{/* <ZoneProperties /> */}
{/* <AsstePropertiies /> */} {/* <AsstePropertiies /> */}
</div> </div>
</div> </div>
@ -84,14 +93,21 @@ const SideBarRight: React.FC = () => {
{toggleUI && activeModule === "simulation" && ( {toggleUI && activeModule === "simulation" && (
<> <>
{activeList === "mechanics" && ( {subModule === "mechanics" && selectedActionSphere && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
<MachineMechanics /> <MachineMechanics />
</div> </div>
</div> </div>
)} )}
{activeList === "analysis" && ( {subModule === "mechanics" && !selectedActionSphere && (
<div className="sidebar-right-container">
<div className="sidebar-right-content-container">
<MachineMechanics />
</div>
</div>
)}
{subModule === "analysis" && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
<Analysis /> <Analysis />

View File

@ -0,0 +1,59 @@
import React from "react";
import { EyeDroperIcon } from "../../../icons/ExportCommonIcons";
interface PositionInputProps {
onChange: (value: string) => void; // Callback for value change
header: string;
placeholder?: string; // Optional placeholder
type?: string; // Input type (e.g., text, number, email)
}
const Vector3Input: React.FC<PositionInputProps> = ({
onChange,
header,
placeholder = "Enter value", // Default placeholder
type = "number", // Default type
}) => {
return (
<div className="custom-input-container">
<div className="header">
{header}{" "}
<div className="eyedrop-button">
<EyeDroperIcon isActive={false} />
</div>
</div>
<div className="inputs-container">
<div className="input-container">
<div className="custom-input-label">X : </div>
<input
className="custom-input-field"
type={type}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
/>
</div>
<div className="input-container">
<div className="custom-input-label">Y : </div>
<input
className="custom-input-field"
type={type}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
min={0}
/>
</div>
<div className="input-container">
<div className="custom-input-label">Z : </div>
<input
className="custom-input-field"
type={type}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
/>
</div>
</div>
</div>
);
};
export default Vector3Input;

View File

@ -14,8 +14,8 @@ import EyeDropInput from "../../../ui/inputs/EyeDropInput";
import { useSelectedActionSphere } from "../../../../store/store"; import { useSelectedActionSphere } from "../../../../store/store";
const MachineMechanics: React.FC = () => { const MachineMechanics: React.FC = () => {
const { selectedActionSphere, setSelectedActionSphere } = useSelectedActionSphere(); const { selectedActionSphere } = useSelectedActionSphere();
console.log('selectedActionSphere: ', selectedActionSphere); console.log("selectedActionSphere: ", selectedActionSphere);
const [actionList, setActionList] = useState<string[]>([]); const [actionList, setActionList] = useState<string[]>([]);
const [triggerList, setTriggerList] = useState<string[]>([]); const [triggerList, setTriggerList] = useState<string[]>([]);
const [selectedItem, setSelectedItem] = useState<{ const [selectedItem, setSelectedItem] = useState<{
@ -71,7 +71,9 @@ const MachineMechanics: React.FC = () => {
return ( return (
<div className="machine-mechanics-container"> <div className="machine-mechanics-container">
<div className="machine-mechanics-header">{selectedActionSphere.path.modelName}</div> <div className="machine-mechanics-header">
{selectedActionSphere?.path?.modelName || "path name not found"}
</div>
{/* <div className="process-list-container"> {/* <div className="process-list-container">
<div className="label">Process:</div> <div className="label">Process:</div>
<RegularDropDown <RegularDropDown
@ -100,11 +102,12 @@ const MachineMechanics: React.FC = () => {
{actionList.map((action, index) => ( {actionList.map((action, index) => (
<div <div
key={index} key={index}
className={`list-item ${selectedItem?.type === "action" && className={`list-item ${
selectedItem?.type === "action" &&
selectedItem.name === action selectedItem.name === action
? "active" ? "active"
: "" : ""
}`} }`}
> >
<div <div
className="value" className="value"
@ -146,11 +149,12 @@ const MachineMechanics: React.FC = () => {
{triggerList.map((trigger, index) => ( {triggerList.map((trigger, index) => (
<div <div
key={index} key={index}
className={`list-item ${selectedItem?.type === "trigger" && className={`list-item ${
selectedItem?.type === "trigger" &&
selectedItem.name === trigger selectedItem.name === trigger
? "active" ? "active"
: "" : ""
}`} }`}
> >
<div <div
className="value" className="value"
@ -188,7 +192,7 @@ const MachineMechanics: React.FC = () => {
label="Speed" label="Speed"
value="" value=""
activeOption=".mm" activeOption=".mm"
onChange={() => { }} onChange={() => {}}
/> />
<EyeDropInput /> <EyeDropInput />
</> </>

View File

@ -0,0 +1,17 @@
import React from "react";
import RenameInput from "../../../ui/inputs/RenameInput";
import Vector3Input from "../customInput/Vector3Input";
const ZoneProperties = () => {
return (
<div className="zone-properties-container">
<div className="header">
<RenameInput value="Selected Zone Name" />
</div>
<Vector3Input onChange={()=>{}} header="Target"/>
<Vector3Input onChange={()=>{}} header="Position"/>
</div>
);
};
export default ZoneProperties;

View File

@ -28,7 +28,7 @@ const DropList: React.FC<DropListProps> = ({ val }) => {
}} }}
> >
{val.pathName} {val.pathName}
<div className="arrow-container"> <div className={`arrow-container${openDrop ? " active" : ""}`}>
<ArrowIcon /> <ArrowIcon />
</div> </div>
</div> </div>
@ -87,8 +87,9 @@ const Simulations: React.FC = () => {
{productsList.map((action, index) => ( {productsList.map((action, index) => (
<div <div
key={index} key={index}
className={`list-item ${selectedItem === action ? "active" : "" className={`list-item ${
}`} selectedItem === action ? "active" : ""
}`}
> >
<div <div
className="value" className="value"

View File

@ -6,17 +6,20 @@ import {
SimulationIcon, SimulationIcon,
VisualizationIcon, VisualizationIcon,
} from "../icons/ExportModuleIcons"; } from "../icons/ExportModuleIcons";
import { usePlayButtonStore } from "../../store/usePlayButtonStore"; import useToggleStore from "../../store/useUIToggleStore";
const ModuleToggle: React.FC = () => { const ModuleToggle: React.FC = () => {
const { activeModule, setActiveModule } = useModuleStore(); const { activeModule, setActiveModule } = useModuleStore();
const { isPlaying, setIsPlaying } = usePlayButtonStore(); const { setToggleUI } = useToggleStore();
return ( return (
<div className="module-toggle-container"> <div className="module-toggle-container">
<div <div
className={`module-list ${activeModule === "builder" && "active"}`} className={`module-list ${activeModule === "builder" && "active"}`}
onClick={() => setActiveModule("builder")} onClick={() => {
setActiveModule("builder");
setToggleUI(true);
}}
> >
<div className="icon"> <div className="icon">
<BuilderIcon isActive={activeModule === "builder"} /> <BuilderIcon isActive={activeModule === "builder"} />
@ -25,7 +28,10 @@ const ModuleToggle: React.FC = () => {
</div> </div>
<div <div
className={`module-list ${activeModule === "simulation" && "active"}`} className={`module-list ${activeModule === "simulation" && "active"}`}
onClick={() => setActiveModule("simulation")} onClick={() => {
setActiveModule("simulation");
setToggleUI(true);
}}
> >
<div className="icon"> <div className="icon">
<SimulationIcon isActive={activeModule === "simulation"} /> <SimulationIcon isActive={activeModule === "simulation"} />
@ -36,7 +42,10 @@ const ModuleToggle: React.FC = () => {
className={`module-list ${ className={`module-list ${
activeModule === "visualization" && "active" activeModule === "visualization" && "active"
}`} }`}
onClick={() => setActiveModule("visualization")} onClick={() => {
setActiveModule("visualization");
setToggleUI(true);
}}
> >
<div className="icon"> <div className="icon">
<VisualizationIcon isActive={activeModule === "visualization"} /> <VisualizationIcon isActive={activeModule === "visualization"} />
@ -45,7 +54,10 @@ const ModuleToggle: React.FC = () => {
</div> </div>
<div <div
className={`module-list ${activeModule === "market" && "active"}`} className={`module-list ${activeModule === "market" && "active"}`}
onClick={() => setActiveModule("market")} onClick={() => {
setActiveModule("market");
setToggleUI(false);
}}
> >
<div className="icon"> <div className="icon">
<CartIcon isActive={activeModule === "market"} /> <CartIcon isActive={activeModule === "market"} />

View File

@ -5,6 +5,7 @@ import AddButtons from "./AddButtons";
import { useSelectedZoneStore } from "../../../store/useZoneStore"; import { useSelectedZoneStore } from "../../../store/useZoneStore";
import DisplayZone from "./DisplayZone"; import DisplayZone from "./DisplayZone";
import Scene from "../../../modules/scene/scene"; import Scene from "../../../modules/scene/scene";
import useModuleStore from "../../../store/useModuleStore";
type Side = "top" | "bottom" | "left" | "right"; type Side = "top" | "bottom" | "left" | "right";
@ -60,6 +61,7 @@ const RealTimeVisulization: React.FC = () => {
}); });
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { activeModule } = useModuleStore();
const { selectedZone, setSelectedZone } = useSelectedZoneStore(); const { selectedZone, setSelectedZone } = useSelectedZoneStore();
useEffect(() => { useEffect(() => {
@ -73,36 +75,48 @@ const RealTimeVisulization: React.FC = () => {
<div <div
ref={containerRef} ref={containerRef}
id="real-time-vis-canvas" id="real-time-vis-canvas"
className={`realTime-viz canvas ${!isPlaying ? "playActiveFalse" : ""}`} className="realTime-viz canvas"
style={{ style={{
height: isPlaying ? "100vh" : "", height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
left: isPlaying ? "0%" : "", width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
}} }}
> >
<div <div
className="scene-container" className="scene-container"
style={{ height: "100%", width: "100%" }} style={{
height: "100%",
width: "100%",
borderRadius:
isPlaying || activeModule !== "visualization" ? "" : "6px",
}}
> >
<Scene /> <Scene />
</div> </div>
{!isPlaying && ( {activeModule === "visualization" && (
<AddButtons <>
hiddenPanels={hiddenPanels} <DisplayZone
setHiddenPanels={setHiddenPanels} zonesData={zonesData}
selectedZone={selectedZone} selectedZone={selectedZone}
setSelectedZone={setSelectedZone} setSelectedZone={setSelectedZone}
/> />
{!isPlaying && (
<AddButtons
hiddenPanels={hiddenPanels}
setHiddenPanels={setHiddenPanels}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
)}
<Panel
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
hiddenPanels={hiddenPanels}
/>
</>
)} )}
<DisplayZone
zonesData={zonesData}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
<Panel
selectedZone={selectedZone}
hiddenPanels={hiddenPanels}
setSelectedZone={setSelectedZone}
/>{" "}
</div> </div>
); );
}; };

View File

@ -1,466 +1,509 @@
import React, { useState, useEffect, useMemo, useRef } from "react"; import React, { useState, useEffect, useMemo, useRef } from "react";
import { Line, Sphere } from "@react-three/drei"; import { Line, Sphere } from "@react-three/drei";
import { useThree, useFrame } from "@react-three/fiber"; import { useThree, useFrame } from "@react-three/fiber";
import * as THREE from "three"; import * as THREE from "three";
import { useActiveLayer, useDeleteModels, useDeletePointOrLine, useMovePoint, useSocketStore, useToggleView, useToolMode, useRemovedLayer, useZones, useZonePoints } from "../../../store/store"; import { useActiveLayer, useDeleteModels, useDeletePointOrLine, useMovePoint, useSocketStore, useToggleView, useToolMode, useRemovedLayer, useZones, useZonePoints } from "../../../store/store";
// import { setZonesApi } from "../../../services/factoryBuilder/zones/setZonesApi"; // import { setZonesApi } from "../../../services/factoryBuilder/zones/setZonesApi";
// import { deleteZonesApi } from "../../../services/factoryBuilder/zones/deleteZoneApi"; // import { deleteZonesApi } from "../../../services/factoryBuilder/zones/deleteZoneApi";
import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi"; import { getZonesApi } from "../../../services/factoryBuilder/zones/getZonesApi";
import * as CONSTANTS from '../../../types/world/worldConstants'; import * as CONSTANTS from '../../../types/world/worldConstants';
const ZoneGroup: React.FC = () => { const ZoneGroup: React.FC = () => {
const { camera, pointer, gl, raycaster, scene, controls } = useThree(); const { camera, pointer, gl, raycaster, scene, controls } = useThree();
const [startPoint, setStartPoint] = useState<THREE.Vector3 | null>(null); const [startPoint, setStartPoint] = useState<THREE.Vector3 | null>(null);
const [endPoint, setEndPoint] = useState<THREE.Vector3 | null>(null); const [endPoint, setEndPoint] = useState<THREE.Vector3 | null>(null);
const { zones, setZones } = useZones(); const { zones, setZones } = useZones();
const { zonePoints, setZonePoints } = useZonePoints(); const { zonePoints, setZonePoints } = useZonePoints();
const [isDragging, setIsDragging] = useState(false); const [isDragging, setIsDragging] = useState(false);
const [draggedSphere, setDraggedSphere] = useState<THREE.Vector3 | null>(null); const [draggedSphere, setDraggedSphere] = useState<THREE.Vector3 | null>(null);
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const { toggleView } = useToggleView(); const { toggleView } = useToggleView();
const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
const { removedLayer, setRemovedLayer } = useRemovedLayer(); const { removedLayer, setRemovedLayer } = useRemovedLayer();
const { toolMode, setToolMode } = useToolMode(); const { toolMode, setToolMode } = useToolMode();
const { movePoint, setMovePoint } = useMovePoint(); const { movePoint, setMovePoint } = useMovePoint();
const { deleteModels, setDeleteModels } = useDeleteModels(); const { deleteModels, setDeleteModels } = useDeleteModels();
const { activeLayer, setActiveLayer } = useActiveLayer(); const { activeLayer, setActiveLayer } = useActiveLayer();
const { socket } = useSocketStore(); const { socket } = useSocketStore();
const groupsRef = useRef<any>(); const groupsRef = useRef<any>();
const zoneMaterial = useMemo(() => new THREE.ShaderMaterial({ const zoneMaterial = useMemo(() => new THREE.ShaderMaterial({
side: THREE.DoubleSide, side: THREE.DoubleSide,
vertexShader: ` vertexShader: `
varying vec2 vUv; varying vec2 vUv;
void main(){ void main(){
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vUv = uv; vUv = uv;
} }
`, `,
fragmentShader: ` fragmentShader: `
varying vec2 vUv; varying vec2 vUv;
uniform vec3 uColor; uniform vec3 uColor;
void main(){ void main(){
float alpha = 1.0 - vUv.y; float alpha = 1.0 - vUv.y;
gl_FragColor = vec4(uColor, alpha); gl_FragColor = vec4(uColor, alpha);
} }
`, `,
uniforms: { uniforms: {
uColor: { value: new THREE.Color(CONSTANTS.zoneConfig.color) }, uColor: { value: new THREE.Color(CONSTANTS.zoneConfig.color) },
}, },
transparent: true, transparent: true,
}), []); }), []);
useEffect(() => { useEffect(() => {
const fetchZones = async () => { const fetchZones = async () => {
const email = localStorage.getItem('email'); const email = localStorage.getItem('email');
if (!email) return; if (!email) return;
const organization = email.split("@")[1].split(".")[0]; const organization = email.split("@")[1].split(".")[0];
const data = await getZonesApi(organization); const data = await getZonesApi(organization);
if (data.data && data.data.length > 0) { if (data.data && data.data.length > 0) {
const fetchedZones = data.data.map((zone: any) => ({ const fetchedZones = data.data.map((zone: any) => ({
zoneId: zone.zoneId, zoneId: zone.zoneId,
zoneName: zone.zoneName, zoneName: zone.zoneName,
points: zone.points, points: zone.points,
layer: zone.layer layer: zone.layer
})); }));
setZones(fetchedZones); setZones(fetchedZones);
const fetchedPoints = data.data.flatMap((zone: any) => const fetchedPoints = data.data.flatMap((zone: any) =>
zone.points.slice(0, 4).map((point: [number, number, number]) => new THREE.Vector3(...point)) zone.points.slice(0, 4).map((point: [number, number, number]) => new THREE.Vector3(...point))
); );
setZonePoints(fetchedPoints); setZonePoints(fetchedPoints);
} }
}; };
fetchZones(); fetchZones();
}, []); }, []);
useEffect(() => { useEffect(() => {
localStorage.setItem('zones', JSON.stringify(zones)); localStorage.setItem('zones', JSON.stringify(zones));
}, [zones]) }, [zones])
useEffect(() => { useEffect(() => {
if (removedLayer) { if (removedLayer) {
const updatedZones = zones.filter((zone: any) => zone.layer !== removedLayer); const updatedZones = zones.filter((zone: any) => zone.layer !== removedLayer);
setZones(updatedZones); setZones(updatedZones);
const updatedzonePoints = zonePoints.filter((_: any, index: any) => { const updatedzonePoints = zonePoints.filter((_: any, index: any) => {
const zoneIndex = Math.floor(index / 4); const zoneIndex = Math.floor(index / 4);
return zones[zoneIndex]?.layer !== removedLayer; return zones[zoneIndex]?.layer !== removedLayer;
}); });
setZonePoints(updatedzonePoints); setZonePoints(updatedzonePoints);
zones.filter((zone: any) => zone.layer === removedLayer).forEach((zone: any) => { zones.filter((zone: any) => zone.layer === removedLayer).forEach((zone: any) => {
deleteZoneFromBackend(zone.zoneId); deleteZoneFromBackend(zone.zoneId);
}); });
setRemovedLayer(null); setRemovedLayer(null);
} }
}, [removedLayer]); }, [removedLayer]);
useEffect(() => { useEffect(() => {
if (toolMode !== "Zone") { if (toolMode !== "Zone") {
setStartPoint(null); setStartPoint(null);
setEndPoint(null); setEndPoint(null);
} else { } else {
setDeletePointOrLine(false); setDeletePointOrLine(false);
setMovePoint(false); setMovePoint(false);
setDeleteModels(false); setDeleteModels(false);
} }
if (!toggleView) { if (!toggleView) {
setStartPoint(null); setStartPoint(null);
setEndPoint(null); setEndPoint(null);
} }
}, [toolMode, toggleView]); }, [toolMode, toggleView]);
const addZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => { const addZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => {
const email = localStorage.getItem('email'); const email = localStorage.getItem('email');
const userId = localStorage.getItem('userId'); const userId = localStorage.getItem('userId');
const organization = (email!.split("@")[1]).split(".")[0]; const organization = (email!.split("@")[1]).split(".")[0];
const input = { const calculateCenter = (points: number[][]) => {
userId: userId, if (!points || points.length === 0) return null;
organization: organization,
zoneData: { let sumX = 0, sumY = 0, sumZ = 0;
zoneName: zone.zoneName, const numPoints = points.length;
zoneId: zone.zoneId,
points: zone.points, points.forEach(([x, y, z]) => {
layer: zone.layer sumX += x;
} sumY += y;
} sumZ += z;
});
socket.emit('v2:zone:set', input);
}; return [sumX / numPoints, sumY / numPoints, sumZ / numPoints] as [number, number, number];
};
const updateZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => {
const target: [number, number, number] | null = calculateCenter(zone.points);
const email = localStorage.getItem('email'); if (!target) return;
const userId = localStorage.getItem('userId'); const position = [target[0], 75, target[2]];
const organization = (email!.split("@")[1]).split(".")[0];
const input = {
const input = { userId: userId,
userId: userId, organization: organization,
organization: organization, zoneData: {
zoneData: { zoneName: zone.zoneName,
zoneName: zone.zoneName, zoneId: zone.zoneId,
zoneId: zone.zoneId, points: zone.points,
points: zone.points, viewPortCenter: target,
layer: zone.layer viewPortposition: position,
} layer: zone.layer
} }
}
socket.emit('v2:zone:set', input);
}; socket.emit('v2:zone:set', input);
};
const deleteZoneFromBackend = async (zoneId: string) => {
const updateZoneToBackend = async (zone: { zoneId: string; zoneName: string; points: [number, number, number][]; layer: string }) => {
const email = localStorage.getItem('email');
const userId = localStorage.getItem('userId'); const email = localStorage.getItem('email');
const organization = (email!.split("@")[1]).split(".")[0]; const userId = localStorage.getItem('userId');
const organization = (email!.split("@")[1]).split(".")[0];
const input = {
userId: userId, const calculateCenter = (points: number[][]) => {
organization: organization, if (!points || points.length === 0) return null;
zoneId: zoneId
} let sumX = 0, sumY = 0, sumZ = 0;
const numPoints = points.length;
socket.emit('v2:zone:delete', input);
}; points.forEach(([x, y, z]) => {
sumX += x;
const handleDeleteZone = (zoneId: string) => { sumY += y;
const updatedZones = zones.filter((zone: any) => zone.zoneId !== zoneId); sumZ += z;
setZones(updatedZones); });
const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === zoneId); return [sumX / numPoints, sumY / numPoints, sumZ / numPoints] as [number, number, number];
if (zoneIndex !== -1) { };
const zonePointsToRemove = zonePoints.slice(zoneIndex * 4, zoneIndex * 4 + 4);
zonePointsToRemove.forEach((point: any) => groupsRef.current.remove(point)); const target: [number, number, number] | null = calculateCenter(zone.points);
const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4); if (!target) return;
setZonePoints(updatedzonePoints); const position = [target[0], 75, target[2]];
}
const input = {
deleteZoneFromBackend(zoneId); userId: userId,
}; organization: organization,
zoneData: {
useEffect(() => { zoneName: zone.zoneName,
if (!camera || !toggleView) return; zoneId: zone.zoneId,
const canvasElement = gl.domElement; points: zone.points,
viewPortCenter: target,
let drag = false; viewPortposition: position,
let isLeftMouseDown = false; layer: zone.layer
}
const onMouseDown = (evt: any) => { }
if (evt.button === 0) {
isLeftMouseDown = true; socket.emit('v2:zone:set', input);
drag = false; };
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObjects(groupsRef.current.children, true); const deleteZoneFromBackend = async (zoneId: string) => {
if (intersects.length > 0 && movePoint) { const email = localStorage.getItem('email');
const clickedObject = intersects[0].object; const userId = localStorage.getItem('userId');
const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position)); const organization = (email!.split("@")[1]).split(".")[0];
if (sphereIndex !== -1) {
(controls as any).enabled = false; const input = {
setDraggedSphere(zonePoints[sphereIndex]); userId: userId,
setIsDragging(true); organization: organization,
} zoneId: zoneId
} }
}
}; socket.emit('v2:zone:delete', input);
};
const onMouseUp = (evt: any) => {
if (evt.button === 0 && !drag && !isDragging && !deletePointOrLine) { const handleDeleteZone = (zoneId: string) => {
isLeftMouseDown = false; const updatedZones = zones.filter((zone: any) => zone.zoneId !== zoneId);
setZones(updatedZones);
if (!startPoint && !movePoint) {
raycaster.setFromCamera(pointer, camera); const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === zoneId);
const intersectionPoint = new THREE.Vector3(); if (zoneIndex !== -1) {
const point = raycaster.ray.intersectPlane(plane, intersectionPoint); const zonePointsToRemove = zonePoints.slice(zoneIndex * 4, zoneIndex * 4 + 4);
if (point) { zonePointsToRemove.forEach((point: any) => groupsRef.current.remove(point));
setStartPoint(point); const updatedzonePoints = zonePoints.filter((_: any, index: any) => index < zoneIndex * 4 || index >= zoneIndex * 4 + 4);
setEndPoint(null); setZonePoints(updatedzonePoints);
} }
} else if (startPoint && !movePoint) {
raycaster.setFromCamera(pointer, camera); deleteZoneFromBackend(zoneId);
const intersectionPoint = new THREE.Vector3(); };
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (!point) return; useEffect(() => {
if (!camera || !toggleView) return;
const points = [ const canvasElement = gl.domElement;
[startPoint.x, 0.15, startPoint.z],
[point.x, 0.15, startPoint.z], let drag = false;
[point.x, 0.15, point.z], let isLeftMouseDown = false;
[startPoint.x, 0.15, point.z],
[startPoint.x, 0.15, startPoint.z], const onMouseDown = (evt: any) => {
] as [number, number, number][]; if (evt.button === 0) {
isLeftMouseDown = true;
const zoneName = `Zone ${zones.length + 1}`; drag = false;
const zoneId = THREE.MathUtils.generateUUID();
const newZone = { raycaster.setFromCamera(pointer, camera);
zoneId, const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
zoneName,
points: points, if (intersects.length > 0 && movePoint) {
layer: activeLayer const clickedObject = intersects[0].object;
}; const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position));
if (sphereIndex !== -1) {
const newZones = [...zones, newZone]; (controls as any).enabled = false;
setDraggedSphere(zonePoints[sphereIndex]);
setZones(newZones); setIsDragging(true);
}
const newzonePoints = [ }
new THREE.Vector3(startPoint.x, 0.15, startPoint.z), }
new THREE.Vector3(point.x, 0.15, startPoint.z), };
new THREE.Vector3(point.x, 0.15, point.z),
new THREE.Vector3(startPoint.x, 0.15, point.z), const onMouseUp = (evt: any) => {
]; if (evt.button === 0 && !drag && !isDragging && !deletePointOrLine) {
isLeftMouseDown = false;
const updatedZonePoints = [...zonePoints, ...newzonePoints];
setZonePoints(updatedZonePoints); if (!startPoint && !movePoint) {
raycaster.setFromCamera(pointer, camera);
addZoneToBackend(newZone); const intersectionPoint = new THREE.Vector3();
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
setStartPoint(null); if (point) {
setEndPoint(null); setStartPoint(point);
} setEndPoint(null);
} else if (evt.button === 0 && !drag && !isDragging && deletePointOrLine) { }
raycaster.setFromCamera(pointer, camera); } else if (startPoint && !movePoint) {
const intersects = raycaster.intersectObjects(groupsRef.current.children, true); raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3();
if (intersects.length > 0) { const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
const clickedObject = intersects[0].object; if (!point) return;
const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position)); const points = [
if (sphereIndex !== -1) { [startPoint.x, 0.15, startPoint.z],
const zoneIndex = Math.floor(sphereIndex / 4); [point.x, 0.15, startPoint.z],
const zoneId = zones[zoneIndex].zoneId; [point.x, 0.15, point.z],
handleDeleteZone(zoneId); [startPoint.x, 0.15, point.z],
return; [startPoint.x, 0.15, startPoint.z],
} ] as [number, number, number][];
}
} const zoneName = `Zone ${zones.length + 1}`;
const zoneId = THREE.MathUtils.generateUUID();
if (evt.button === 0) { const newZone = {
if (isDragging && draggedSphere) { zoneId,
setIsDragging(false); zoneName,
setDraggedSphere(null); points: points,
layer: activeLayer
const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere); };
if (sphereIndex !== -1) {
const zoneIndex = Math.floor(sphereIndex / 4); const newZones = [...zones, newZone];
if (zoneIndex !== -1 && zones[zoneIndex]) { setZones(newZones);
updateZoneToBackend(zones[zoneIndex]);
} const newzonePoints = [
} new THREE.Vector3(startPoint.x, 0.15, startPoint.z),
} new THREE.Vector3(point.x, 0.15, startPoint.z),
} new THREE.Vector3(point.x, 0.15, point.z),
}; new THREE.Vector3(startPoint.x, 0.15, point.z),
];
const onMouseMove = () => {
if (isLeftMouseDown) { const updatedZonePoints = [...zonePoints, ...newzonePoints];
drag = true; setZonePoints(updatedZonePoints);
}
raycaster.setFromCamera(pointer, camera); addZoneToBackend(newZone);
const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
setStartPoint(null);
if (intersects.length > 0 && intersects[0].object.name.includes('point')) { setEndPoint(null);
gl.domElement.style.cursor = movePoint ? "pointer" : "default"; }
} else { } else if (evt.button === 0 && !drag && !isDragging && deletePointOrLine) {
gl.domElement.style.cursor = "default"; raycaster.setFromCamera(pointer, camera);
} const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
if (isDragging && draggedSphere) {
raycaster.setFromCamera(pointer, camera); if (intersects.length > 0) {
const intersectionPoint = new THREE.Vector3(); const clickedObject = intersects[0].object;
const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (point) { const sphereIndex = zonePoints.findIndex((point: any) => point.equals(clickedObject.position));
draggedSphere.set(point.x, 0.15, point.z); if (sphereIndex !== -1) {
const zoneIndex = Math.floor(sphereIndex / 4);
const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere); const zoneId = zones[zoneIndex].zoneId;
if (sphereIndex !== -1) { handleDeleteZone(zoneId);
const zoneIndex = Math.floor(sphereIndex / 4); return;
const cornerIndex = sphereIndex % 4; }
}
const updatedZones = zones.map((zone: any, index: number) => { }
if (index === zoneIndex) {
const updatedPoints = [...zone.points]; if (evt.button === 0) {
updatedPoints[cornerIndex] = [point.x, 0.15, point.z]; if (isDragging && draggedSphere) {
updatedPoints[4] = updatedPoints[0]; setIsDragging(false);
return { ...zone, points: updatedPoints }; setDraggedSphere(null);
}
return zone; const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere);
}); if (sphereIndex !== -1) {
const zoneIndex = Math.floor(sphereIndex / 4);
setZones(updatedZones);
} if (zoneIndex !== -1 && zones[zoneIndex]) {
} updateZoneToBackend(zones[zoneIndex]);
} }
}; }
}
const onContext = (event: any) => { }
event.preventDefault(); };
setStartPoint(null);
setEndPoint(null); const onMouseMove = () => {
}; if (isLeftMouseDown) {
drag = true;
if (toolMode === 'Zone' || deletePointOrLine || movePoint) { }
canvasElement.addEventListener("mousedown", onMouseDown); raycaster.setFromCamera(pointer, camera);
canvasElement.addEventListener("mouseup", onMouseUp); const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
canvasElement.addEventListener("mousemove", onMouseMove);
canvasElement.addEventListener("contextmenu", onContext); if (intersects.length > 0 && intersects[0].object.name.includes('point')) {
} gl.domElement.style.cursor = movePoint ? "pointer" : "default";
return () => { } else {
canvasElement.removeEventListener("mousedown", onMouseDown); gl.domElement.style.cursor = "default";
canvasElement.removeEventListener("mouseup", onMouseUp); }
canvasElement.removeEventListener("mousemove", onMouseMove); if (isDragging && draggedSphere) {
canvasElement.removeEventListener("contextmenu", onContext); raycaster.setFromCamera(pointer, camera);
}; const intersectionPoint = new THREE.Vector3();
}, [gl, camera, startPoint, toggleView, scene, toolMode, zones, isDragging, deletePointOrLine, zonePoints, draggedSphere, movePoint, activeLayer]); const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (point) {
useFrame(() => { draggedSphere.set(point.x, 0.15, point.z);
if (!startPoint) return;
raycaster.setFromCamera(pointer, camera); const sphereIndex = zonePoints.findIndex((point: any) => point === draggedSphere);
const intersectionPoint = new THREE.Vector3(); if (sphereIndex !== -1) {
const point = raycaster.ray.intersectPlane(plane, intersectionPoint); const zoneIndex = Math.floor(sphereIndex / 4);
if (point) { const cornerIndex = sphereIndex % 4;
setEndPoint(point);
} const updatedZones = zones.map((zone: any, index: number) => {
}); if (index === zoneIndex) {
return ( const updatedPoints = [...zone.points];
<group ref={groupsRef} name='zoneGroup' > updatedPoints[cornerIndex] = [point.x, 0.15, point.z];
<group name="zones" visible={!toggleView}> updatedPoints[4] = updatedPoints[0];
{zones return { ...zone, points: updatedPoints };
.map((zone: any) => ( }
<group key={zone.zoneId} name={zone.zoneName}> return zone;
{zone.points.slice(0, -1).map((point: [number, number, number], index: number) => { });
const nextPoint = zone.points[index + 1];
setZones(updatedZones);
const point1 = new THREE.Vector3(point[0], point[1], point[2]); }
const point2 = new THREE.Vector3(nextPoint[0], nextPoint[1], nextPoint[2]); }
}
const planeWidth = point1.distanceTo(point2); };
const planeHeight = CONSTANTS.wallConfig.height;
const onContext = (event: any) => {
const midpoint = new THREE.Vector3((point1.x + point2.x) / 2, (CONSTANTS.wallConfig.height / 2) + ((zone.layer - 1) * CONSTANTS.wallConfig.height), (point1.z + point2.z) / 2); event.preventDefault();
setStartPoint(null);
const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x); setEndPoint(null);
};
return (
<mesh if (toolMode === 'Zone' || deletePointOrLine || movePoint) {
key={index} canvasElement.addEventListener("mousedown", onMouseDown);
position={midpoint} canvasElement.addEventListener("mouseup", onMouseUp);
rotation={[0, -angle, 0]} canvasElement.addEventListener("mousemove", onMouseMove);
> canvasElement.addEventListener("contextmenu", onContext);
<planeGeometry args={[planeWidth, planeHeight]} /> }
<primitive return () => {
object={zoneMaterial.clone()} canvasElement.removeEventListener("mousedown", onMouseDown);
attach="material" canvasElement.removeEventListener("mouseup", onMouseUp);
/> canvasElement.removeEventListener("mousemove", onMouseMove);
</mesh> canvasElement.removeEventListener("contextmenu", onContext);
); };
})} }, [gl, camera, startPoint, toggleView, scene, toolMode, zones, isDragging, deletePointOrLine, zonePoints, draggedSphere, movePoint, activeLayer]);
</group>
))} useFrame(() => {
</group> if (!startPoint) return;
<group name='zoneLines' visible={toggleView}> raycaster.setFromCamera(pointer, camera);
{zones const intersectionPoint = new THREE.Vector3();
.filter((zone: any) => zone.layer === activeLayer) const point = raycaster.ray.intersectPlane(plane, intersectionPoint);
.map((zone: any) => ( if (point) {
<Line setEndPoint(point);
key={zone.zoneId} }
points={zone.points} });
color="#007BFF" return (
lineWidth={3} <group ref={groupsRef} name='zoneGroup' >
onClick={(e) => { <group name="zones" visible={!toggleView}>
e.stopPropagation(); {zones
if (deletePointOrLine) { .map((zone: any) => (
handleDeleteZone(zone.zoneId); <group key={zone.zoneId} name={zone.zoneName}>
} {zone.points.slice(0, -1).map((point: [number, number, number], index: number) => {
}} const nextPoint = zone.points[index + 1];
/>
))} const point1 = new THREE.Vector3(point[0], point[1], point[2]);
</group> const point2 = new THREE.Vector3(nextPoint[0], nextPoint[1], nextPoint[2]);
<group name="zonePoints" visible={toggleView}>
{zones.filter((zone: any) => zone.layer === activeLayer).flatMap((zone: any) => ( const planeWidth = point1.distanceTo(point2);
zone.points.slice(0, 4).map((point: any, pointIndex: number) => ( const planeHeight = CONSTANTS.wallConfig.height;
<Sphere
key={`${zone.zoneId}-point-${pointIndex}`} const midpoint = new THREE.Vector3((point1.x + point2.x) / 2, (CONSTANTS.wallConfig.height / 2) + ((zone.layer - 1) * CONSTANTS.wallConfig.height), (point1.z + point2.z) / 2);
position={new THREE.Vector3(...point)}
args={[0.3, 16, 16]} const angle = Math.atan2(point2.z - point1.z, point2.x - point1.x);
name={`point-${zone.zoneId}-${pointIndex}`}
> return (
<meshBasicMaterial color="red" /> <mesh
</Sphere> key={index}
)) position={midpoint}
))} rotation={[0, -angle, 0]}
</group> >
<group name="tempGroup" visible={toggleView}> <planeGeometry args={[planeWidth, planeHeight]} />
{startPoint && endPoint && ( <primitive
<Line object={zoneMaterial.clone()}
points={[ attach="material"
[startPoint.x, 0.15, startPoint.z], />
[endPoint.x, 0.15, startPoint.z], </mesh>
[endPoint.x, 0.15, endPoint.z], );
[startPoint.x, 0.15, endPoint.z], })}
[startPoint.x, 0.15, startPoint.z], </group>
]} ))}
color="#C164FF" </group>
lineWidth={3} <group name='zoneLines' visible={toggleView}>
/> {zones
)} .filter((zone: any) => zone.layer === activeLayer)
</group> .map((zone: any) => (
</group> <Line
); key={zone.zoneId}
}; points={zone.points}
color="#007BFF"
lineWidth={3}
onClick={(e) => {
e.stopPropagation();
if (deletePointOrLine) {
handleDeleteZone(zone.zoneId);
}
}}
/>
))}
</group>
<group name="zonePoints" visible={toggleView}>
{zones.filter((zone: any) => zone.layer === activeLayer).flatMap((zone: any) => (
zone.points.slice(0, 4).map((point: any, pointIndex: number) => (
<Sphere
key={`${zone.zoneId}-point-${pointIndex}`}
position={new THREE.Vector3(...point)}
args={[0.3, 16, 16]}
name={`point-${zone.zoneId}-${pointIndex}`}
>
<meshBasicMaterial color="red" />
</Sphere>
))
))}
</group>
<group name="tempGroup" visible={toggleView}>
{startPoint && endPoint && (
<Line
points={[
[startPoint.x, 0.15, startPoint.z],
[endPoint.x, 0.15, startPoint.z],
[endPoint.x, 0.15, endPoint.z],
[startPoint.x, 0.15, endPoint.z],
[startPoint.x, 0.15, startPoint.z],
]}
color="#C164FF"
lineWidth={3}
/>
)}
</group>
</group>
);
};
export default ZoneGroup; export default ZoneGroup;

View File

@ -7,6 +7,7 @@ import {
VerifiedIcon, VerifiedIcon,
} from "../../components/icons/marketPlaceIcons"; } from "../../components/icons/marketPlaceIcons";
import assetImage from "../../assets/image/image.png";
const Card: React.FC = () => { const Card: React.FC = () => {
return ( return (
<div className="card-container"> <div className="card-container">
@ -14,7 +15,7 @@ const Card: React.FC = () => {
<DownloadIcon /> <DownloadIcon />
</div> </div>
<div className="image-container"> <div className="image-container">
<img src="" alt="" /> <img src={assetImage} alt="" />
</div> </div>
<div className="assets-container"> <div className="assets-container">
<div className="name-container"> <div className="name-container">
@ -32,11 +33,18 @@ const Card: React.FC = () => {
</div> </div>
</div> </div>
</div> </div>
<div className="vendor-icon"> <div className="vendor-icon">
HEXR FACTORY <VerifiedIcon /> HEXR FACTORY <VerifiedIcon />
</div> </div>
<div className="stars-container"> <div className="stars-container">
<StarsIconSmall /> <div className="stars-wrapper">
<StarsIconSmall />
<StarsIconSmall />
<StarsIconSmall />
<StarsIconSmall />
<StarsIconSmall />
</div>
<div className="units"> <div className="units">
36,500/<span>unit</span> 36,500/<span>unit</span>
</div> </div>

View File

@ -4,9 +4,13 @@ import CardsContainer from "./CardsContainer";
const MarketPlace = () => { const MarketPlace = () => {
return ( return (
<div className="marketPlace"> <div className="marketplace-wrapper">
<FilterSearch /> <div className="marketplace-container">
<CardsContainer /> <div className="marketPlace">
<FilterSearch />
<CardsContainer />
</div>
</div>
</div> </div>
); );
}; };

View File

@ -23,8 +23,8 @@ const Project: React.FC = () => {
let navigate = useNavigate(); let navigate = useNavigate();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { userName, setUserName } = useUserName(); const { setUserName } = useUserName();
const { organization, setOrganization } = useOrganization(); const { setOrganization } = useOrganization();
const { setFloorItems } = useFloorItems(); const { setFloorItems } = useFloorItems();
const { setWallItems } = useWallItems(); const { setWallItems } = useWallItems();
const { setZones } = useZones(); const { setZones } = useZones();
@ -50,24 +50,17 @@ const Project: React.FC = () => {
return ( return (
<div className="project-main"> <div className="project-main">
{!isPlaying && <ModuleToggle />} {!isPlaying && (
{!isPlaying && <SideBarLeft />} <>
{!isPlaying && <SideBarRight />} <ModuleToggle />
{activeModule === "visualization" && <RealTimeVisulization />} <SideBarLeft />
<SideBarRight />
</>
)}
{activeModule === "market" && <MarketPlace />} {activeModule === "market" && <MarketPlace />}
{/* {activeModule !== "visualization" && <Scene />} */} <RealTimeVisulization />
<Tools /> {activeModule !== "market" && <Tools />}
{/* <Scene /> */}
{/* <SimulationUI /> */} {/* <SimulationUI /> */}
<div
className="canvas-container"
style={{ height: "100vh", width: "100vw" }}
>
{activeModule !== "visualization" && activeModule !== "market" && (
<Scene />
)}
</div>
</div> </div>
); );
}; };

View File

@ -141,7 +141,7 @@ const UserAuth: React.FC = () => {
</div> </div>
{!isSignIn && ( {!isSignIn && (
<div className="policy-checkbox"> <div className="policy-checkbox">
<input type="checkbox" name="" id="" /> <input type="checkbox" name="" id="" required/>
<div className="label"> <div className="label">
I have read and agree to the terms of service I have read and agree to the terms of service
</div> </div>

View File

@ -6,7 +6,7 @@ interface ModuleStore {
} }
const useModuleStore = create<ModuleStore>((set) => ({ const useModuleStore = create<ModuleStore>((set) => ({
activeModule: "market", // Initial state activeModule: "builder", // Initial state
setActiveModule: (module) => set({ activeModule: module }), // Update state setActiveModule: (module) => set({ activeModule: module }), // Update state
})); }));

View File

@ -1,89 +1,185 @@
@use "../../abstracts/variables" as *; @use "../../abstracts/variables" as *;
@use "../../abstracts/mixins.scss" as *; @use "../../abstracts/mixins.scss" as *;
.marketplace-wrapper {
.marketPlace { height: 100vh;
width: calc((100vw) - (320px + 270px + 100px)); width: 100vw;
background-color: #FCFDFD; z-index: #{$z-index-marketplace};
background-color: var(--background-color-secondary);
position: absolute; position: absolute;
top: 100px; left: 0;
left: calc(240px + 45px); padding: 100px 50px;
padding: 14px;
display: flex;
flex-direction: column;
gap: 24px;
.filter-search-container { .marketplace-container {
padding: 20px 2px;
height: calc(100vh - 120px);
background-color: var(--background-color);
box-shadow: #{$box-shadow-medium};
border-radius: #{$border-radius-extra-large};
}
.marketPlace {
width: 100%;
height: 100%;
overflow: auto;
left: calc(120px / 2);
top: 100px;
padding: 14px;
padding-bottom: 60px;
display: flex; display: flex;
align-items: center; flex-direction: column;
gap: 12px; gap: 24px;
.search-wrapper { .filter-search-container {
min-width: 40%; width: 100%;
display: flex;
align-items: center;
gap: 12px;
width: 684px; .search-wrapper {
padding: 0; min-width: 60%;
max-width: 684px;
padding: 0;
border-radius: $border-radius-large ;
.search-container { .search-container {
border: none !important;
box-shadow: 0px 2px 10.5px 0px #0000000D;
input {
border: none !important; border: none !important;
outline: none; box-shadow: $box-shadow-medium;
border-radius: $border-radius-large ;
input {
border: none !important;
outline: none;
}
}
}
.regularDropdown-container {
max-width: 159px;
}
.button {
padding: 5px 20px;
border: 1px solid var(--accent-color);
border-radius: 14px;
}
.rating-container {
display: flex;
align-items: center;
gap: 6px;
.stars {
display: flex;
align-items: center;
} }
} }
} }
.regularDropdown-container { .cards-container-container {
max-width: 159px; padding: 0px 20px;
}
.button {
padding: 5px 20px;
border: 1px solid var(--accent-color);
border-radius: 14px;
}
.rating-container {
display: flex; display: flex;
align-items: center; flex-direction: column;
gap: 6px; gap: 6px;
.stars { .header {
display: flex; color: var(--text-color);
align-items: center; font-weight: $medium-weight;
font-size: $xlarge;
} }
}
}
.cards-container-container { .cards-wrapper-container {
.header { display: flex;
color: var(--text-color); flex-wrap: wrap;
font-weight: $medium-weight; gap: 28px;
font-size: $xlarge;
}
.cards-wrapper-container { .card-container {
.card-container { width: calc(25% - 23px);
width: 316px; border-radius: 18px;
height: 309px; padding: 12px;
border-radius: 18px; box-shadow: 0px 2px 10.5px 0px #0000000D;
padding: 12px; border: 1px solid var(--background-accent-transparent, #E0DFFF80);
box-shadow: 0px 2px 10.5px 0px #0000000D; position: relative;
border: 1px solid var(--background-accent-transparent, #E0DFFF80); display: flex;
position: relative; flex-direction: column;
.icon { justify-content: center;
position: absolute; gap: 6px;
top: 12px;
left: 12px; .icon {
width: 30px; position: absolute;
height: 30px; top: 12px;
border-radius: 10px; left: 12px;
padding: 5px; width: 30px;
background-color: var(--accent-color); height: 30px;
border-radius: 10px;
padding: 5px;
background-color: var(--accent-color);
}
.image-container {
width: 100%;
display: flex;
justify-content: center;
}
.assets-container {
display: flex;
justify-content: space-between;
.name-container {
display: flex;
flex-direction: column;
gap: 3px;
.asstes-container {
font-weight: #{$bold-weight};
font-size: $regular ;
}
.assets-date {
color: var(--accent-color);
font-size: $small;
}
}
.details {
display: flex;
align-items: center;
gap: 10px;
.content {
display: flex;
align-items: center;
gap: 6px;
}
}
}
.vendor-icon {
font-weight: #{$bold-weight};
font-size: $regular ;
}
.stars-container {
display: flex;
justify-content: space-between;
}
.buy-now-button {
width: 100%;
background-color: var(--background-color-secondary);
border-radius: $border-radius-extra-large ;
padding: 8px 0;
@include flex-center;
color: var(--accent-color);
&:hover {
cursor: pointer;
}
}
} }
} }
} }

View File

@ -14,8 +14,7 @@
width: fit-content; width: fit-content;
transition: width 0.2s; transition: width 0.2s;
background-color: var(--background-color); background-color: var(--background-color);
z-index: #{$z-index-tools}; z-index: #{$z-index-default};
.split { .split {
height: 20px; height: 20px;
width: 2px; width: 2px;

View File

@ -662,16 +662,30 @@
.collapse-header-container { .collapse-header-container {
@include flex-space-between; @include flex-space-between;
padding-right: 12px; padding-right: 12px;
margin-top: 8px;
border-top: 1px solid var(--border-color);
border-bottom: 1px solid var(--border-color);
.header {
color: var(--accent-color);
}
} }
.process-container { .process-container {
padding: 0 12px;
margin: 6px 0;
.value { .value {
@include flex-space-between;
.arrow-container { .arrow-container {
height: 16px;
width: 16px;
} }
.active { .active {
rotate: 90deg;
} }
} }
.children-drop { .children-drop {
.value { .value {
padding: 6px;
border-left: 1px solid var(--border-color);
} }
} }
} }
@ -716,12 +730,16 @@
} }
.global-properties-container, .global-properties-container,
.analysis-main-container, .analysis-main-container,
.asset-properties-container { .asset-properties-container,
.zone-properties-container {
.header { .header {
padding: 8px 12px; padding: 8px 12px;
border-top: 1px solid var(--highlight-accent-color); border-top: 1px solid var(--highlight-accent-color);
border-bottom: 1px solid var(--highlight-accent-color); border-bottom: 1px solid var(--highlight-accent-color);
color: var(--accent-color); color: var(--accent-color);
.input-value {
color: inherit;
}
} }
.input-container { .input-container {
@include flex-center; @include flex-center;
@ -759,7 +777,11 @@
} }
.custom-input-container { .custom-input-container {
.header { .header {
@include flex-space-between;
border: none; border: none;
.eyedrop-button {
@include flex-center;
}
} }
.inputs-container { .inputs-container {
@include flex-space-between; @include flex-space-between;

View File

@ -6,22 +6,20 @@
background-color: var(--background-color); background-color: var(--background-color);
border-radius: 20px; border-radius: 20px;
box-shadow: $box-shadow-medium; box-shadow: $box-shadow-medium;
width: 100%; width: calc(100% - (320px + 270px + 90px));
height: 100%; height: calc(100% - (200px + 80px));
position: absolute; position: absolute;
top: 0; top: 50%;
left: 0; left: calc(270px + 45px);
transform: scale(1); transform: translate(0, -50%);
border-radius: #{$border-radius-medium};
transition: all 0.2s;
z-index: #{$z-index-default};
.scene-container { .scene-container {
width: 100%; overflow: hidden;
height: 100%;
canvas {
width: 100vw !important;
height: 100% !important;
}
} }
// Panels // Panels
.panel { .panel {
position: absolute; position: absolute;

6
package-lock.json generated Normal file
View File

@ -0,0 +1,6 @@
{
"name": "Dwinzo_dev",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}