first commit

This commit is contained in:
2025-06-10 15:28:23 +05:30
commit e22a2dc275
699 changed files with 100382 additions and 0 deletions

View File

@@ -0,0 +1,710 @@
import * as THREE from "three";
import { create } from "zustand";
import { io } from "socket.io-client";
import * as CONSTANTS from "../../types/world/worldConstants";
export const useSocketStore = create<any>((set: any, get: any) => ({
socket: null,
initializeSocket: (email?: string, organization?: string, token?: string) => {
const existingSocket = get().socket;
if (existingSocket) {
return;
}
const socket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder_v1`,
{
reconnection: true,
auth: { token },
}
);
const visualizationSocket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization_v1`,
{
reconnection: true,
auth: { token },
}
);
const dashBoardSocket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`,
{
reconnection: true,
auth: { token },
}
);
const projectSocket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`,
{
reconnection: true,
auth: { token },
}
);
set({ socket, visualizationSocket, dashBoardSocket, projectSocket });
},
disconnectSocket: () => {
set((state: any) => {
state.socket?.disconnect();
state.visualizationSocket?.disconnect();
state.dashBoardSocket?.disconnect();
state.projectSocket?.disconnect();
return { socket: null };
});
},
}));
// export const useSocketStore = create<any>((set: any, get: any) => ({
// socket: null,
// initializeSocket: (
// email: string,
// organization: string,
// userId?: string,
// token?: string
// ) => {
// const existingSocket = get().socket;
// if (existingSocket) {
// return;
// }
// const socket = io(
// `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder`,
// {
// reconnection: true,
// auth: { email, organization },
// }
// );
// const visualizationSocket = io(
// `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization`,
// {
// reconnection: true,
// auth: { email, organization },
// }
// );
// const dashBoardSocket = io(
// `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`,
// {
// reconnection: true,
// auth: { token },
// }
// );
// // const dashBoardSocket = io(
// // `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`,
// // {
// // reconnection: true,
// // auth: { token },
// // }
// // );
// set({ socket, visualizationSocket, dashBoardSocket });
// },
// disconnectSocket: () => {
// set((state: any) => {
// state.socket?.disconnect();
// state.visualizationSocket?.disconnect();
// state.dashBoardSocket?.disconnect();
// return { socket: null };
// });
// },
// }));
export const useLoadingProgress = create<{
loadingProgress: number;
setLoadingProgress: (x: number) => void;
}>((set) => ({
loadingProgress: 1,
setLoadingProgress: (x: number) => set({ loadingProgress: x }),
}));
export const useOrganization = create<any>((set: any) => ({
organization: "",
setOrganization: (x: any) => set(() => ({ organization: x })),
}));
export const useToggleView = create<any>((set: any) => ({
toggleView: false,
setToggleView: (x: any) => set(() => ({ toggleView: x })),
}));
export const useUpdateScene = create<any>((set: any) => ({
updateScene: false,
setUpdateScene: (x: any) => set(() => ({ updateScene: x })),
}));
export const useWalls = create<any>((set: any) => ({
walls: [],
setWalls: (x: any) => set(() => ({ walls: x })),
}));
export const useRoomsState = create<any>((set: any) => ({
roomsState: [],
setRoomsState: (x: any) => set(() => ({ roomsState: x })),
}));
export const useZones = create<any>((set: any) => ({
zones: [],
setZones: (callback: any) =>
set((state: any) => ({
zones: typeof callback === "function" ? callback(state.zones) : callback,
})),
}));
interface ZonePointsState {
zonePoints: THREE.Vector3[];
setZonePoints: (points: THREE.Vector3[]) => void;
}
export const useZonePoints = create<ZonePointsState>((set) => ({
zonePoints: [],
setZonePoints: (points) => set({ zonePoints: points }),
}));
export const useSelectedItem = create<any>((set: any) => ({
selectedItem: {
name: "",
id: "",
type: undefined,
category: "",
subCatergory: "",
},
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
}));
export const useNavMesh = create<any>((set: any) => ({
navMesh: null,
setNavMesh: (x: any) => set({ navMesh: x }),
}));
export const useSelectedAssets = create<any>((set: any) => ({
selectedAssets: [],
setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })),
}));
export const useLayers = create<any>((set: any) => ({
Layers: 1,
setLayers: (x: any) => set(() => ({ Layers: x })),
}));
export const useCamPosition = create<any>((set: any) => ({
camPosition: { x: undefined, y: undefined, z: undefined },
setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }),
}));
export const useMenuVisible = create<any>((set: any) => ({
menuVisible: false,
setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
}));
export const useDeleteTool = create<any>((set: any) => ({
deleteTool: false,
setDeleteTool: (x: any) => set(() => ({ deleteTool: x })),
}));
export const useToolMode = create<any>((set: any) => ({
toolMode: null,
setToolMode: (x: any) => set(() => ({ toolMode: x })),
}));
export const useNewLines = create<any>((set: any) => ({
newLines: [],
setNewLines: (x: any) => set(() => ({ newLines: x })),
}));
export const useDeletedLines = create<any>((set: any) => ({
deletedLines: [],
setDeletedLines: (x: any) => set(() => ({ deletedLines: x })),
}));
export const useMovePoint = create<any>((set: any) => ({
movePoint: false,
setMovePoint: (x: any) => set(() => ({ movePoint: x })),
}));
export const useDeletePointOrLine = create<any>((set: any) => ({
deletePointOrLine: false,
setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })),
}));
export const useWallItems = create<any>((set: any) => ({
wallItems: [],
setWallItems: (callback: any) =>
set((state: any) => ({
wallItems:
typeof callback === "function" ? callback(state.wallItems) : callback,
})),
}));
export const useSelectedWallItem = create<any>((set: any) => ({
selectedWallItem: null,
setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })),
}));
export const useSelectedFloorItem = create<any>((set: any) => ({
selectedFloorItem: null,
setSelectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })),
}));
export const useDeletableFloorItem = create<any>((set: any) => ({
deletableFloorItem: null,
setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })),
}));
export const useSetScale = create<any>((set: any) => ({
scale: null,
setScale: (x: any) => set(() => ({ scale: x })),
}));
export const useRoofVisibility = create<any>((set: any) => ({
roofVisibility: false,
setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })),
}));
export const useWallVisibility = create<any>((set: any) => ({
wallVisibility: false,
setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })),
}));
export const useShadows = create<any>((set: any) => ({
shadows: false,
setShadows: (x: any) => set(() => ({ shadows: x })),
}));
export const useSunPosition = create<any>((set: any) => ({
sunPosition: { x: undefined, y: undefined, z: undefined },
setSunPosition: (newSuntPosition: any) =>
set({ sunPosition: newSuntPosition }),
}));
export const useRemoveLayer = create<any>((set: any) => ({
removeLayer: false,
setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })),
}));
export const useRemovedLayer = create<any>((set: any) => ({
removedLayer: null,
setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })),
}));
export const useProjectName = create<any>((set: any) => ({
projectName: "Creating Your Project",
setProjectName: (x: any) => set({ projectName: x }),
}));
export const useActiveLayer = create<any>((set: any) => ({
activeLayer: 1,
setActiveLayer: (x: any) => set({ activeLayer: x }),
}));
interface RefTextUpdateState {
refTextupdate: number;
setRefTextUpdate: (
callback: (currentValue: number) => number | number
) => void;
}
export const useRefTextUpdate = create<RefTextUpdateState>((set) => ({
refTextupdate: -1000,
setRefTextUpdate: (callback) =>
set((state) => ({
refTextupdate:
typeof callback === "function"
? callback(state.refTextupdate)
: callback,
})),
}));
export const useResetCamera = create<any>((set: any) => ({
resetCamera: false,
setResetCamera: (x: any) => set({ resetCamera: x }),
}));
export const useAddAction = create<any>((set: any) => ({
addAction: null,
setAddAction: (x: any) => set({ addAction: x }),
}));
export const useActiveTool = create<any>((set: any) => ({
activeTool: "cursor",
setActiveTool: (x: any) => set({ activeTool: x }),
}));
export const useActiveSubTool = create<any>((set: any) => ({
activeSubTool: "cursor",
setActiveSubTool: (x: any) => set({ activeSubTool: x }),
}));
export const use2DUndoRedo = create<any>((set: any) => ({
is2DUndoRedo: null,
set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }),
}));
export const useElevation = create<any>((set: any) => ({
elevation: 45,
setElevation: (x: any) => set({ elevation: x }),
}));
export const useAzimuth = create<any>((set: any) => ({
azimuth: -160,
setAzimuth: (x: any) => set({ azimuth: x }),
}));
export const useRenderDistance = create<any>((set: any) => ({
renderDistance: 40,
setRenderDistance: (x: any) => set({ renderDistance: x }),
}));
export const useCamMode = create<any>((set: any) => ({
camMode: "ThirdPerson",
setCamMode: (x: any) => set({ camMode: x }),
}));
export const useUserName = create<any>((set: any) => ({
userName: "",
setUserName: (x: any) => set({ userName: x }),
}));
export const useRenameModeStore = create<any>((set: any) => ({
isRenameMode: false,
setIsRenameMode: (state: boolean) => set({ isRenameMode: state }),
}));
export const useObjectPosition = create<any>((set: any) => ({
objectPosition: { x: undefined, y: undefined, z: undefined },
setObjectPosition: (newObjectPosition: any) =>
set({ objectPosition: newObjectPosition }),
}));
export const useObjectRotation = create<any>((set: any) => ({
objectRotation: { x: undefined, y: undefined, z: undefined },
setObjectRotation: (newObjectRotation: any) =>
set({ objectRotation: newObjectRotation }),
}));
export const useDrieTemp = create<any>((set: any) => ({
drieTemp: undefined,
setDrieTemp: (x: any) => set({ drieTemp: x }),
}));
export const useActiveUsers = create<any>((set: any) => ({
activeUsers: [],
setActiveUsers: (callback: (prev: any[]) => any[] | any[]) =>
set((state: { activeUsers: any[] }) => ({
activeUsers:
typeof callback === "function" ? callback(state.activeUsers) : callback,
})),
}));
export const useDrieUIValue = create<any>((set: any) => ({
drieUIValue: { touch: null, temperature: null, humidity: null },
setDrieUIValue: (x: any) =>
set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })),
setTouch: (value: any) =>
set((state: any) => ({
drieUIValue: { ...state.drieUIValue, touch: value },
})),
setTemperature: (value: any) =>
set((state: any) => ({
drieUIValue: { ...state.drieUIValue, temperature: value },
})),
setHumidity: (value: any) =>
set((state: any) => ({
drieUIValue: { ...state.drieUIValue, humidity: value },
})),
}));
export const useStartSimulation = create<any>((set: any) => ({
startSimulation: false,
setStartSimulation: (x: any) => set({ startSimulation: x }),
}));
export const useEyeDropMode = create<any>((set: any) => ({
eyeDropMode: false,
setEyeDropMode: (x: any) => set({ eyeDropMode: x }),
}));
export const useEditingPoint = create<any>((set: any) => ({
editingPoint: false,
setEditingPoint: (x: any) => set({ editingPoint: x }),
}));
export const usezoneTarget = create<any>((set: any) => ({
zoneTarget: [],
setZoneTarget: (x: any) => set({ zoneTarget: x }),
}));
export const usezonePosition = create<any>((set: any) => ({
zonePosition: [],
setZonePosition: (x: any) => set({ zonePosition: x }),
}));
interface EditPositionState {
Edit: boolean;
setEdit: (value: boolean) => void;
}
export const useEditPosition = create<EditPositionState>((set) => ({
Edit: false,
setEdit: (value) => set({ Edit: value }),
}));
export const useAsset3dWidget = create<any>((set: any) => ({
widgetSelect: "",
setWidgetSelect: (x: any) => set({ widgetSelect: x }),
}));
export const useWidgetSubOption = create<any>((set: any) => ({
widgetSubOption: "2D",
setWidgetSubOption: (x: any) => set({ widgetSubOption: x }),
}));
export const useLimitDistance = create<any>((set: any) => ({
limitDistance: true,
setLimitDistance: (x: any) => set({ limitDistance: x }),
}));
export const useTileDistance = create<any>((set: any) => ({
gridValue: {
size: CONSTANTS.gridConfig.size,
divisions: CONSTANTS.gridConfig.divisions,
},
planeValue: {
height: CONSTANTS.planeConfig.height,
width: CONSTANTS.planeConfig.width,
},
setGridValue: (value: any) =>
set((state: any) => ({
gridValue: { ...state.gridValue, ...value },
})),
setPlaneValue: (value: any) =>
set((state: any) => ({
planeValue: { ...state.planeValue, ...value },
})),
}));
export const usePlayAgv = create<any>((set, get) => ({
PlayAgv: [],
setPlayAgv: (updateFn: (prev: any[]) => any[]) =>
set({ PlayAgv: updateFn(get().PlayAgv) }),
}));
// Define the Asset type
type Asset = {
id: string;
name: string;
position?: [number, number, number]; // Optional: 3D position
rotation?: { x: number; y: number; z: number }; // Optional: Euler rotation
};
// Zustand store type
type ZoneAssetState = {
zoneAssetId: Asset | null;
setZoneAssetId: (asset: Asset | null) => void;
};
// Zustand store
export const useZoneAssetId = create<ZoneAssetState>((set) => ({
zoneAssetId: null,
setZoneAssetId: (asset) => set({ zoneAssetId: asset }),
}));
// version visible hidden
interface VersionHistoryState {
viewVersionHistory: boolean;
setVersionHistory: (value: boolean) => void;
}
const useVersionHistoryStore = create<VersionHistoryState>((set) => ({
viewVersionHistory: false,
setVersionHistory: (value) => set({ viewVersionHistory: value }),
}));
export default useVersionHistoryStore;
interface ShortcutStore {
showShortcuts: boolean;
setShowShortcuts: (value: boolean) => void;
toggleShortcuts: () => void;
}
export const useShortcutStore = create<ShortcutStore>((set) => ({
showShortcuts: false,
setShowShortcuts: (value) => set({ showShortcuts: value }),
toggleShortcuts: () =>
set((state) => ({ showShortcuts: !state.showShortcuts })),
}));
export const useMachineCount = create<any>((set: any) => ({
machineCount: 0,
setMachineCount: (x: any) => set({ machineCount: x }),
}));
export const useMachineUptime = create<any>((set: any) => ({
machineActiveTime: 0,
setMachineActiveTime: (x: any) => set({ machineActiveTime: x }),
}));
export const useMaterialCycle = create<any>((set: any) => ({
materialCycleTime: 0,
setMaterialCycleTime: (x: any) => set({ materialCycleTime: x }),
}));
export const useThroughPutData = create<any>((set: any) => ({
throughputData: 0,
setThroughputData: (x: any) => set({ throughputData: x }),
}));
export const useProductionCapacityData = create<any>((set: any) => ({
productionCapacityData: 0,
setProductionCapacityData: (x: any) => set({ productionCapacityData: x }),
}));
export const useProcessBar = create<any>((set: any) => ({
processBar: [],
setProcessBar: (x: any) => set({ processBar: x }),
}));
export const useDfxUpload = create<any>((set: any) => ({
dfxuploaded: [],
dfxWallGenerate: [],
objValue: { x: 0, y: 0, z: 0 },
setDfxUploaded: (x: any) => set({ dfxuploaded: x }),
setDfxGenerate: (x: any) => set({ dfxWallGenerate: x }),
setObjValue: (x: any) => set({ objValue: x }),
}));
type InputValuesStore = {
inputValues: Record<string, string>;
setInputValues: (values: Record<string, string>) => void;
updateInputValue: (label: string, value: string) => void; // <- New
};
export const useInputValues = create<InputValuesStore>((set) => ({
inputValues: {},
setInputValues: (values) => set({ inputValues: values }),
updateInputValue: (label, value) =>
set((state) => ({
inputValues: {
...state.inputValues,
[label]: value,
},
})),
}));
export interface ROISummaryData {
productName: string;
roiPercentage: number;
paybackPeriod: number;
totalCost: number;
revenueGenerated: number;
netProfit: number;
netLoss: number;
}
interface ROISummaryStore {
roiSummary: ROISummaryData;
setRoiSummaryData: (values: ROISummaryData) => void;
}
export const useROISummaryData = create<ROISummaryStore>((set) => ({
roiSummary: {
productName: "",
roiPercentage: 0,
paybackPeriod: 0,
totalCost: 0,
revenueGenerated: 0,
netProfit: 0,
netLoss: 0,
},
setRoiSummaryData: (values) => set({ roiSummary: values }),
}));
interface CompareStore {
comparePopUp: boolean;
setComparePopUp: (value: boolean) => void;
toggleComparePopUp: () => void;
}
export const useCompareStore = create<CompareStore>((set) => ({
comparePopUp: true,
setComparePopUp: (value) => set({ comparePopUp: value }),
toggleComparePopUp: () =>
set((state) => ({ comparePopUp: !state.comparePopUp })),
}));
// Save state store
interface SaveVersionStore {
isVersionSaved: boolean;
setIsVersionSaved: (value: boolean) => void;
}
export const useSaveVersion = create<SaveVersionStore>((set) => ({
isVersionSaved: false,
setIsVersionSaved: (value: boolean) => set({ isVersionSaved: value }),
}));
// Version object type
export interface Version {
id: string;
versionLabel: string;
versionName?: string;
timestamp: string;
savedBy: string;
description?: string;
}
// Version list store
interface VersionListStore {
versions: Version[];
addVersion: (version: Version) => void;
clearVersions: () => void;
setVersions: (newVersions: Version[]) => void;
updateVersion: (id: string, data: Partial<Version>) => void; // ✅ Added
}
export const useVersionStore = create<VersionListStore>((set) => ({
versions: [],
addVersion: (newVersion) =>
set((state) => ({
versions: [newVersion, ...state.versions],
})),
clearVersions: () => set({ versions: [] }),
setVersions: (newVersions) => set({ versions: newVersions }),
updateVersion: (id, data) =>
set((state) => ({
versions: state.versions.map((version) =>
version.id === id ? { ...version, ...data } : version
),
})),
}));
interface ViewSceneState {
viewSceneLabels: boolean;
setViewSceneLabels: (value: boolean | ((prev: boolean) => boolean)) => void;
}
export const useViewSceneStore = create<ViewSceneState>((set) => ({
viewSceneLabels: getInitialViewSceneLabels(),
setViewSceneLabels: (value) => {
set((state) => {
const newValue =
typeof value === 'function' ? value(state.viewSceneLabels) : value;
// Store in localStorage manually
localStorage.setItem('viewSceneLabels', JSON.stringify(newValue));
return { viewSceneLabels: newValue };
});
},
}));
function getInitialViewSceneLabels(): boolean {
if (typeof window === 'undefined') return false; // SSR safety
const saved = localStorage.getItem('viewSceneLabels');
return saved ? JSON.parse(saved) : false;
}

View File

@@ -0,0 +1,247 @@
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
interface AisleStore {
aisles: Aisles;
setAisles: (aisles: Aisles) => void;
addAisle: (aisle: Aisle) => void;
updateAisle: (uuid: string, updated: Partial<Aisle>) => void;
removeAisle: (uuid: string) => void;
removePoint: (uuid: string) => Aisles;
setPosition: (
pointUuid: string,
position: [number, number, number]
) => Aisle | undefined;
setLayer: (pointUuid: string, layer: number) => void;
setColor: (aisleUuid: string, color: AisleColors) => void;
// Type-specific setters
setSolidAisleWidth: (aisleUuid: string, width: number) => void;
setDashedAisleProperties: (
aisleUuid: string,
props: { aisleWidth?: number; dashLength?: number; gapLength?: number }
) => void;
setDottedAisleProperties: (
aisleUuid: string,
props: { dotRadius?: number; gapLength?: number }
) => void;
setArrowAisleWidth: (aisleUuid: string, width: number) => void;
setArrowsAisleProperties: (
aisleUuid: string,
props: { aisleWidth?: number; aisleLength?: number; gapLength?: number }
) => void;
setArcAisleWidth: (
aisleUuid: string,
props: { aisleWidth?: number; isFlipped: boolean }
) => void;
setCircleAisleWidth: (aisleUuid: string, width: number) => void;
setJunctionAisleProperties: (
aisleUuid: string,
props: { aisleWidth?: number; isFlipped: boolean }
) => void;
getAisleById: (uuid: string) => Aisle | undefined;
getAislesByPointId: (uuid: string) => Aisle[] | [];
getAislePointById: (uuid: string) => Point | undefined;
getConnectedPoints: (uuid: string) => Point[] | [];
getAisleType: <T extends AisleType>(uuid: string) => T | undefined;
}
export const useAisleStore = create<AisleStore>()(
immer((set, get) => ({
aisles: [],
setAisles: (aisles) =>
set((state) => {
state.aisles = aisles;
}),
addAisle: (aisle) =>
set((state) => {
state.aisles.push(aisle);
}),
updateAisle: (uuid, updated) =>
set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === uuid);
if (aisle) {
Object.assign(aisle, updated);
}
}),
removeAisle: (uuid) =>
set((state) => {
state.aisles = state.aisles.filter((a) => a.aisleUuid !== uuid);
}),
removePoint: (uuid) => {
const removedAisles: Aisle[] = [];
set((state) => {
state.aisles = state.aisles.filter((aisle) => {
const hasPoint = aisle.points.some(
(point) => point.pointUuid === uuid
);
if (hasPoint) {
removedAisles.push(JSON.parse(JSON.stringify(aisle)));
return false;
}
return true;
});
});
return removedAisles;
},
setPosition: (pointUuid, position) => {
let updatedAisle: Aisle | undefined;
set((state) => {
for (const aisle of state.aisles) {
const point = aisle.points.find((p) => p.pointUuid === pointUuid);
if (point) {
point.position = position;
updatedAisle = JSON.parse(JSON.stringify(aisle));
}
}
});
return updatedAisle;
},
setLayer: (pointUuid, layer) =>
set((state) => {
for (const aisle of state.aisles) {
const point = aisle.points.find((p) => p.pointUuid === pointUuid);
if (point) {
point.layer = layer;
}
}
}),
setColor: (aisleUuid, color) =>
set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle) {
aisle.type.aisleColor = color;
}
}),
// Type-specific property setters
setSolidAisleWidth: (aisleUuid, width) =>
set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "solid-aisle") {
aisle.type.aisleWidth = width;
}
}),
setDashedAisleProperties: (aisleUuid, props) =>
set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "dashed-aisle") {
if (props.aisleWidth !== undefined)
aisle.type.aisleWidth = props.aisleWidth;
if (props.dashLength !== undefined)
aisle.type.dashLength = props.dashLength;
if (props.gapLength !== undefined)
aisle.type.gapLength = props.gapLength;
}
}),
setDottedAisleProperties: (aisleUuid, props) =>
set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "dotted-aisle") {
if (props.dotRadius !== undefined)
aisle.type.dotRadius = props.dotRadius;
if (props.gapLength !== undefined)
aisle.type.gapLength = props.gapLength;
}
}),
setArrowAisleWidth: (aisleUuid, width) =>
set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "arrow-aisle") {
aisle.type.aisleWidth = width;
}
}),
setArrowsAisleProperties: (aisleUuid, props) =>
set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "arrows-aisle") {
if (props.aisleWidth !== undefined)
aisle.type.aisleWidth = props.aisleWidth;
if (props.aisleLength !== undefined)
aisle.type.aisleLength = props.aisleLength;
if (props.gapLength !== undefined)
aisle.type.gapLength = props.gapLength;
}
}),
setArcAisleWidth: (aisleUuid, props) =>
set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "arc-aisle") {
if (props.aisleWidth !== undefined)
aisle.type.aisleWidth = props.aisleWidth;
if (props.isFlipped !== undefined)
aisle.type.isFlipped = props.isFlipped;
}
}),
setCircleAisleWidth: (aisleUuid, width) =>
set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "circle-aisle") {
aisle.type.aisleWidth = width;
}
}),
setJunctionAisleProperties: (aisleUuid, props) =>
set((state) => {
const aisle = state.aisles.find((a) => a.aisleUuid === aisleUuid);
if (aisle && aisle.type.aisleType === "junction-aisle") {
if (props.aisleWidth !== undefined)
aisle.type.aisleWidth = props.aisleWidth;
if (props.isFlipped !== undefined)
aisle.type.isFlipped = props.isFlipped;
}
}),
getAisleById: (uuid) => {
return get().aisles.find((a) => a.aisleUuid === uuid);
},
getAislesByPointId: (uuid) => {
return get().aisles.filter((a) => {
return a.points.some((p) => p.pointUuid === uuid);
})
},
getAislePointById: (uuid) => {
for (const aisle of get().aisles) {
const point = aisle.points.find((p) => p.pointUuid === uuid);
if (point) {
return point;
}
}
return undefined;
},
getConnectedPoints: (uuid) => {
const connected: Point[] = [];
for (const aisle of get().aisles) {
for (const point of aisle.points) {
if (point.pointUuid === uuid) {
connected.push(...aisle.points.filter((p) => p.pointUuid !== uuid));
}
}
}
return connected;
},
getAisleType: <T extends AisleType>(uuid: string) => {
const aisle = get().aisles.find((a) => a.aisleUuid === uuid);
return aisle?.type as T | undefined;
},
}))
);

View File

@@ -0,0 +1,231 @@
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
interface AssetsStore {
assets: Assets;
// Asset CRUD operations
addAsset: (asset: Asset) => void;
removeAsset: (modelUuid: string) => void;
updateAsset: (modelUuid: string, updates: Partial<Asset>) => void;
setAssets: (assets: Assets) => void;
// Asset properties
setName: (modelUuid: string, newName: string) => void;
setPosition: (modelUuid: string, position: [number, number, number]) => void;
setRotation: (modelUuid: string, rotation: [number, number, number]) => void;
setLock: (modelUuid: string, isLocked: boolean) => void;
setCollision: (modelUuid: string, isCollidable: boolean) => void;
setVisibility: (modelUuid: string, isVisible: boolean) => void;
setOpacity: (modelUuid: string, opacity: number) => void;
// Animation controls
setAnimation: (modelUuid: string, animation: string) => void;
setCurrentAnimation: (modelUuid: string, current: string, isPlaying: boolean) => void;
addAnimation: (modelUuid: string, animation: string) => void;
removeAnimation: (modelUuid: string, animation: string) => void;
// Event data operations
addEventData: (modelUuid: string, eventData: Asset['eventData']) => void;
updateEventData: (modelUuid: string, updates: Partial<Asset['eventData']>) => void;
removeEventData: (modelUuid: string) => void;
// Helper functions
getAssetById: (modelUuid: string) => Asset | undefined;
getAssetByPointUuid: (pointUuid: string) => Asset | undefined;
hasAsset: (modelUuid: string) => boolean;
}
export const useAssetsStore = create<AssetsStore>()(
immer((set, get) => ({
assets: [],
// Asset CRUD operations
addAsset: (asset) => {
set((state) => {
if (!state.assets.some(a => a.modelUuid === asset.modelUuid)) {
state.assets.push(asset);
}
});
},
removeAsset: (modelUuid) => {
set((state) => {
state.assets = state.assets.filter(a => a.modelUuid !== modelUuid);
});
},
updateAsset: (modelUuid, updates) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
Object.assign(asset, updates);
}
});
},
setAssets: (assets) => {
set((state) => {
state.assets = assets;
});
},
// Asset properties
setName: (modelUuid, newName) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.modelName = newName;
}
});
},
setPosition: (modelUuid, position) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.position = position;
}
});
},
setRotation: (modelUuid, rotation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.rotation = rotation;
}
});
},
setLock: (modelUuid, isLocked) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.isLocked = isLocked;
}
});
},
setCollision: (modelUuid, isCollidable) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.isCollidable = isCollidable;
}
});
},
setVisibility: (modelUuid, isVisible) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.isVisible = isVisible;
}
});
},
setOpacity: (modelUuid, opacity) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.opacity = opacity;
}
});
},
// Animation controls
setAnimation: (modelUuid, animation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
if (!asset.animationState) {
asset.animationState = { current: animation, playing: false };
} else {
asset.animationState.current = animation;
}
}
});
},
setCurrentAnimation: (modelUuid, current, isPlaying) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset?.animationState) {
asset.animationState.current = current;
asset.animationState.playing = isPlaying;
}
});
},
addAnimation: (modelUuid, animation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
if (!asset.animations) {
asset.animations = [animation];
} else if (!asset.animations.includes(animation)) {
asset.animations.push(animation);
}
}
});
},
removeAnimation: (modelUuid, animation) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset?.animations) {
asset.animations = asset.animations.filter(a => a !== animation);
if (asset.animationState?.current === animation) {
asset.animationState.playing = false;
asset.animationState.current = '';
}
}
});
},
// Event data operations
addEventData: (modelUuid, eventData) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
asset.eventData = eventData;
}
});
},
updateEventData: (modelUuid, updates) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset?.eventData) {
asset.eventData = { ...asset.eventData, ...updates };
}
});
},
removeEventData: (modelUuid) => {
set((state) => {
const asset = state.assets.find(a => a.modelUuid === modelUuid);
if (asset) {
delete asset.eventData;
}
});
},
// Helper functions
getAssetById: (modelUuid) => {
return get().assets.find(a => a.modelUuid === modelUuid);
},
getAssetByPointUuid: (pointUuid) => {
return get().assets.find(asset =>
asset.eventData?.point?.uuid === pointUuid ||
asset.eventData?.points?.some(p => p.uuid === pointUuid)
);
},
hasAsset: (modelUuid) => {
return get().assets.some(a => a.modelUuid === modelUuid);
}
}))
);

View File

@@ -0,0 +1,211 @@
import { Object3D } from 'three';
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
interface BuilderState {
// Common properties
hoveredPoint: Point | null;
snappedPoint: Point | null;
snappedPosition: [number, number, number] | null;
// Wall
wallThickness: number;
wallHeight: number;
setWallThickness: (thickness: number) => void;
setWallHeight: (height: number) => void;
// Aisle
selectedAisle: Object3D | null;
aisleType: AisleTypes;
aisleWidth: number;
aisleColor: AisleColors;
// Dashed aisle properties
dashLength: number;
gapLength: number;
// Dotted aisle properties
dotRadius: number;
// Arrows aisle properties
aisleLength: number;
// Junction aisle properties
isFlipped: boolean;
// Setters for common properties
setHoveredPoint: (point: Point | null) => void;
setSnappedPoint: (point: Point | null) => void;
setSnappedPosition: (position: [number, number, number] | null) => void;
setSelectedAisle: (aisle: Object3D | null) => void;
setAisleType: (type: AisleTypes) => void;
setAisleWidth: (width: number) => void;
setAisleColor: (color: AisleColors) => void;
// Setters for dashed aisle
setDashLength: (length: number) => void;
setGapLength: (length: number) => void;
// Setters for dotted aisle
setDotRadius: (radius: number) => void;
// Setters for arrows aisle
setAisleLength: (length: number) => void;
// Setters for junction aisle
setIsFlipped: (isFlipped: boolean) => void;
// Batch setters
setDashedAisleProperties: (width: number, dashLength: number, gapLength: number) => void;
setDottedAisleProperties: (width: number, dotRadius: number, gapLength: number) => void;
setArrowsAisleProperties: (width: number, aisleLength: number, gapLength: number) => void;
setAisleProperties: (type: AisleTypes, width: number, color: AisleColors) => void;
}
export const useBuilderStore = create<BuilderState>()(
immer((set) => ({
// Default values
hoveredPoint: null,
snappedPoint: null,
snappedPosition: null,
// Wall
wallThickness: 0.1,
wallHeight: 7,
setWallThickness: (thickness: number) => {
set((state) => {
state.wallThickness = thickness;
})
},
setWallHeight: (height: number) => {
set((state) => {
state.wallHeight = height;
})
},
// Aisle
selectedAisle: null,
aisleType: 'solid-aisle',
aisleWidth: 0.1,
aisleColor: 'yellow',
dashLength: 0.5,
gapLength: 0.3,
dotRadius: 0.1,
aisleLength: 0.6,
isFlipped: false,
// Individual setters
setHoveredPoint: (point: Point | null) => {
set((state) => {
state.hoveredPoint = point;
});
},
setSnappedPoint: (point: Point | null) => {
set((state) => {
state.snappedPoint = point;
});
},
setSnappedPosition: (position: [number, number, number] | null) => {
set((state) => {
state.snappedPosition = position;
});
},
setSelectedAisle: (aisle: Object3D | null) => {
set((state) => {
state.selectedAisle = aisle;
});
},
setAisleType: (type) => {
set((state) => {
state.aisleType = type;
});
},
setAisleWidth: (width) => {
set((state) => {
state.aisleWidth = width;
});
},
setAisleColor: (color) => {
set((state) => {
state.aisleColor = color;
});
},
setDashLength: (length) => {
set((state) => {
state.dashLength = length;
});
},
setGapLength: (length) => {
set((state) => {
state.gapLength = length;
});
},
setDotRadius: (radius) => {
set((state) => {
state.dotRadius = radius;
});
},
setAisleLength: (length) => {
set((state) => {
state.aisleLength = length;
});
},
setIsFlipped: (isFlipped) => {
set((state) => {
state.isFlipped = isFlipped;
});
},
// Batch setters
setDashedAisleProperties: (width, dashLength, gapLength) => {
set((state) => {
state.aisleType = 'dashed-aisle';
state.aisleWidth = width;
state.dashLength = dashLength;
state.gapLength = gapLength;
});
},
setDottedAisleProperties: (width, dotRadius, gapLength) => {
set((state) => {
state.aisleType = 'dotted-aisle';
state.aisleWidth = width;
state.dotRadius = dotRadius;
state.gapLength = gapLength;
});
},
setArrowsAisleProperties: (width, aisleLength, gapLength) => {
set((state) => {
state.aisleType = 'arrows-aisle';
state.aisleWidth = width;
state.aisleLength = aisleLength;
state.gapLength = gapLength;
});
},
setAisleProperties: (type, width, color) => {
set((state) => {
state.aisleType = type;
state.aisleWidth = width;
state.aisleColor = color;
});
}
}))
);

View File

@@ -0,0 +1,158 @@
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
interface WallStore {
walls: Wall[];
setWalls: (walls: Wall[]) => void;
addWall: (wall: Wall) => void;
updateWall: (uuid: string, updated: Partial<Wall>) => void;
removeWall: (uuid: string) => void;
addDecal: (wallUuid: string, decal: Decal) => void;
updateDecal: (decalUuid: string, decal: Decal) => void;
removeDecal: (decalUuid: string) => void;
updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void;
updateDecalRotation: (decalUuid: string, rotation: number) => void;
updateDecalScale: (decalUuid: string, scale: number) => void;
removePoint: (pointUuid: string) => Wall[];
setPosition: (pointUuid: string, position: [number, number, number]) => void;
setLayer: (pointUuid: string, layer: number) => void;
getWallById: (uuid: string) => Wall | undefined;
getWallPointById: (uuid: string) => Point | undefined;
getConnectedPoints: (uuid: string) => Point[];
}
export const useWallStore = create<WallStore>()(
immer((set, get) => ({
walls: [],
setWalls: (walls) => set((state) => {
state.walls = walls;
}),
addWall: (wall) => set((state) => {
state.walls.push(wall);
}),
updateWall: (uuid, updated) => set((state) => {
const wall = state.walls.find(w => w.wallUuid === uuid);
if (wall) {
Object.assign(wall, updated);
}
}),
removeWall: (uuid) => set((state) => {
state.walls = state.walls.filter(w => w.wallUuid !== uuid);
}),
addDecal: (wallUuid, decal) => set((state) => {
const wallToUpdate = state.walls.find(w => w.wallUuid === wallUuid);
if (wallToUpdate) {
wallToUpdate.decals.push(decal);
}
}),
updateDecal: (decalUuid, decal) => set((state) => {
for (const wall of state.walls) {
const decalToUpdate = wall.decals.find(d => d.decalUuid === decalUuid);
if (decalToUpdate) {
Object.assign(decalToUpdate, decal);
}
}
}),
removeDecal: (decalUuid) => set((state) => {
for (const wall of state.walls) {
wall.decals = wall.decals.filter(d => d.decalUuid !== decalUuid);
}
}),
updateDecalPosition: (decalUuid, position) => set((state) => {
for (const wall of state.walls) {
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
if (decal) {
decal.decalPosition = position;
break;
}
}
}),
updateDecalRotation: (decalUuid, rotation) => set((state) => {
for (const wall of state.walls) {
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
if (decal) {
decal.decalRotation = rotation;
break;
}
}
}),
updateDecalScale: (decalUuid, scale) => set((state) => {
for (const wall of state.walls) {
const decal = wall.decals.find(d => d.decalUuid === decalUuid);
if (decal) {
decal.decalScale = scale;
break;
}
}
}),
removePoint: (pointUuid) => {
const removedWalls: Wall[] = [];
set((state) => {
state.walls = state.walls.filter((wall) => {
const hasPoint = wall.points.some(p => p.pointUuid === pointUuid);
if (hasPoint) {
removedWalls.push(JSON.parse(JSON.stringify(wall)));
return false;
}
return true;
});
});
return removedWalls;
},
setPosition: (pointUuid, position) => set((state) => {
for (const wall of state.walls) {
const point = wall.points.find(p => p.pointUuid === pointUuid);
if (point) {
point.position = position;
}
}
}),
setLayer: (pointUuid, layer) => set((state) => {
for (const wall of state.walls) {
const point = wall.points.find(p => p.pointUuid === pointUuid);
if (point) {
point.layer = layer;
}
}
}),
getWallById: (uuid) => {
return get().walls.find(w => w.wallUuid === uuid);
},
getWallPointById: (uuid) => {
for (const wall of get().walls) {
const point = wall.points.find(p => p.pointUuid === uuid);
if (point) return point;
}
return undefined;
},
getConnectedPoints: (uuid) => {
const connected: Point[] = [];
for (const wall of get().walls) {
for (const point of wall.points) {
if (point.pointUuid === uuid) {
connected.push(...wall.points.filter(p => p.pointUuid !== uuid));
}
}
}
return connected;
},
}))
);

View File

@@ -0,0 +1,37 @@
import { create } from 'zustand';
type Layout = null | 'layout1' | 'layout2' ;
type LayoutState = {
currentLayout: Layout;
setLayout: (layout: Layout) => void;
resetLayout: () => void;
};
const LAYOUT_STORAGE_KEY = 'currentLayout';
const useLayoutStore = create<LayoutState>((set) => ({
currentLayout: (() => {
if (typeof window !== 'undefined') {
const storedLayout = localStorage.getItem(LAYOUT_STORAGE_KEY);
return storedLayout ? (JSON.parse(storedLayout) as Layout) : null;
}
return null;
})(),
setLayout: (layout) => {
if (typeof window !== 'undefined') {
localStorage.setItem(LAYOUT_STORAGE_KEY, JSON.stringify(layout));
}
set({ currentLayout: layout });
},
resetLayout: () => {
if (typeof window !== 'undefined') {
localStorage.removeItem(LAYOUT_STORAGE_KEY);
}
set({ currentLayout: null });
},
}));
export default useLayoutStore;