first commit
This commit is contained in:
710
app/src/store/builder/store.ts
Normal file
710
app/src/store/builder/store.ts
Normal 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;
|
||||
}
|
||||
247
app/src/store/builder/useAisleStore.ts
Normal file
247
app/src/store/builder/useAisleStore.ts
Normal 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;
|
||||
},
|
||||
}))
|
||||
);
|
||||
231
app/src/store/builder/useAssetStore.ts
Normal file
231
app/src/store/builder/useAssetStore.ts
Normal 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);
|
||||
}
|
||||
}))
|
||||
);
|
||||
211
app/src/store/builder/useBuilderStore.ts
Normal file
211
app/src/store/builder/useBuilderStore.ts
Normal 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;
|
||||
});
|
||||
}
|
||||
}))
|
||||
);
|
||||
158
app/src/store/builder/useWallStore.tsx
Normal file
158
app/src/store/builder/useWallStore.tsx
Normal 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;
|
||||
},
|
||||
}))
|
||||
);
|
||||
37
app/src/store/builder/uselayoutStore.ts
Normal file
37
app/src/store/builder/uselayoutStore.ts
Normal 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;
|
||||
36
app/src/store/collaboration/useCollabStore.ts
Normal file
36
app/src/store/collaboration/useCollabStore.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface SelectedUser {
|
||||
color: string;
|
||||
name: string;
|
||||
id: string,
|
||||
location?: {
|
||||
position: {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
};
|
||||
rotation?: {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
};
|
||||
target?: {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
interface SelectedUserStore {
|
||||
selectedUser: SelectedUser | null;
|
||||
setSelectedUser: (user: SelectedUser) => void;
|
||||
clearSelectedUser: () => void;
|
||||
}
|
||||
|
||||
export const useSelectedUserStore = create<SelectedUserStore>((set) => ({
|
||||
selectedUser: null,
|
||||
setSelectedUser: (user) => set({ selectedUser: user }),
|
||||
clearSelectedUser: () => set({ selectedUser: null }),
|
||||
}));
|
||||
92
app/src/store/collaboration/useCommentStore.ts
Normal file
92
app/src/store/collaboration/useCommentStore.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { create } from 'zustand';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
interface CommentStore {
|
||||
comments: CommentsSchema;
|
||||
|
||||
// Comment operations
|
||||
addComment: (comment: CommentSchema) => void;
|
||||
setComments: (comments: CommentsSchema) => void;
|
||||
updateComment: (commentId: string, updates: Partial<CommentSchema>) => void;
|
||||
removeComment: (commentId: string) => void;
|
||||
|
||||
// Reply operations
|
||||
addReply: (commentId: string, reply: Reply) => void;
|
||||
updateReply: (commentId: string, replyId: string, updates: Partial<Reply>) => void;
|
||||
removeReply: (commentId: string, replyId: string) => void;
|
||||
|
||||
// Getters
|
||||
getCommentById: (commentId: string) => CommentSchema | undefined;
|
||||
}
|
||||
|
||||
export const useCommentStore = create<CommentStore>()(
|
||||
immer((set, get) => ({
|
||||
comments: [],
|
||||
|
||||
// Comment operations
|
||||
addComment: (comment) => {
|
||||
set((state) => {
|
||||
if (!state.comments.find(c => c.commentId === comment.commentId)) {
|
||||
state.comments.push(JSON.parse(JSON.stringify(comment)));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setComments: (comments) => {
|
||||
set((state) => {
|
||||
state.comments = comments;
|
||||
});
|
||||
},
|
||||
|
||||
updateComment: (commentId, updates) => {
|
||||
set((state) => {
|
||||
const comment = state.comments.find(c => c.commentId === commentId);
|
||||
if (comment) {
|
||||
Object.assign(comment, updates);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeComment: (commentId) => {
|
||||
set((state) => {
|
||||
state.comments = state.comments.filter(c => c.commentId !== commentId);
|
||||
});
|
||||
},
|
||||
|
||||
// Reply operations
|
||||
addReply: (commentId, reply) => {
|
||||
set((state) => {
|
||||
const comment = state.comments.find(c => c.commentId === commentId);
|
||||
if (comment) {
|
||||
comment.replies.push(reply);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateReply: (commentId, replyId, updates) => {
|
||||
set((state) => {
|
||||
const comment = state.comments.find(c => c.commentId === commentId);
|
||||
if (comment) {
|
||||
const reply = comment.replies.find(r => r.replyId === replyId);
|
||||
if (reply) {
|
||||
Object.assign(reply, updates);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeReply: (commentId, replyId) => {
|
||||
set((state) => {
|
||||
const comment = state.comments.find(c => c.commentId === commentId);
|
||||
if (comment) {
|
||||
comment.replies = comment.replies.filter(r => r.replyId !== replyId);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Getter
|
||||
getCommentById: (commentId) => {
|
||||
return get().comments.find(c => c.commentId === commentId);
|
||||
},
|
||||
}))
|
||||
);
|
||||
210
app/src/store/simulation/useArmBotStore.ts
Normal file
210
app/src/store/simulation/useArmBotStore.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
import { create } from 'zustand';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
interface ArmBotStore {
|
||||
armBots: ArmBotStatus[];
|
||||
|
||||
addArmBot: (productUuid: string, event: RoboticArmEventSchema) => void;
|
||||
removeArmBot: (modelUuid: string) => void;
|
||||
updateArmBot: (
|
||||
modelUuid: string,
|
||||
updates: Partial<Omit<ArmBotStatus, 'modelUuid' | 'productUuid'>>
|
||||
) => void;
|
||||
clearArmBots: () => void;
|
||||
|
||||
addCurrentAction: (modelUuid: string, actionUuid: string, materialType: string, materialId: string) => void;
|
||||
removeCurrentAction: (modelUuid: string) => void;
|
||||
|
||||
addAction: (modelUuid: string, action: RoboticArmPointSchema['actions'][number]) => void;
|
||||
removeAction: (modelUuid: string, actionUuid: string) => void;
|
||||
|
||||
updateStartPoint: (modelUuid: string, actionUuid: string, startPoint: [number, number, number] | null) => void;
|
||||
updateEndPoint: (modelUuid: string, actionUuid: string, endPoint: [number, number, number] | null) => void;
|
||||
|
||||
setArmBotActive: (modelUuid: string, isActive: boolean) => void;
|
||||
setArmBotState: (modelUuid: string, newState: ArmBotStatus['state']) => void;
|
||||
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||
|
||||
getArmBotById: (modelUuid: string) => ArmBotStatus | undefined;
|
||||
getArmBotsByProduct: (productUuid: string) => ArmBotStatus[];
|
||||
getArmBotsByState: (state: string) => ArmBotStatus[];
|
||||
getActiveArmBots: () => ArmBotStatus[];
|
||||
getIdleArmBots: () => ArmBotStatus[];
|
||||
getArmBotsByCurrentAction: (actionUuid: string) => ArmBotStatus[];
|
||||
}
|
||||
|
||||
export const createArmBotStore = () => {
|
||||
return create<ArmBotStore>()(
|
||||
immer((set, get) => ({
|
||||
armBots: [],
|
||||
|
||||
addArmBot: (productUuid, event) => {
|
||||
set((state) => {
|
||||
const exists = state.armBots.some(a => a.modelUuid === event.modelUuid);
|
||||
if (!exists) {
|
||||
state.armBots.push({
|
||||
...event,
|
||||
productUuid,
|
||||
isActive: false,
|
||||
idleTime: 0,
|
||||
activeTime: 0,
|
||||
state: 'idle',
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeArmBot: (modelUuid) => {
|
||||
set((state) => {
|
||||
state.armBots = state.armBots.filter(a => a.modelUuid !== modelUuid);
|
||||
});
|
||||
},
|
||||
|
||||
updateArmBot: (modelUuid, updates) => {
|
||||
set((state) => {
|
||||
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
Object.assign(armBot, updates);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
clearArmBots: () => {
|
||||
set((state) => {
|
||||
state.armBots = [];
|
||||
});
|
||||
},
|
||||
|
||||
addCurrentAction: (modelUuid, actionUuid, materialType, materialId) => {
|
||||
set((state) => {
|
||||
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
const action = armBot.point.actions.find(a => a.actionUuid === actionUuid);
|
||||
if (action) {
|
||||
armBot.currentAction = {
|
||||
actionUuid: action.actionUuid,
|
||||
actionName: action.actionName,
|
||||
materialType: materialType,
|
||||
materialId: materialId
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeCurrentAction: (modelUuid) => {
|
||||
set((state) => {
|
||||
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
armBot.currentAction = undefined;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
addAction: (modelUuid, action) => {
|
||||
set((state) => {
|
||||
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
armBot.point.actions.push(action);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeAction: (modelUuid, actionUuid) => {
|
||||
set((state) => {
|
||||
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
armBot.point.actions = armBot.point.actions.filter(a => a.actionUuid !== actionUuid);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateStartPoint: (modelUuid, actionUuid, startPoint) => {
|
||||
set((state) => {
|
||||
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
const action = armBot.point.actions.find(a => a.actionUuid === actionUuid);
|
||||
if (action) {
|
||||
action.process.startPoint = startPoint;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateEndPoint: (modelUuid, actionUuid, endPoint) => {
|
||||
set((state) => {
|
||||
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
const action = armBot.point.actions.find(a => a.actionUuid === actionUuid);
|
||||
if (action) {
|
||||
action.process.endPoint = endPoint;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setArmBotActive: (modelUuid, isActive) => {
|
||||
set((state) => {
|
||||
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
armBot.isActive = isActive;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setArmBotState: (modelUuid, newState) => {
|
||||
set((state) => {
|
||||
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
armBot.state = newState;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
armBot.activeTime += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const armBot = state.armBots.find(a => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
armBot.idleTime += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getArmBotById: (modelUuid) => {
|
||||
return get().armBots.find(a => a.modelUuid === modelUuid);
|
||||
},
|
||||
|
||||
getArmBotsByProduct: (productUuid) => {
|
||||
return get().armBots.filter(a => a.productUuid === productUuid);
|
||||
},
|
||||
|
||||
getArmBotsByState: (state) => {
|
||||
return get().armBots.filter(a => a.state === state);
|
||||
},
|
||||
|
||||
getActiveArmBots: () => {
|
||||
return get().armBots.filter(a => a.isActive);
|
||||
},
|
||||
|
||||
getIdleArmBots: () => {
|
||||
return get().armBots.filter(a => !a.isActive && a.state === 'idle');
|
||||
},
|
||||
|
||||
getArmBotsByCurrentAction: (actionUuid) => {
|
||||
return get().armBots.filter(a => a.currentAction?.actionUuid === actionUuid);
|
||||
}
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
export type ArmBotStoreType = ReturnType<typeof createArmBotStore>;
|
||||
140
app/src/store/simulation/useConveyorStore.ts
Normal file
140
app/src/store/simulation/useConveyorStore.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { create } from 'zustand';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
interface ConveyorStore {
|
||||
conveyors: ConveyorStatus[];
|
||||
|
||||
addConveyor: (productUuid: string, event: ConveyorEventSchema) => void;
|
||||
removeConveyor: (modelUuid: string) => void;
|
||||
updateConveyor: (
|
||||
modelUuid: string,
|
||||
updates: Partial<Omit<ConveyorStatus, 'modelUuid' | 'productUuid'>>
|
||||
) => void;
|
||||
clearConveyors: () => void;
|
||||
|
||||
setConveyorActive: (modelUuid: string, isActive: boolean) => void;
|
||||
setConveyorState: (modelUuid: string, newState: ConveyorStatus['state']) => void;
|
||||
setConveyorPaused: (modelUuid: string, isPaused: boolean) => void;
|
||||
|
||||
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||
|
||||
getConveyorById: (modelUuid: string) => ConveyorStatus | undefined;
|
||||
getConveyorsByProduct: (productUuid: string) => ConveyorStatus[];
|
||||
getConveyorsByState: (state: string) => ConveyorStatus[];
|
||||
getActiveConveyors: () => ConveyorStatus[];
|
||||
getIdleConveyors: () => ConveyorStatus[];
|
||||
}
|
||||
|
||||
export const createConveyorStore = () => {
|
||||
return create<ConveyorStore>()(
|
||||
immer((set, get) => ({
|
||||
conveyors: [],
|
||||
|
||||
addConveyor: (productUuid, event) => {
|
||||
set((state) => {
|
||||
const exists = state.conveyors.some(c => c.modelUuid === event.modelUuid);
|
||||
if (!exists) {
|
||||
state.conveyors.push({
|
||||
...event,
|
||||
productUuid,
|
||||
isActive: false,
|
||||
isPaused: false,
|
||||
idleTime: 0,
|
||||
activeTime: 0,
|
||||
state: 'idle',
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeConveyor: (modelUuid) => {
|
||||
set((state) => {
|
||||
state.conveyors = state.conveyors.filter(c => c.modelUuid !== modelUuid);
|
||||
});
|
||||
},
|
||||
|
||||
updateConveyor: (modelUuid, updates) => {
|
||||
set((state) => {
|
||||
const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
|
||||
if (conveyor) {
|
||||
Object.assign(conveyor, updates);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
clearConveyors: () => {
|
||||
set((state) => {
|
||||
state.conveyors = [];
|
||||
});
|
||||
},
|
||||
|
||||
setConveyorActive: (modelUuid, isActive) => {
|
||||
set((state) => {
|
||||
const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
|
||||
if (conveyor) {
|
||||
conveyor.isActive = isActive;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setConveyorState: (modelUuid, newState) => {
|
||||
set((state) => {
|
||||
const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
|
||||
if (conveyor) {
|
||||
conveyor.state = newState;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setConveyorPaused: (modelUuid, isPaused) => {
|
||||
set((state) => {
|
||||
const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
|
||||
if (conveyor) {
|
||||
conveyor.isPaused = isPaused;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
|
||||
if (conveyor) {
|
||||
conveyor.activeTime += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
|
||||
if (conveyor) {
|
||||
conveyor.idleTime += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getConveyorById: (modelUuid) => {
|
||||
return get().conveyors.find(c => c.modelUuid === modelUuid);
|
||||
},
|
||||
|
||||
getConveyorsByProduct: (productUuid) => {
|
||||
return get().conveyors.filter(c => c.productUuid === productUuid);
|
||||
},
|
||||
|
||||
getConveyorsByState: (state) => {
|
||||
return get().conveyors.filter(c => c.state === state);
|
||||
},
|
||||
|
||||
getActiveConveyors: () => {
|
||||
return get().conveyors.filter(c => c.isActive);
|
||||
},
|
||||
|
||||
getIdleConveyors: () => {
|
||||
return get().conveyors.filter(c => !c.isActive && c.state === 'idle');
|
||||
},
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
export type ConveyorStoreType = ReturnType<typeof createConveyorStore>;
|
||||
350
app/src/store/simulation/useEventsStore.ts
Normal file
350
app/src/store/simulation/useEventsStore.ts
Normal file
@@ -0,0 +1,350 @@
|
||||
import { create } from 'zustand';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
type EventsStore = {
|
||||
events: EventsSchema[];
|
||||
|
||||
// Event-level actions
|
||||
addEvent: (event: EventsSchema) => void;
|
||||
removeEvent: (modelUuid: string) => void;
|
||||
updateEvent: (modelUuid: string, updates: Partial<EventsSchema>) => EventsSchema | undefined;
|
||||
|
||||
// Point-level actions
|
||||
addPoint: (modelUuid: string, point: ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema) => void;
|
||||
removePoint: (modelUuid: string, pointUuid: string) => void;
|
||||
updatePoint: (
|
||||
modelUuid: string,
|
||||
pointUuid: string,
|
||||
updates: Partial<ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema>
|
||||
) => EventsSchema | undefined;
|
||||
|
||||
// Action-level actions
|
||||
addAction: (
|
||||
modelUuid: string,
|
||||
pointUuid: string,
|
||||
action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']
|
||||
) => void;
|
||||
removeAction: (actionUuid: string) => void;
|
||||
updateAction: (
|
||||
actionUuid: string,
|
||||
updates: Partial<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']>
|
||||
) => void;
|
||||
|
||||
// Trigger-level actions
|
||||
addTrigger: (actionUuid: string, trigger: TriggerSchema) => void;
|
||||
removeTrigger: (triggerUuid: string) => void;
|
||||
updateTrigger: (triggerUuid: string, updates: Partial<TriggerSchema>) => void;
|
||||
|
||||
// Helper functions
|
||||
getEventByModelUuid: (modelUuid: string) => EventsSchema | undefined;
|
||||
getPointByUuid: (modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
|
||||
getActionByUuid: (actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
|
||||
getTriggerByUuid: (triggerUuid: string) => TriggerSchema | undefined;
|
||||
};
|
||||
|
||||
export const useEventsStore = create<EventsStore>()(
|
||||
immer((set, get) => ({
|
||||
events: [],
|
||||
|
||||
// Event-level actions
|
||||
addEvent: (event) => {
|
||||
set((state) => {
|
||||
if (!state.events.some(e => 'modelUuid' in e && e.modelUuid === event.modelUuid)) {
|
||||
state.events.push(event);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeEvent: (modelUuid) => {
|
||||
set((state) => {
|
||||
state.events = state.events.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid);
|
||||
});
|
||||
},
|
||||
|
||||
updateEvent: (modelUuid, updates) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
if (event) {
|
||||
Object.assign(event, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
// Point-level actions
|
||||
addPoint: (modelUuid, point) => {
|
||||
set((state) => {
|
||||
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
if (event && 'points' in event) {
|
||||
const existingPoint = (event as ConveyorEventSchema).points.find(p => p.uuid === point.uuid);
|
||||
if (!existingPoint) {
|
||||
(event as ConveyorEventSchema).points.push(point as ConveyorPointSchema);
|
||||
}
|
||||
} else if (event && 'point' in event) {
|
||||
if (!(event as any).point || (event as any).point.uuid !== point.uuid) {
|
||||
(event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removePoint: (modelUuid, pointUuid) => {
|
||||
set((state) => {
|
||||
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
if (event && 'points' in event) {
|
||||
(event as ConveyorEventSchema).points = (event as ConveyorEventSchema).points.filter(p => p.uuid !== pointUuid);
|
||||
}
|
||||
// For single-point events, you might want to handle differently
|
||||
});
|
||||
},
|
||||
|
||||
updatePoint: (modelUuid, pointUuid, updates) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
if (event && 'points' in event) {
|
||||
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||
if (point) {
|
||||
Object.assign(point, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
|
||||
Object.assign((event as any).point, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
// Action-level actions
|
||||
addAction: (modelUuid, pointUuid, action) => {
|
||||
set((state) => {
|
||||
const event = state.events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
if (event && 'points' in event) {
|
||||
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||
if (point && (!point.action || point.action.actionUuid !== action.actionUuid)) {
|
||||
point.action = action as any;
|
||||
}
|
||||
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && (!point.action || point.action.actionUuid !== action.actionUuid)) {
|
||||
point.action = action;
|
||||
} else if ('actions' in point && !point.actions.some((a: any) => a.actionUuid === action.actionUuid)) {
|
||||
point.actions.push(action);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeAction: (actionUuid) => {
|
||||
set((state) => {
|
||||
for (const event of state.events) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && point.action.actionUuid === actionUuid) {
|
||||
// Handle removal for single action points
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if (event.type === "roboticArm") {
|
||||
if ('actions' in point) {
|
||||
point.actions = point.actions.filter((a: any) => a.actionUuid !== actionUuid);
|
||||
}
|
||||
} else if ('action' in point && point.action?.actionUuid === actionUuid) {
|
||||
// Handle single action
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateAction: (actionUuid, updates) => {
|
||||
set((state) => {
|
||||
for (const event of state.events) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && point.action.actionUuid === actionUuid) {
|
||||
Object.assign(point.action, updates);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && point.action.actionUuid === actionUuid) {
|
||||
Object.assign(point.action, updates);
|
||||
return;
|
||||
} else if ('actions' in point) {
|
||||
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
|
||||
if (action) {
|
||||
Object.assign(action, updates);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Trigger-level actions
|
||||
addTrigger: (actionUuid, trigger) => {
|
||||
set((state) => {
|
||||
for (const event of state.events) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && point.action.actionUuid === actionUuid) {
|
||||
if (!point.action.triggers.some(t => t.triggerUuid === trigger.triggerUuid)) {
|
||||
point.action.triggers.push(trigger);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point: MachinePointSchema | VehiclePointSchema = (event as any).point;
|
||||
if ('action' in point && point.action.actionUuid === actionUuid) {
|
||||
if (!point.action.triggers.some(t => t.triggerUuid === trigger.triggerUuid)) {
|
||||
point.action.triggers.push(trigger);
|
||||
}
|
||||
return;
|
||||
} else if ('actions' in point) {
|
||||
const action = (point as RoboticArmPointSchema).actions.find((a) => a.actionUuid === actionUuid);
|
||||
if (action && !action.triggers.some(t => t.triggerUuid === trigger.triggerUuid)) {
|
||||
action.triggers.push(trigger);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeTrigger: (triggerUuid) => {
|
||||
set((state) => {
|
||||
for (const event of state.events) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && 'triggers' in point.action) {
|
||||
point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid);
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && 'triggers' in point.action) {
|
||||
point.action.triggers = point.action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
|
||||
} else if ('actions' in point) {
|
||||
for (const action of point.actions) {
|
||||
if ('triggers' in action) {
|
||||
action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateTrigger: (triggerUuid, updates) => {
|
||||
set((state) => {
|
||||
for (const event of state.events) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && 'triggers' in point.action) {
|
||||
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
||||
if (trigger) {
|
||||
Object.assign(trigger, updates);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && 'triggers' in point.action) {
|
||||
const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||
if (trigger) {
|
||||
Object.assign(trigger, updates);
|
||||
return;
|
||||
}
|
||||
} else if ('actions' in point) {
|
||||
for (const action of point.actions) {
|
||||
if ('triggers' in action) {
|
||||
const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||
if (trigger) {
|
||||
Object.assign(trigger, updates);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Helper functions
|
||||
getEventByModelUuid: (modelUuid) => {
|
||||
return get().events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
},
|
||||
|
||||
getPointByUuid: (modelUuid, pointUuid) => {
|
||||
const event = get().events.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
if (event && 'points' in event) {
|
||||
return (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
|
||||
return (event as any).point;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getActionByUuid: (actionUuid) => {
|
||||
const state = get();
|
||||
for (const event of state.events) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && point.action.actionUuid === actionUuid) {
|
||||
return point.action;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && point.action.actionUuid === actionUuid) {
|
||||
return point.action;
|
||||
} else if ('actions' in point) {
|
||||
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
|
||||
if (action) return action;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getTriggerByUuid: (triggerUuid) => {
|
||||
const state = get();
|
||||
for (const event of state.events) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && 'triggers' in point.action) {
|
||||
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
||||
if (trigger) return trigger;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && 'triggers' in point.action) {
|
||||
const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||
if (trigger) return trigger;
|
||||
} else if ('actions' in point) {
|
||||
for (const action of point.actions) {
|
||||
if ('triggers' in action) {
|
||||
const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||
if (trigger) return trigger;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}))
|
||||
);
|
||||
180
app/src/store/simulation/useMachineStore.ts
Normal file
180
app/src/store/simulation/useMachineStore.ts
Normal file
@@ -0,0 +1,180 @@
|
||||
import { create } from "zustand";
|
||||
import { immer } from "zustand/middleware/immer";
|
||||
|
||||
interface MachineStore {
|
||||
machines: MachineStatus[];
|
||||
|
||||
addMachine: (productUuid: string, machine: MachineEventSchema) => void;
|
||||
removeMachine: (modelUuid: string) => void;
|
||||
updateMachine: (
|
||||
modelUuid: string,
|
||||
updates: Partial<Omit<MachineStatus, "modelUuid" | "productUuid">>
|
||||
) => void;
|
||||
clearMachines: () => void;
|
||||
|
||||
addCurrentAction: (
|
||||
modelUuid: string,
|
||||
actionUuid: string,
|
||||
materialType: string,
|
||||
materialId: string
|
||||
) => void;
|
||||
removeCurrentAction: (modelUuid: string) => void;
|
||||
|
||||
setMachineActive: (modelUuid: string, isActive: boolean) => void;
|
||||
setMachineState: (
|
||||
modelUuid: string,
|
||||
newState: MachineStatus["state"]
|
||||
) => void;
|
||||
|
||||
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||
resetTime: (modelUuid: string) => void;
|
||||
|
||||
getMachineById: (modelUuid: string) => MachineStatus | undefined;
|
||||
getMachinesByProduct: (productUuid: string) => MachineStatus[];
|
||||
getMachinesBystate: (state: string) => MachineStatus[];
|
||||
getActiveMachines: () => MachineStatus[];
|
||||
getIdleMachines: () => MachineStatus[];
|
||||
}
|
||||
|
||||
export const createMachineStore = () => {
|
||||
return create<MachineStore>()(
|
||||
immer((set, get) => ({
|
||||
machines: [],
|
||||
|
||||
addMachine: (productUuid, machine) => {
|
||||
set((state) => {
|
||||
const exists = state.machines.some(
|
||||
(m) => m.modelUuid === machine.modelUuid
|
||||
);
|
||||
if (!exists) {
|
||||
state.machines.push({
|
||||
...machine,
|
||||
productUuid,
|
||||
isActive: false,
|
||||
idleTime: 0,
|
||||
activeTime: 0,
|
||||
state: "idle",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeMachine: (modelUuid) => {
|
||||
set((state) => {
|
||||
state.machines = state.machines.filter(
|
||||
(m) => m.modelUuid !== modelUuid
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
updateMachine: (modelUuid, updates) => {
|
||||
set((state) => {
|
||||
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
|
||||
if (machine) {
|
||||
Object.assign(machine, updates);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
clearMachines: () => {
|
||||
set((state) => {
|
||||
state.machines = [];
|
||||
});
|
||||
},
|
||||
|
||||
addCurrentAction: (modelUuid, actionUuid, materialType, materialId) => {
|
||||
set((state) => {
|
||||
const armBot = state.machines.find((a) => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
const action = armBot.point.action;
|
||||
if (action) {
|
||||
armBot.currentAction = {
|
||||
actionUuid: actionUuid,
|
||||
actionName: action.actionName,
|
||||
materialType: materialType,
|
||||
materialId: materialId,
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeCurrentAction: (modelUuid) => {
|
||||
set((state) => {
|
||||
const armBot = state.machines.find((a) => a.modelUuid === modelUuid);
|
||||
if (armBot) {
|
||||
armBot.currentAction = undefined;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setMachineActive: (modelUuid, isActive) => {
|
||||
set((state) => {
|
||||
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
|
||||
if (machine) {
|
||||
machine.isActive = isActive;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setMachineState: (modelUuid, newState) => {
|
||||
set((state) => {
|
||||
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
|
||||
if (machine) {
|
||||
machine.state = newState;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
|
||||
if (machine) {
|
||||
machine.activeTime += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
|
||||
if (machine) {
|
||||
machine.idleTime += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
resetTime: (modelUuid) => {
|
||||
set((state) => {
|
||||
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
|
||||
if (machine) {
|
||||
machine.activeTime = 0;
|
||||
machine.idleTime = 0;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getMachineById: (modelUuid) => {
|
||||
return get().machines.find((m) => m.modelUuid === modelUuid);
|
||||
},
|
||||
|
||||
getMachinesByProduct: (productUuid) => {
|
||||
return get().machines.filter((m) => m.productUuid === productUuid);
|
||||
},
|
||||
|
||||
getMachinesBystate: (state) => {
|
||||
return get().machines.filter((m) => m.state === state);
|
||||
},
|
||||
|
||||
getActiveMachines: () => {
|
||||
return get().machines.filter((m) => m.isActive);
|
||||
},
|
||||
|
||||
getIdleMachines: () => {
|
||||
return get().machines.filter((m) => !m.isActive && m.state === "idle");
|
||||
},
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
export type MachineStoreType = ReturnType<typeof createMachineStore>;
|
||||
284
app/src/store/simulation/useMaterialStore.ts
Normal file
284
app/src/store/simulation/useMaterialStore.ts
Normal file
@@ -0,0 +1,284 @@
|
||||
import { create } from 'zustand';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
type MaterialsStore = {
|
||||
materials: MaterialsSchema;
|
||||
materialHistory: MaterialHistorySchema;
|
||||
|
||||
addMaterial: (material: MaterialSchema) => MaterialSchema | undefined;
|
||||
removeMaterial: (materialId: string) => MaterialSchema | undefined;
|
||||
clearMaterials: () => void;
|
||||
updateMaterial: (materialId: string, updates: Partial<MaterialSchema>) => MaterialSchema | undefined;
|
||||
|
||||
setPreviousLocation: (
|
||||
materialId: string,
|
||||
location: {
|
||||
modelUuid: string;
|
||||
pointUuid: string;
|
||||
actionUuid: string;
|
||||
}
|
||||
) => MaterialSchema | undefined;
|
||||
|
||||
setCurrentLocation: (
|
||||
materialId: string,
|
||||
location: {
|
||||
modelUuid: string;
|
||||
pointUuid: string;
|
||||
actionUuid: string;
|
||||
}
|
||||
) => MaterialSchema | undefined;
|
||||
|
||||
setNextLocation: (
|
||||
materialId: string,
|
||||
location: {
|
||||
modelUuid: string;
|
||||
pointUuid: string;
|
||||
} | null
|
||||
) => MaterialSchema | undefined;
|
||||
|
||||
setMaterial: (materialId: string, materialType: string) => MaterialSchema | undefined;
|
||||
setStartTime: (materialId: string, startTime: number) => MaterialSchema | undefined;
|
||||
setEndTime: (materialId: string, endTime: number) => MaterialSchema | undefined;
|
||||
setCost: (materialId: string, cost: number) => MaterialSchema | undefined;
|
||||
setWeight: (materialId: string, weight: number) => MaterialSchema | undefined;
|
||||
setIsActive: (materialId: string, isActive: boolean) => MaterialSchema | undefined;
|
||||
setIsVisible: (materialId: string, isVisible: boolean) => MaterialSchema | undefined;
|
||||
setIsPaused: (materialId: string, isPaused: boolean) => MaterialSchema | undefined;
|
||||
setIsRendered: (materialId: string, isRendered: boolean) => MaterialSchema | undefined;
|
||||
|
||||
getMaterialById: (materialId: string) => MaterialSchema | undefined;
|
||||
getMaterialsByCurrentModelUuid: (currentModelUuid: string) => MaterialSchema[] | undefined;
|
||||
getMaterialByCurrentPointUuid: (currentPointUuid: string) => MaterialSchema | undefined;
|
||||
getMaterialsByPoint: (pointUuid: string) => MaterialSchema[];
|
||||
getMaterialsByModel: (modelUuid: string) => MaterialSchema[];
|
||||
getMaterialHistory: () => MaterialHistorySchema;
|
||||
};
|
||||
|
||||
export const createMaterialStore = () => {
|
||||
return create<MaterialsStore>()(
|
||||
immer((set, get) => ({
|
||||
materials: [],
|
||||
materialHistory: [],
|
||||
|
||||
addMaterial: (material) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
state.materials.push(material);
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
removeMaterial: (materialId) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
state.materials = state.materials.filter(m => m.materialId !== materialId);
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
|
||||
state.materialHistory.push({
|
||||
material,
|
||||
removedAt: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
clearMaterials: () => {
|
||||
set((state) => {
|
||||
state.materials = [];
|
||||
});
|
||||
},
|
||||
|
||||
updateMaterial: (materialId, updates) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
Object.assign(material, updates);
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
}
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setPreviousLocation: (materialId, location) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.previous = location;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
}
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setCurrentLocation: (materialId, location) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.current = location;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
}
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setNextLocation: (materialId, location) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.next = location;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
}
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setMaterial: (materialId, materialType) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.materialType = materialType;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
};
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setStartTime: (materialId, startTime) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.startTime = startTime
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
};
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setEndTime: (materialId, endTime) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.endTime = endTime;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
};
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setCost: (materialId, cost) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.cost = cost;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
};
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setWeight: (materialId, weight) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.weight = weight;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
};
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setIsActive: (materialId, isActive) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.isActive = isActive;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
};
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setIsVisible: (materialId, isVisible) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.isVisible = isVisible;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
};
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setIsPaused: (materialId, isPaused) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.isPaused = isPaused;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
};
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
setIsRendered: (materialId, isRendered) => {
|
||||
let updatedMaterial: MaterialSchema | undefined;
|
||||
set((state) => {
|
||||
const material = state.materials.find(m => m.materialId === materialId);
|
||||
if (material) {
|
||||
material.isRendered = isRendered;
|
||||
updatedMaterial = JSON.parse(JSON.stringify(material));
|
||||
};
|
||||
});
|
||||
return updatedMaterial;
|
||||
},
|
||||
|
||||
getMaterialById: (materialId) => {
|
||||
return get().materials.find(m => m.materialId === materialId);
|
||||
},
|
||||
|
||||
getMaterialsByCurrentModelUuid: (currentModelUuid) => {
|
||||
return get().materials.filter(m => m.current?.modelUuid === currentModelUuid);
|
||||
},
|
||||
|
||||
getMaterialByCurrentPointUuid: (currentPointlUuid) => {
|
||||
return get().materials.find(m => m.current?.pointUuid === currentPointlUuid);
|
||||
},
|
||||
|
||||
getMaterialsByPoint: (pointUuid) => {
|
||||
return get().materials.filter(m =>
|
||||
m.current?.pointUuid === pointUuid ||
|
||||
m.next?.pointUuid === pointUuid
|
||||
);
|
||||
},
|
||||
|
||||
getMaterialsByModel: (modelUuid) => {
|
||||
return get().materials.filter(m =>
|
||||
m.current?.modelUuid === modelUuid ||
|
||||
m.next?.modelUuid === modelUuid
|
||||
);
|
||||
},
|
||||
|
||||
getMaterialHistory: () => {
|
||||
return get().materialHistory;
|
||||
},
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export type MaterialStoreType = ReturnType<typeof createMaterialStore>;
|
||||
791
app/src/store/simulation/useProductStore.ts
Normal file
791
app/src/store/simulation/useProductStore.ts
Normal file
@@ -0,0 +1,791 @@
|
||||
import { create } from 'zustand';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
type ProductsStore = {
|
||||
products: productsSchema;
|
||||
|
||||
// Product-level actions
|
||||
addProduct: (productName: string, productUuid: string) => void;
|
||||
setProducts: (products: productsSchema) => void;
|
||||
removeProduct: (productUuid: string) => void;
|
||||
updateProduct: (productUuid: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void;
|
||||
|
||||
// Event-level actions
|
||||
addEvent: (productUuid: string, event: EventsSchema) => void;
|
||||
removeEvent: (productUuid: string, modelUuid: string) => void;
|
||||
deleteEvent: (modelUuid: string) => void;
|
||||
updateEvent: (productUuid: string, modelUuid: string, updates: Partial<EventsSchema>) => EventsSchema | undefined;
|
||||
|
||||
// Point-level actions
|
||||
addPoint: (productUuid: string, modelUuid: string, point: ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema) => void;
|
||||
removePoint: (productUuid: string, modelUuid: string, pointUuid: string) => void;
|
||||
updatePoint: (
|
||||
productUuid: string,
|
||||
modelUuid: string,
|
||||
pointUuid: string,
|
||||
updates: Partial<ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema>
|
||||
) => EventsSchema | undefined;
|
||||
|
||||
// Action-level actions
|
||||
addAction: (
|
||||
productUuid: string,
|
||||
modelUuid: string,
|
||||
pointUuid: string,
|
||||
action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']
|
||||
) => EventsSchema | undefined;
|
||||
removeAction: (productUuid: string, actionUuid: string) => EventsSchema | undefined;
|
||||
updateAction: (
|
||||
productUuid: string,
|
||||
actionUuid: string,
|
||||
updates: Partial<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']>
|
||||
) => EventsSchema | undefined;
|
||||
|
||||
// Trigger-level actionss
|
||||
addTrigger: (
|
||||
productUuid: string,
|
||||
actionUuid: string,
|
||||
trigger: TriggerSchema
|
||||
) => EventsSchema | undefined;
|
||||
removeTrigger: (productUuid: string, triggerUuid: string) => EventsSchema | undefined;
|
||||
updateTrigger: (
|
||||
productUuid: string,
|
||||
triggerUuid: string,
|
||||
updates: Partial<TriggerSchema>
|
||||
) => EventsSchema | undefined;
|
||||
|
||||
// Renaming functions
|
||||
renameProduct: (productUuid: string, newName: string) => void;
|
||||
renameAction: (productUuid: string, actionUuid: string, newName: string) => EventsSchema | undefined;
|
||||
renameTrigger: (productUuid: string, triggerUuid: string, newName: string) => EventsSchema | undefined;
|
||||
|
||||
// Helper functions
|
||||
getProductById: (productUuid: string) => { productName: string; productUuid: string; eventDatas: EventsSchema[] } | undefined;
|
||||
getEventByModelUuid: (productUuid: string, modelUuid: string) => EventsSchema | undefined;
|
||||
getEventByActionUuid: (productUuid: string, actionUuid: string) => EventsSchema | undefined;
|
||||
getEventByTriggerUuid: (productUuid: string, triggerUuid: string) => EventsSchema | undefined;
|
||||
getEventByPointUuid: (productUuid: string, pointUuid: string) => EventsSchema | undefined;
|
||||
getPointByUuid: (productUuid: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
|
||||
getActionByUuid: (productUuid: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
|
||||
getActionByPointUuid: (productUuid: string, pointUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
|
||||
getModelUuidByPointUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
||||
getModelUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
||||
getPointUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
||||
getTriggerByUuid: (productUuid: string, triggerUuid: string) => TriggerSchema | undefined;
|
||||
getIsEventInProduct: (productUuid: string, modelUuid: string) => boolean;
|
||||
};
|
||||
|
||||
export const useProductStore = create<ProductsStore>()(
|
||||
immer((set, get) => ({
|
||||
products: [],
|
||||
|
||||
// Product-level actions
|
||||
addProduct: (productName, productUuid) => {
|
||||
set((state) => {
|
||||
const existingProduct = state.products.find(p => p.productUuid === productUuid);
|
||||
if (!existingProduct) {
|
||||
const newProduct = {
|
||||
productName,
|
||||
productUuid: productUuid,
|
||||
eventDatas: []
|
||||
};
|
||||
state.products.push(newProduct);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setProducts: (products) => {
|
||||
set((state) => {
|
||||
state.products = products;
|
||||
});
|
||||
},
|
||||
|
||||
removeProduct: (productUuid) => {
|
||||
set((state) => {
|
||||
state.products = state.products.filter(p => p.productUuid !== productUuid);
|
||||
});
|
||||
},
|
||||
|
||||
updateProduct: (productUuid, updates) => {
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
Object.assign(product, updates);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Event-level actions
|
||||
addEvent: (productUuid, event) => {
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
const existingEvent = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === event.modelUuid);
|
||||
if (!existingEvent) {
|
||||
product.eventDatas.push(event);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeEvent: (productUuid, modelUuid) => {
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
product.eventDatas = product.eventDatas.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
deleteEvent: (modelUuid) => {
|
||||
set((state) => {
|
||||
for (const product of state.products) {
|
||||
product.eventDatas = product.eventDatas.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateEvent: (productUuid, modelUuid, updates) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
if (event) {
|
||||
Object.assign(event, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
// Point-level actions
|
||||
addPoint: (productUuid, modelUuid, point) => {
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
if (event && 'points' in event) {
|
||||
const existingPoint = (event as ConveyorEventSchema).points.find(p => p.uuid === point.uuid);
|
||||
if (!existingPoint) {
|
||||
(event as ConveyorEventSchema).points.push(point as ConveyorPointSchema);
|
||||
}
|
||||
} else if (event && 'point' in event) {
|
||||
const existingPoint = (event as any).point?.uuid === point.uuid;
|
||||
if (!existingPoint) {
|
||||
(event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removePoint: (productUuid, modelUuid, pointUuid) => {
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
if (event && 'points' in event) {
|
||||
(event as ConveyorEventSchema).points = (event as ConveyorEventSchema).points.filter(p => p.uuid !== pointUuid);
|
||||
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
|
||||
// For events with single point, we can't remove it, only reset to empty
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updatePoint: (productUuid, modelUuid, pointUuid, updates) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
if (event && 'points' in event) {
|
||||
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||
if (point) {
|
||||
Object.assign(point, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
|
||||
Object.assign((event as any).point, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
// Action-level actions
|
||||
addAction: (productUuid, modelUuid, pointUuid, action) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
if (event && 'points' in event) {
|
||||
const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||
if (point && (!point.action || point.action.actionUuid !== action.actionUuid)) {
|
||||
point.action = action as any;
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
} else if (event && 'point' in event && (event as any).point.uuid === pointUuid) {
|
||||
if ('action' in (event as any).point) {
|
||||
if (!(event as any).point.action || (event as any).point.action.actionUuid !== action.actionUuid) {
|
||||
(event as any).point.action = action;
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
} else if ('actions' in (event as any).point) {
|
||||
const existingAction = (event as any).point.actions.find((a: any) => a.actionUuid === action.actionUuid);
|
||||
if (!existingAction) {
|
||||
(event as any).point.actions.push(action);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
removeAction: (productUuid, actionUuid) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
// Handle ConveyorEventSchema
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if (event.type === "roboticArm") {
|
||||
if ('actions' in point) {
|
||||
const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid);
|
||||
if (index !== -1) {
|
||||
point.actions.splice(index, 1);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if ('action' in point && point.action?.actionUuid === actionUuid) {
|
||||
point.action = undefined;
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
updateAction: (productUuid, actionUuid, updates) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && point.action.actionUuid === actionUuid) {
|
||||
Object.assign(point.action, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && point.action.actionUuid === actionUuid) {
|
||||
Object.assign(point.action, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
} else if ('actions' in point) {
|
||||
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
|
||||
if (action) {
|
||||
Object.assign(action, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
// Trigger-level actions
|
||||
addTrigger: (productUuid, actionUuid, trigger) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && point.action.actionUuid === actionUuid) {
|
||||
const existingTrigger = point.action.triggers.find(t => t.triggerUuid === trigger.triggerUuid);
|
||||
if (!existingTrigger) {
|
||||
point.action.triggers.push(trigger);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && point.action.actionUuid === actionUuid) {
|
||||
const existingTrigger = point.action.triggers.find((t: any) => t.triggerUuid === trigger.triggerUuid);
|
||||
if (!existingTrigger) {
|
||||
point.action.triggers.push(trigger);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
return;
|
||||
} else if ('actions' in point) {
|
||||
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
|
||||
if (action) {
|
||||
const existingTrigger = action.triggers.find((t: any) => t.triggerUuid === trigger.triggerUuid);
|
||||
if (!existingTrigger) {
|
||||
action.triggers.push(trigger);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
removeTrigger: (productUuid, triggerUuid) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && 'triggers' in point.action) {
|
||||
const Trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
||||
if (Trigger) {
|
||||
point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && 'triggers' in point.action) {
|
||||
const Trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||
if (Trigger) {
|
||||
point.action.triggers = point.action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
} else if ('actions' in point) {
|
||||
for (const action of point.actions) {
|
||||
if ('triggers' in action) {
|
||||
const Trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||
if (Trigger) {
|
||||
action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
updateTrigger: (productUuid, triggerUuid, updates) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && 'triggers' in point.action) {
|
||||
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
||||
if (trigger) {
|
||||
Object.assign(trigger, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && 'triggers' in point.action) {
|
||||
const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||
if (trigger) {
|
||||
Object.assign(trigger, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
} else if ('actions' in point) {
|
||||
for (const action of point.actions) {
|
||||
if ('triggers' in action) {
|
||||
const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||
if (trigger) {
|
||||
Object.assign(trigger, updates);
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
// Renaming functions
|
||||
renameProduct: (productUuid, newName) => {
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
product.productName = newName;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
renameAction: (productUuid, actionUuid, newName) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && point.action.actionUuid === actionUuid) {
|
||||
point.action.actionName = newName;
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && point.action.actionUuid === actionUuid) {
|
||||
point.action.actionName = newName;
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
} else if ('actions' in point) {
|
||||
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
|
||||
if (action) {
|
||||
action.actionName = newName;
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
renameTrigger: (productUuid, triggerUuid, newName) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
const product = state.products.find(p => p.productUuid === productUuid);
|
||||
if (product) {
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action && 'triggers' in point.action) {
|
||||
const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid);
|
||||
if (trigger) {
|
||||
trigger.triggerName = newName;
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && 'triggers' in point.action) {
|
||||
const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||
if (trigger) {
|
||||
trigger.triggerName = newName;
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
} else if ('actions' in point) {
|
||||
for (const action of point.actions) {
|
||||
if ('triggers' in action) {
|
||||
const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid);
|
||||
if (trigger) {
|
||||
trigger.triggerName = newName;
|
||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return updatedEvent;
|
||||
},
|
||||
|
||||
// Helper functions
|
||||
getProductById: (productUuid) => {
|
||||
return get().products.find(p => p.productUuid === productUuid);
|
||||
},
|
||||
|
||||
getEventByModelUuid: (productUuid, modelUuid) => {
|
||||
const product = get().getProductById(productUuid);
|
||||
if (!product) return undefined;
|
||||
return product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
},
|
||||
|
||||
getEventByActionUuid: (productUuid, actionUuid) => {
|
||||
const product = get().getProductById(productUuid);
|
||||
if (!product) return undefined;
|
||||
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action?.actionUuid === actionUuid) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && point.action?.actionUuid === actionUuid) {
|
||||
return event;
|
||||
} else if ('actions' in point) {
|
||||
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
|
||||
if (action) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getEventByTriggerUuid: (productUuid, triggerUuid) => {
|
||||
const product = get().getProductById(productUuid);
|
||||
if (!product) return undefined;
|
||||
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action?.triggers?.some(t => t.triggerUuid === triggerUuid)) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point) {
|
||||
if (point.action?.triggers?.some((t: any) => t.triggerUuid === triggerUuid)) {
|
||||
return event;
|
||||
}
|
||||
} else if ('actions' in point) {
|
||||
for (const action of point.actions) {
|
||||
if (action.triggers?.some((t: any) => t.triggerUuid === triggerUuid)) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getEventByPointUuid: (productUuid, pointUuid) => {
|
||||
const product = get().getProductById(productUuid);
|
||||
if (!product) return undefined;
|
||||
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
if ((event as ConveyorEventSchema).points.some(p => p.uuid === pointUuid)) {
|
||||
return event;
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
if ((event as any).point?.uuid === pointUuid) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getPointByUuid: (productUuid, modelUuid, pointUuid) => {
|
||||
const event = get().getEventByModelUuid(productUuid, modelUuid);
|
||||
if (!event) return undefined;
|
||||
|
||||
if ('points' in event) {
|
||||
return (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid);
|
||||
} else if ('point' in event && (event as any).point.uuid === pointUuid) {
|
||||
return (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getActionByUuid: (productUuid, actionUuid) => {
|
||||
const product = get().products.find(p => p.productUuid === productUuid);
|
||||
if (!product) return undefined;
|
||||
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action?.actionUuid === actionUuid) {
|
||||
return point.action;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && point.action?.actionUuid === actionUuid) {
|
||||
return point.action;
|
||||
} else if ('actions' in point) {
|
||||
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
|
||||
if (action) return action;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getActionByPointUuid: (productUuid, pointUuid) => {
|
||||
const product = get().products.find(p => p.productUuid === productUuid);
|
||||
if (!product) return undefined;
|
||||
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.uuid === pointUuid) {
|
||||
return point.action;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if (point.uuid === pointUuid) {
|
||||
return point.action;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getModelUuidByPointUuid: (productUuid, pointUuid) => {
|
||||
const product = get().products.find(p => p.productUuid === productUuid);
|
||||
if (!product) return undefined;
|
||||
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.uuid === pointUuid) {
|
||||
return event.modelUuid;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if (point.uuid === pointUuid) {
|
||||
return event.modelUuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getModelUuidByActionUuid: (productUuid, actionUuid) => {
|
||||
const product = get().products.find(p => p.productUuid === productUuid);
|
||||
if (!product) return undefined;
|
||||
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action?.actionUuid === actionUuid) {
|
||||
return event.modelUuid;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && point.action?.actionUuid === actionUuid) {
|
||||
return event.modelUuid;
|
||||
} else if ('actions' in point) {
|
||||
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
|
||||
if (action) return event.modelUuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getPointUuidByActionUuid: (productUuid, actionUuid) => {
|
||||
const product = get().products.find(p => p.productUuid === productUuid);
|
||||
if (!product) return undefined;
|
||||
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
if (point.action?.actionUuid === actionUuid) {
|
||||
return point.uuid;
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point && point.action?.actionUuid === actionUuid) {
|
||||
return point.uuid;
|
||||
} else if ('actions' in point) {
|
||||
const action = point.actions.find((a: any) => a.actionUuid === actionUuid);
|
||||
if (action) return point.uuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getTriggerByUuid: (productUuid, triggerUuid) => {
|
||||
const product = get().products.find(p => p.productUuid === productUuid);
|
||||
if (!product) return undefined;
|
||||
|
||||
for (const event of product.eventDatas) {
|
||||
if ('points' in event) {
|
||||
for (const point of (event as ConveyorEventSchema).points) {
|
||||
for (const trigger of point.action?.triggers || []) {
|
||||
if (trigger.triggerUuid === triggerUuid) {
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ('point' in event) {
|
||||
const point = (event as any).point;
|
||||
if ('action' in point) {
|
||||
for (const trigger of point.action?.triggers || []) {
|
||||
if (trigger.triggerUuid === triggerUuid) {
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
} else if ('actions' in point) {
|
||||
for (const action of point.actions) {
|
||||
for (const trigger of action.triggers || []) {
|
||||
if (trigger.triggerUuid === triggerUuid) {
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
getIsEventInProduct: (productUuid, modelUuid) => {
|
||||
const product = get().getProductById(productUuid);
|
||||
if (!product) return false;
|
||||
return product.eventDatas.some(e => 'modelUuid' in e && e.modelUuid === modelUuid);
|
||||
}
|
||||
}))
|
||||
);
|
||||
197
app/src/store/simulation/useSimulationStore.ts
Normal file
197
app/src/store/simulation/useSimulationStore.ts
Normal file
@@ -0,0 +1,197 @@
|
||||
import { create } from 'zustand';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import * as THREE from 'three';
|
||||
|
||||
interface SelectedEventSphereState {
|
||||
selectedEventSphere: THREE.Mesh | null;
|
||||
setSelectedEventSphere: (mesh: THREE.Mesh | null) => void;
|
||||
clearSelectedEventSphere: () => void;
|
||||
}
|
||||
|
||||
export const useSelectedEventSphere = create<SelectedEventSphereState>()(
|
||||
immer((set) => ({
|
||||
selectedEventSphere: null,
|
||||
setSelectedEventSphere: (mesh) => {
|
||||
set((state) => {
|
||||
state.selectedEventSphere = mesh;
|
||||
});
|
||||
},
|
||||
clearSelectedEventSphere: () => {
|
||||
set((state) => {
|
||||
state.selectedEventSphere = null;
|
||||
});
|
||||
},
|
||||
}))
|
||||
);
|
||||
|
||||
interface SelectedEventDataState {
|
||||
selectedEventData: { data: EventsSchema; selectedPoint: string } | undefined;
|
||||
setSelectedEventData: (data: EventsSchema, selectedPoint: string) => void;
|
||||
clearSelectedEventData: () => void;
|
||||
}
|
||||
|
||||
export const useSelectedEventData = create<SelectedEventDataState>()(
|
||||
immer((set) => ({
|
||||
selectedEventData: undefined,
|
||||
setSelectedEventData: (data, selectedPoint) => {
|
||||
set((state) => {
|
||||
state.selectedEventData = { data, selectedPoint };
|
||||
});
|
||||
},
|
||||
clearSelectedEventData: () => {
|
||||
set((state) => {
|
||||
state.selectedEventData = undefined;
|
||||
});
|
||||
},
|
||||
}))
|
||||
);
|
||||
|
||||
interface SelectedAssetState {
|
||||
selectedAsset: EventsSchema | undefined;
|
||||
setSelectedAsset: (EventData: EventsSchema) => void;
|
||||
clearSelectedAsset: () => void;
|
||||
}
|
||||
|
||||
export const useSelectedAsset = create<SelectedAssetState>()(
|
||||
immer((set) => ({
|
||||
selectedAsset: undefined,
|
||||
setSelectedAsset: (EventData) => {
|
||||
set((state) => {
|
||||
state.selectedAsset = EventData;
|
||||
});
|
||||
},
|
||||
clearSelectedAsset: () => {
|
||||
set((state) => {
|
||||
state.selectedAsset = undefined;
|
||||
});
|
||||
},
|
||||
}))
|
||||
);
|
||||
|
||||
interface SelectedProductState {
|
||||
selectedProduct: { productUuid: string; productName: string };
|
||||
setSelectedProduct: (productUuid: string, productName: string) => void;
|
||||
clearSelectedProduct: () => void;
|
||||
}
|
||||
|
||||
export const createSelectedProductStore = () => {
|
||||
return create<SelectedProductState>()(
|
||||
immer((set) => ({
|
||||
selectedProduct: { productUuid: '', productName: '' },
|
||||
setSelectedProduct: (productUuid, productName) => {
|
||||
set((state) => {
|
||||
state.selectedProduct.productUuid = productUuid;
|
||||
state.selectedProduct.productName = productName;
|
||||
});
|
||||
},
|
||||
clearSelectedProduct: () => {
|
||||
set((state) => {
|
||||
state.selectedProduct.productUuid = '';
|
||||
state.selectedProduct.productName = '';
|
||||
});
|
||||
},
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
export type SelectedProductType = ReturnType<typeof createSelectedProductStore>;
|
||||
|
||||
interface SelectedActionState {
|
||||
selectedAction: { actionId: string | null; actionName: string | null };
|
||||
setSelectedAction: (actionId: string, actionName: string) => void;
|
||||
clearSelectedAction: () => void;
|
||||
}
|
||||
|
||||
export const useSelectedAction = create<SelectedActionState>()(
|
||||
immer((set) => ({
|
||||
selectedAction: { actionId: null, actionName: null },
|
||||
setSelectedAction: (actionId, actionName) => {
|
||||
set((state) => {
|
||||
state.selectedAction.actionId = actionId;
|
||||
state.selectedAction.actionName = actionName;
|
||||
});
|
||||
},
|
||||
clearSelectedAction: () => {
|
||||
set((state) => {
|
||||
state.selectedAction.actionId = null;
|
||||
state.selectedAction.actionName = null;
|
||||
});
|
||||
},
|
||||
}))
|
||||
);
|
||||
|
||||
interface IsDraggingState {
|
||||
isDragging: "start" | "end" | null;
|
||||
setIsDragging: (state: "start" | "end" | null) => void;
|
||||
}
|
||||
|
||||
export const useIsDragging = create<IsDraggingState>()(
|
||||
immer((set) => ({
|
||||
isDragging: null,
|
||||
setIsDragging: (state) => {
|
||||
set((s) => {
|
||||
s.isDragging = state;
|
||||
});
|
||||
},
|
||||
}))
|
||||
);
|
||||
|
||||
interface IsRotatingState {
|
||||
isRotating: "start" | "end" | null;
|
||||
setIsRotating: (state: "start" | "end" | null) => void;
|
||||
}
|
||||
|
||||
export const useIsRotating = create<IsRotatingState>()(
|
||||
immer((set) => ({
|
||||
isRotating: null,
|
||||
setIsRotating: (state) => {
|
||||
set((s) => {
|
||||
s.isRotating = state;
|
||||
});
|
||||
},
|
||||
}))
|
||||
);
|
||||
|
||||
interface MainProductState {
|
||||
mainProduct: { productUuid: string; productName: string } | null;
|
||||
setMainProduct: (productUuid: string, productName: string) => void;
|
||||
clearMainProduct: () => void;
|
||||
}
|
||||
|
||||
export const useMainProduct = create<MainProductState>()(
|
||||
immer((set) => ({
|
||||
mainProduct: null,
|
||||
setMainProduct: (productUuid: string, productName: string) => {
|
||||
set((state) => {
|
||||
state.mainProduct = { productUuid, productName };
|
||||
});
|
||||
},
|
||||
clearMainProduct: () => {
|
||||
set((state) => {
|
||||
state.mainProduct = null;
|
||||
});
|
||||
},
|
||||
}))
|
||||
);
|
||||
|
||||
interface ComparisonProductState {
|
||||
comparisonProduct: { productUuid: string; productName: string } | null;
|
||||
setComparisonProduct: (productUuid: string, productName: string) => void;
|
||||
clearComparisonProduct: () => void;
|
||||
}
|
||||
|
||||
export const useComparisonProduct = create<ComparisonProductState>()(
|
||||
immer((set) => ({
|
||||
comparisonProduct: null,
|
||||
setComparisonProduct: (productUuid: string, productName: string) => {
|
||||
set((state) => {
|
||||
state.comparisonProduct = { productUuid, productName };
|
||||
});
|
||||
},
|
||||
clearComparisonProduct: () => {
|
||||
set((state) => {
|
||||
state.comparisonProduct = null;
|
||||
});
|
||||
},
|
||||
}))
|
||||
);
|
||||
219
app/src/store/simulation/useStorageUnitStore.ts
Normal file
219
app/src/store/simulation/useStorageUnitStore.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
import { create } from 'zustand';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
interface StorageUnitStore {
|
||||
storageUnits: StorageUnitStatus[];
|
||||
|
||||
addStorageUnit: (productUuid: string, storageUnit: StorageEventSchema) => void;
|
||||
removeStorageUnit: (modelUuid: string) => void;
|
||||
updateStorageUnit: (
|
||||
modelUuid: string,
|
||||
updates: Partial<Omit<StorageUnitStatus, 'modelUuid' | 'productUuid'>>
|
||||
) => void;
|
||||
clearStorageUnits: () => void;
|
||||
|
||||
setStorageUnitActive: (modelUuid: string, isActive: boolean) => void;
|
||||
setStorageUnitState: (modelUuid: string, newState: StorageUnitStatus['state']) => void;
|
||||
|
||||
updateCurrentLoad: (modelUuid: string, incrementBy: number) => void;
|
||||
|
||||
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||
|
||||
addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void;
|
||||
setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string; }[]) => void;
|
||||
getLastMaterial: (modelUuid: string) => { materialId: string; materialType: string; } | undefined;
|
||||
removeLastMaterial: (modelUuid: string) => { materialId: string; materialType: string; } | undefined;
|
||||
clearCurrentMaterials: (modelUuid: string) => void;
|
||||
|
||||
getStorageUnitById: (modelUuid: string) => StorageUnitStatus | undefined;
|
||||
getStorageUnitsByProduct: (productUuid: string) => StorageUnitStatus[];
|
||||
getStorageUnitsBystate: (state: string) => StorageUnitStatus[];
|
||||
getActiveStorageUnits: () => StorageUnitStatus[];
|
||||
getIdleStorageUnits: () => StorageUnitStatus[];
|
||||
getFullStorageUnits: () => StorageUnitStatus[];
|
||||
getEmptyStorageUnits: () => StorageUnitStatus[];
|
||||
}
|
||||
|
||||
export const createStorageUnitStore = () => {
|
||||
return create<StorageUnitStore>()(
|
||||
immer((set, get) => ({
|
||||
storageUnits: [],
|
||||
|
||||
addStorageUnit: (productUuid, storageUnit) => {
|
||||
set((state) => {
|
||||
const exists = state.storageUnits.some(s => s.modelUuid === storageUnit.modelUuid);
|
||||
if (!exists) {
|
||||
state.storageUnits.push({
|
||||
...storageUnit,
|
||||
productUuid,
|
||||
isActive: false,
|
||||
idleTime: 0,
|
||||
activeTime: 0,
|
||||
currentLoad: 0,
|
||||
currentMaterials: [],
|
||||
state: 'idle'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeStorageUnit: (modelUuid) => {
|
||||
set((state) => {
|
||||
state.storageUnits = state.storageUnits.filter(s => s.modelUuid !== modelUuid);
|
||||
});
|
||||
},
|
||||
|
||||
updateStorageUnit: (modelUuid, updates) => {
|
||||
set((state) => {
|
||||
const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
|
||||
if (unit) {
|
||||
Object.assign(unit, updates);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
clearStorageUnits: () => {
|
||||
set(() => ({
|
||||
storageUnits: [],
|
||||
}));
|
||||
},
|
||||
|
||||
setStorageUnitActive: (modelUuid, isActive) => {
|
||||
set((state) => {
|
||||
const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
|
||||
if (unit) {
|
||||
unit.isActive = isActive;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setStorageUnitState: (modelUuid, newState) => {
|
||||
set((state) => {
|
||||
const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
|
||||
if (unit) {
|
||||
unit.state = newState;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateCurrentLoad: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
|
||||
if (unit) {
|
||||
unit.currentLoad += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
|
||||
if (unit) {
|
||||
unit.activeTime += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const unit = state.storageUnits.find(s => s.modelUuid === modelUuid);
|
||||
if (unit) {
|
||||
unit.idleTime += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
addCurrentMaterial: (modelUuid, materialType, materialId) => {
|
||||
set((state) => {
|
||||
const storage = state.storageUnits.find((s) => s.modelUuid === modelUuid);
|
||||
if (storage) {
|
||||
storage.currentMaterials.push({ materialType, materialId });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setCurrentMaterials: (modelUuid, materials) => {
|
||||
set((state) => {
|
||||
const storage = state.storageUnits.find((s) => s.modelUuid === modelUuid);
|
||||
if (storage) {
|
||||
storage.currentMaterials = materials;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getLastMaterial: (modelUuid) => {
|
||||
let removedMaterial: { materialId: string; materialType: string; } | undefined;
|
||||
set((state) => {
|
||||
const storage = state.storageUnits.find((s) => s.modelUuid === modelUuid);
|
||||
if (storage) {
|
||||
if (storage.currentMaterials.length > 0) {
|
||||
const material = storage.currentMaterials[storage.currentMaterials.length - 1];
|
||||
if (material) {
|
||||
removedMaterial = { materialId: material.materialId, materialType: material.materialType };
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return removedMaterial;
|
||||
},
|
||||
|
||||
removeLastMaterial: (modelUuid) => {
|
||||
let removedMaterial: { materialId: string; materialType: string; } | undefined;
|
||||
set((state) => {
|
||||
const storage = state.storageUnits.find((s) => s.modelUuid === modelUuid);
|
||||
if (storage) {
|
||||
if (storage.currentMaterials.length > 0) {
|
||||
const material = storage.currentMaterials.pop();
|
||||
if (material) {
|
||||
removedMaterial = { materialId: material.materialId, materialType: material.materialType };
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return removedMaterial;
|
||||
},
|
||||
|
||||
clearCurrentMaterials: (modelUuid) => {
|
||||
set((state) => {
|
||||
const storage = state.storageUnits.find((s) => s.modelUuid === modelUuid);
|
||||
if (storage) {
|
||||
storage.currentMaterials = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getStorageUnitById: (modelUuid) => {
|
||||
return get().storageUnits.find(s => s.modelUuid === modelUuid);
|
||||
},
|
||||
|
||||
getStorageUnitsByProduct: (productUuid) => {
|
||||
return get().storageUnits.filter(s => s.productUuid === productUuid);
|
||||
},
|
||||
|
||||
getStorageUnitsBystate: (state) => {
|
||||
return get().storageUnits.filter(s => s.state === state);
|
||||
},
|
||||
|
||||
getActiveStorageUnits: () => {
|
||||
return get().storageUnits.filter(s => s.isActive);
|
||||
},
|
||||
|
||||
getIdleStorageUnits: () => {
|
||||
return get().storageUnits.filter(s => !s.isActive && s.state === 'idle');
|
||||
},
|
||||
|
||||
getFullStorageUnits: () => {
|
||||
return get().storageUnits.filter(
|
||||
s => s.currentLoad >= s.point.action.storageCapacity
|
||||
);
|
||||
},
|
||||
|
||||
getEmptyStorageUnits: () => {
|
||||
return get().storageUnits.filter(s => s.currentLoad === 0);
|
||||
},
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
export type StorageUnitStoreType = ReturnType<typeof createStorageUnitStore>;
|
||||
257
app/src/store/simulation/useVehicleStore.ts
Normal file
257
app/src/store/simulation/useVehicleStore.ts
Normal file
@@ -0,0 +1,257 @@
|
||||
import { create } from "zustand";
|
||||
import { immer } from "zustand/middleware/immer";
|
||||
|
||||
interface VehiclesStore {
|
||||
vehicles: VehicleStatus[];
|
||||
|
||||
addVehicle: (productUuid: string, event: VehicleEventSchema) => void;
|
||||
removeVehicle: (modelUuid: string) => void;
|
||||
updateVehicle: (
|
||||
modelUuid: string,
|
||||
updates: Partial<Omit<VehicleStatus, "modelUuid" | "productUuid">>
|
||||
) => void;
|
||||
clearvehicles: () => void;
|
||||
|
||||
setVehicleActive: (modelUuid: string, isActive: boolean) => void;
|
||||
setVehiclePicking: (modelUuid: string, isPicking: boolean) => void;
|
||||
updateSteeringAngle: (modelUuid: string, steeringAngle: number) => void;
|
||||
incrementVehicleLoad: (modelUuid: string, incrementBy: number) => void;
|
||||
decrementVehicleLoad: (modelUuid: string, decrementBy: number) => void;
|
||||
setVehicleLoad: (modelUuid: string, load: number) => void;
|
||||
setVehicleState: (
|
||||
modelUuid: string,
|
||||
newState: VehicleStatus["state"]
|
||||
) => void;
|
||||
addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void;
|
||||
setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string; }[]) => void;
|
||||
removeLastMaterial: (modelUuid: string) => { materialId: string; materialType: string; } | undefined;
|
||||
getLastMaterial: (modelUuid: string) => { materialId: string; materialType: string; } | undefined;
|
||||
clearCurrentMaterials: (modelUuid: string) => void;
|
||||
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||
resetTime: (modelUuid: string) => void;
|
||||
|
||||
getVehicleById: (modelUuid: string) => VehicleStatus | undefined;
|
||||
getVehiclesByProduct: (productUuid: string) => VehicleStatus[];
|
||||
getVehiclesByState: (state: string) => VehicleStatus[];
|
||||
getActiveVehicles: () => VehicleStatus[];
|
||||
}
|
||||
|
||||
export const createVehicleStore = () => {
|
||||
return create<VehiclesStore>()(
|
||||
immer((set, get) => ({
|
||||
vehicles: [],
|
||||
|
||||
addVehicle: (productUuid, event) => {
|
||||
set((state) => {
|
||||
const exists = state.vehicles.some((v) => v.modelUuid === event.modelUuid);
|
||||
if (!exists) {
|
||||
state.vehicles.push({
|
||||
...event,
|
||||
productUuid,
|
||||
isActive: false,
|
||||
isPicking: false,
|
||||
idleTime: 0,
|
||||
activeTime: 0,
|
||||
currentLoad: 0,
|
||||
currentMaterials: [],
|
||||
distanceTraveled: 0,
|
||||
state: 'idle'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeVehicle: (modelUuid) => {
|
||||
set((state) => {
|
||||
state.vehicles = state.vehicles.filter(
|
||||
(v) => v.modelUuid !== modelUuid
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
updateVehicle: (modelUuid, updates) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
Object.assign(vehicle, updates);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
clearvehicles: () => {
|
||||
set((state) => {
|
||||
state.vehicles = [];
|
||||
});
|
||||
},
|
||||
|
||||
setVehicleActive: (modelUuid, isActive) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.isActive = isActive;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setVehiclePicking: (modelUuid, isPicking) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.isPicking = isPicking;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateSteeringAngle: (modelUuid, steeringAngle) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.point.action.steeringAngle = steeringAngle;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementVehicleLoad: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.currentLoad += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
decrementVehicleLoad: (modelUuid, decrementBy) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.currentLoad -= decrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setVehicleLoad: (modelUuid, load) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.currentLoad = load;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setVehicleState: (modelUuid, newState) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.state = newState;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
addCurrentMaterial: (modelUuid, materialType, materialId) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.currentMaterials.push({ materialType, materialId });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setCurrentMaterials: (modelUuid, materials) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.currentMaterials = materials;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
removeLastMaterial: (modelUuid) => {
|
||||
let removedMaterial: { materialId: string; materialType: string; } | undefined;
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
if (vehicle.currentMaterials.length > 0) {
|
||||
const material = vehicle.currentMaterials.pop();
|
||||
if (material) {
|
||||
removedMaterial = { materialId: material.materialId, materialType: material.materialType };
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return removedMaterial;
|
||||
},
|
||||
|
||||
getLastMaterial: (modelUuid) => {
|
||||
let removedMaterial: { materialId: string; materialType: string; } | undefined;
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
if (vehicle.currentMaterials.length > 0) {
|
||||
removedMaterial = {
|
||||
materialId: vehicle.currentMaterials[vehicle.currentMaterials.length - 1].materialId,
|
||||
materialType: vehicle.currentMaterials[vehicle.currentMaterials.length - 1].materialType
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
return removedMaterial;
|
||||
},
|
||||
|
||||
clearCurrentMaterials: (modelUuid) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.currentMaterials = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.activeTime += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.idleTime += incrementBy;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
resetTime: (modelUuid) => {
|
||||
set((state) => {
|
||||
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
if (vehicle) {
|
||||
vehicle.activeTime = 0;
|
||||
vehicle.idleTime = 0;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getVehicleById: (modelUuid) => {
|
||||
return get().vehicles.find((v) => v.modelUuid === modelUuid);
|
||||
},
|
||||
|
||||
getVehiclesByProduct: (productUuid) => {
|
||||
return get().vehicles.filter((v) => v.productUuid === productUuid);
|
||||
},
|
||||
|
||||
getVehiclesByState: (state) => {
|
||||
return get().vehicles.filter((v) => v.state === state);
|
||||
},
|
||||
|
||||
getActiveVehicles: () => {
|
||||
return get().vehicles.filter((v) => v.isActive);
|
||||
},
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
export type VehicleStoreType = ReturnType<typeof createVehicleStore>;
|
||||
42
app/src/store/useModuleStore.ts
Normal file
42
app/src/store/useModuleStore.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
interface ModuleStore {
|
||||
activeModule: string;
|
||||
setActiveModule: (module: string) => void;
|
||||
}
|
||||
|
||||
const useModuleStore = create<ModuleStore>((set) => ({
|
||||
activeModule: "builder", // Initial state
|
||||
setActiveModule: (module) => set({ activeModule: module }), // Update state
|
||||
}));
|
||||
|
||||
export default useModuleStore;
|
||||
|
||||
// New store for subModule
|
||||
|
||||
type SubModule = 'properties' | 'simulations' | 'mechanics' | 'analysis' | 'zoneProperties';
|
||||
|
||||
interface SubModuleStore {
|
||||
subModule: SubModule;
|
||||
setSubModule: (subModule: SubModule) => void;
|
||||
}
|
||||
|
||||
const useSubModuleStore = create<SubModuleStore>((set) => ({
|
||||
subModule: "properties", // Initial subModule state
|
||||
setSubModule: (value) => set({ subModule: value }), // Update subModule state
|
||||
}));
|
||||
|
||||
export { useSubModuleStore };
|
||||
|
||||
interface ThreeDState {
|
||||
toggleThreeD: boolean;
|
||||
setToggleThreeD: (value: boolean) => void;
|
||||
}
|
||||
|
||||
// Create the Zustand store
|
||||
const useThreeDStore = create<ThreeDState>((set) => ({
|
||||
toggleThreeD: true, // Initial state
|
||||
setToggleThreeD: (value) => set({ toggleThreeD: value }), // Action to update the state
|
||||
}));
|
||||
|
||||
export { useThreeDStore };
|
||||
49
app/src/store/usePlayButtonStore.ts
Normal file
49
app/src/store/usePlayButtonStore.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
type PlayButtonStore = {
|
||||
isPlaying: boolean; // Updated state name to reflect the play/pause status more clearly
|
||||
setIsPlaying: (value: boolean) => void; // Updated setter function name for clarity
|
||||
};
|
||||
type PauseButtonStore = {
|
||||
isPaused: boolean; // Updated state name to reflect the play/pause status more clearly
|
||||
setIsPaused: (value: boolean) => void; // Updated setter function name for clarity
|
||||
};
|
||||
type ResetButtonStore = {
|
||||
isReset: boolean; // Updated state name to reflect the play/pause status more clearly
|
||||
setReset: (value: boolean) => void; // Updated setter function name for clarity
|
||||
};
|
||||
interface AnimationSpeedState {
|
||||
speed: number;
|
||||
setSpeed: (value: number) => void;
|
||||
}
|
||||
|
||||
export const usePlayButtonStore = create<PlayButtonStore>((set) => ({
|
||||
isPlaying: false, // Default state for play/pause
|
||||
setIsPlaying: (value) => set({ isPlaying: value }), // Update isPlaying state
|
||||
}));
|
||||
export const useResetButtonStore = create<ResetButtonStore>((set) => ({
|
||||
isReset: false, // Default state for play/pause
|
||||
setReset: (value) => set({ isReset: value }), // Update isPlaying state
|
||||
}));
|
||||
export const usePauseButtonStore = create<PauseButtonStore>((set) => ({
|
||||
isPaused: false, // Default state for play/pause
|
||||
setIsPaused: (value) => set({ isPaused: value }), // Update isPlaying state
|
||||
}));
|
||||
export const useAnimationPlaySpeed = create<AnimationSpeedState>((set) => ({
|
||||
speed: 1,
|
||||
setSpeed: (value) => set({ speed: value }),
|
||||
}));
|
||||
|
||||
interface CameraModeState {
|
||||
walkMode: boolean;
|
||||
setWalkMode: (enabled: boolean) => void;
|
||||
toggleWalkMode: () => void;
|
||||
}
|
||||
|
||||
const useCameraModeStore = create<CameraModeState>((set) => ({
|
||||
walkMode: false,
|
||||
setWalkMode: (enabled) => set({ walkMode: enabled }),
|
||||
toggleWalkMode: () => set((state) => ({ walkMode: !state.walkMode })),
|
||||
}));
|
||||
|
||||
export default useCameraModeStore;
|
||||
51
app/src/store/useTemplateStore.ts
Normal file
51
app/src/store/useTemplateStore.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
export interface Widget {
|
||||
id: string;
|
||||
type: string;
|
||||
title: string;
|
||||
panel: string;
|
||||
data: any;
|
||||
}
|
||||
|
||||
export interface Template {
|
||||
id: string;
|
||||
name: string;
|
||||
panelOrder: string[];
|
||||
widgets: Widget[];
|
||||
floatingWidget: any[]; // Fixed empty array type
|
||||
widgets3D: any[]; // Fixed empty array type
|
||||
snapshot?: string | null;
|
||||
}
|
||||
|
||||
interface TemplateStore {
|
||||
templates: Template[];
|
||||
addTemplate: (template: Template) => void;
|
||||
setTemplates: (templates: Template[]) => void; // Changed from `setTemplate`
|
||||
removeTemplate: (id: string) => void;
|
||||
}
|
||||
|
||||
export const useTemplateStore = create<TemplateStore>((set) => ({
|
||||
templates: [],
|
||||
|
||||
// Add a new template to the list
|
||||
addTemplate: (template) =>
|
||||
set((state) => ({
|
||||
templates: [...state.templates, template],
|
||||
})),
|
||||
|
||||
// Set (replace) the templates list with a new array
|
||||
setTemplates: (templates) =>
|
||||
set(() => ({
|
||||
templates, // Ensures no duplication
|
||||
})),
|
||||
|
||||
// Remove a template by ID
|
||||
removeTemplate: (id) =>
|
||||
set((state) => ({
|
||||
templates: state.templates.filter((t) => t.id !== id),
|
||||
})),
|
||||
}));
|
||||
|
||||
export default useTemplateStore;
|
||||
|
||||
11
app/src/store/useThemeStore.ts
Normal file
11
app/src/store/useThemeStore.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
interface ThemeState {
|
||||
themeColor: string[]; // This should be an array of strings
|
||||
setThemeColor: (colors: string[]) => void; // This function will accept an array of strings
|
||||
}
|
||||
|
||||
export const useThemeStore = create<ThemeState>((set) => ({
|
||||
themeColor: ["#5c87df", "#EEEEFE", "#969BA7"],
|
||||
setThemeColor: (colors) => set({ themeColor: colors }),
|
||||
}));
|
||||
26
app/src/store/useUIToggleStore.ts
Normal file
26
app/src/store/useUIToggleStore.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
interface ToggleState {
|
||||
toggleUILeft: boolean;
|
||||
toggleUIRight: boolean;
|
||||
setToggleUI: (value1: boolean, value2: boolean) => void;
|
||||
}
|
||||
|
||||
export const useToggleStore = create<ToggleState>((set) => ({
|
||||
toggleUILeft: true,
|
||||
toggleUIRight: false,
|
||||
setToggleUI: (value1: boolean, value2: boolean) => {
|
||||
set({ toggleUILeft: value1, toggleUIRight: value2 });
|
||||
},
|
||||
}));
|
||||
|
||||
interface PlayerState {
|
||||
hidePlayer: boolean;
|
||||
setHidePlayer: (hide: boolean) => void;
|
||||
}
|
||||
|
||||
// Create the Zustand store
|
||||
export const usePlayerStore = create<PlayerState>((set) => ({
|
||||
hidePlayer: false, // initial state
|
||||
setHidePlayer: (hide) => set({ hidePlayer: hide }), // state updater
|
||||
}));
|
||||
35
app/src/store/useWidgetStore.ts
Normal file
35
app/src/store/useWidgetStore.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
export interface Widget {
|
||||
id: string;
|
||||
type: string; // Can be chart type or "progress"
|
||||
panel: "top" | "bottom" | "left" | "right";
|
||||
title: string;
|
||||
fontFamily?: string;
|
||||
fontSize?: string;
|
||||
fontWeight?: string;
|
||||
data?: any;
|
||||
Data?:any;
|
||||
}
|
||||
|
||||
interface WidgetStore {
|
||||
draggedAsset: Widget | null; // The currently dragged widget asset
|
||||
widgets: Widget[]; // List of all widgets
|
||||
selectedChartId: any;
|
||||
setDraggedAsset: (asset: Widget | null) => void; // Setter for draggedAsset
|
||||
addWidget: (widget: Widget) => void; // Add a new widget
|
||||
setWidgets: (widgets: Widget[]) => void; // Replace the entire widgets array
|
||||
setSelectedChartId: (widget: any | null) => void; // Set the selected chart/widget
|
||||
}
|
||||
|
||||
// Create the store with Zustand
|
||||
export const useWidgetStore = create<WidgetStore>((set) => ({
|
||||
draggedAsset: null,
|
||||
widgets: [],
|
||||
selectedChartId: null, // Initialize as null, not as an array
|
||||
setDraggedAsset: (asset) => set({ draggedAsset: asset }),
|
||||
addWidget: (widget) =>
|
||||
set((state) => ({ widgets: [...state.widgets, widget] })),
|
||||
setWidgets: (widgets) => set({ widgets }),
|
||||
setSelectedChartId: (widget) => set({ selectedChartId: widget }),
|
||||
}));
|
||||
53
app/src/store/visualization/useChartStore.ts
Normal file
53
app/src/store/visualization/useChartStore.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
interface Measurement {
|
||||
name: string;
|
||||
fields: string;
|
||||
}
|
||||
|
||||
interface MeasurementStore {
|
||||
measurements: Record<string, Measurement>; // Change array to Record<string, Measurement>
|
||||
interval: number;
|
||||
duration: string;
|
||||
name: string;
|
||||
header: string;
|
||||
flotingDuration: string;
|
||||
flotingMeasurements: Record<string, Measurement>; // Change array to Record<string, Measurement>
|
||||
setMeasurements: (newMeasurements: Record<string, Measurement>) => void;
|
||||
updateDuration: (newDuration: string) => void;
|
||||
updateName: (newName: string) => void;
|
||||
updateHeader: (newHeader: string) => void;
|
||||
updateFlotingDuration: (newFlotingDuration: string) => void;
|
||||
setFlotingMeasurements: (newFlotingMeasurements: Record<string, Measurement>) => void;
|
||||
}
|
||||
|
||||
const useChartStore = create<MeasurementStore>((set) => ({
|
||||
measurements: {}, // Initialize as an empty object
|
||||
interval: 1000,
|
||||
duration: "1h",
|
||||
name:'',
|
||||
header:'',
|
||||
flotingDuration: "1h",
|
||||
flotingMeasurements: {},
|
||||
|
||||
setMeasurements: (newMeasurements) =>
|
||||
set(() => ({ measurements: newMeasurements })),
|
||||
|
||||
updateDuration: (newDuration) =>
|
||||
set(() => ({ duration: newDuration })),
|
||||
|
||||
updateName: (newName) =>
|
||||
set(() => ({ name: newName })),
|
||||
|
||||
updateHeader: (newHeader) =>
|
||||
set(() => ({ header: newHeader })),
|
||||
|
||||
updateFlotingDuration: (newFlotingDuration) =>
|
||||
set(() => ({ flotingDuration: newFlotingDuration })),
|
||||
|
||||
setFlotingMeasurements: (newFlotingMeasurements) =>
|
||||
set(() => ({ flotingMeasurements: newFlotingMeasurements })),
|
||||
}));
|
||||
|
||||
export default useChartStore;
|
||||
|
||||
200
app/src/store/visualization/useDroppedObjectsStore.ts
Normal file
200
app/src/store/visualization/useDroppedObjectsStore.ts
Normal file
@@ -0,0 +1,200 @@
|
||||
import { create } from "zustand";
|
||||
import { useSocketStore } from "../builder/store";
|
||||
import useChartStore from "./useChartStore";
|
||||
|
||||
type DroppedObject = {
|
||||
className: string;
|
||||
id: string;
|
||||
position: {
|
||||
top: number | "auto";
|
||||
left: number | "auto";
|
||||
right: number | "auto";
|
||||
bottom: number | "auto";
|
||||
};
|
||||
value?: number;
|
||||
per?: string;
|
||||
header?: string;
|
||||
Data: {};
|
||||
};
|
||||
|
||||
type Zone = {
|
||||
zoneName: string;
|
||||
zoneUuid: string;
|
||||
objects: DroppedObject[];
|
||||
};
|
||||
|
||||
type DroppedObjectsState = {
|
||||
zones: Record<string, Zone>;
|
||||
setZone: (zoneName: string, zoneUuid: string) => void;
|
||||
addObject: (zoneName: string, newObject: DroppedObject) => void;
|
||||
updateObjectPosition: (
|
||||
zoneName: string,
|
||||
index: number,
|
||||
newPosition: {
|
||||
top: number | "auto";
|
||||
left: number | "auto";
|
||||
right: number | "auto";
|
||||
bottom: number | "auto";
|
||||
}
|
||||
) => void;
|
||||
deleteObject: (zoneName: string, id: string) => void; // Add this line
|
||||
duplicateObject: (zoneName: string, index: number, projectId?: string) => void; // Add this line
|
||||
};
|
||||
|
||||
export const useDroppedObjectsStore = create<DroppedObjectsState>((set) => ({
|
||||
zones: {},
|
||||
|
||||
setZone: (zoneName: string, zoneUuid: string) =>
|
||||
set((state) => ({
|
||||
zones: {
|
||||
[zoneName]: state.zones[zoneName] || { zoneName, zoneUuid, objects: [] }, // Keep existing zone if it exists
|
||||
},
|
||||
})),
|
||||
|
||||
addObject: (zoneName: string, newObject: DroppedObject) =>
|
||||
set((state) => ({
|
||||
zones: {
|
||||
...state.zones,
|
||||
[zoneName]: {
|
||||
...state.zones[zoneName],
|
||||
objects: [...state.zones[zoneName].objects, newObject], // Append new object
|
||||
},
|
||||
},
|
||||
})),
|
||||
|
||||
updateObjectPosition: (zoneName, index, newPosition) =>
|
||||
set((state) => {
|
||||
const zone = state.zones[zoneName];
|
||||
if (!zone) return state;
|
||||
return {
|
||||
zones: {
|
||||
[zoneName]: {
|
||||
...zone,
|
||||
objects: zone.objects.map((obj, i) =>
|
||||
i === index ? { ...obj, position: newPosition } : obj
|
||||
),
|
||||
},
|
||||
},
|
||||
};
|
||||
}),
|
||||
|
||||
deleteObject: (zoneName: string, id: string) =>
|
||||
set((state) => {
|
||||
const zone = state.zones[zoneName];
|
||||
|
||||
if (!zone) return state;
|
||||
return {
|
||||
zones: {
|
||||
[zoneName]: {
|
||||
...zone,
|
||||
objects: zone.objects.filter((obj) => obj.id !== id), // Remove object at the given index
|
||||
},
|
||||
},
|
||||
};
|
||||
}),
|
||||
duplicateObject: async (zoneName: string, index: number, projectId?: string) => {
|
||||
const state = useDroppedObjectsStore.getState(); // Get the current state
|
||||
const zone = state.zones[zoneName];
|
||||
let socketState = useSocketStore.getState();
|
||||
let iotData = useChartStore.getState();
|
||||
let visualizationSocket = socketState.visualizationSocket;
|
||||
let iotMeasurements = iotData.flotingMeasurements;
|
||||
let iotDuration = iotData.flotingDuration;
|
||||
let iotHeader = iotData.header
|
||||
|
||||
if (!zone) return;
|
||||
|
||||
const originalObject = zone.objects[index];
|
||||
if (!originalObject) return;
|
||||
|
||||
const email = localStorage.getItem("email") || "";
|
||||
const organization = email?.split("@")[1]?.split(".")[0];
|
||||
const userId = localStorage.getItem("userId");
|
||||
|
||||
// Create a shallow copy of the object with a unique ID and slightly adjusted position
|
||||
const duplicatedObject: DroppedObject = {
|
||||
...originalObject,
|
||||
Data: {
|
||||
measurements: iotMeasurements,
|
||||
duration: iotDuration,
|
||||
},
|
||||
header: iotHeader,
|
||||
id: `${originalObject.id}-copy-${Date.now()}`, // Unique ID
|
||||
position: {
|
||||
...originalObject.position,
|
||||
top:
|
||||
typeof originalObject.position.top === "number"
|
||||
? originalObject.position.top + 20 // Offset vertically
|
||||
: originalObject.position.top,
|
||||
left:
|
||||
typeof originalObject.position.left === "number"
|
||||
? originalObject.position.left + 20 // Offset horizontally
|
||||
: originalObject.position.left,
|
||||
},
|
||||
};
|
||||
console.log("duplicated object", duplicatedObject);
|
||||
|
||||
let duplicateFloatingWidget = {
|
||||
organization: organization,
|
||||
widget: duplicatedObject,
|
||||
zoneUuid: zone.zoneUuid,
|
||||
index: index,
|
||||
projectId, userId
|
||||
|
||||
};
|
||||
|
||||
if (visualizationSocket) {
|
||||
visualizationSocket.emit(
|
||||
"v1:viz-float:addDuplicate",
|
||||
duplicateFloatingWidget
|
||||
);
|
||||
}
|
||||
useDroppedObjectsStore.setState((state) => ({
|
||||
zones: {
|
||||
...state.zones,
|
||||
[zoneName]: {
|
||||
...state.zones[zoneName],
|
||||
objects: [...state.zones[zoneName].objects, duplicatedObject], // Append duplicated object
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
// Make async API call outside of Zustand set function
|
||||
// let response = await addingFloatingWidgets(
|
||||
// zone.zoneUuid,
|
||||
// organization,
|
||||
// duplicatedObject
|
||||
// );
|
||||
|
||||
// if (response.message === "FloatWidget created successfully") {
|
||||
// Update the state inside `set`
|
||||
|
||||
// }
|
||||
},
|
||||
}));
|
||||
|
||||
export interface DroppedObjects {
|
||||
header: string;
|
||||
id: string;
|
||||
Data: {};
|
||||
value: string | number; // ✅ Allows both numbers and formatted strings
|
||||
per: string;
|
||||
className: string;
|
||||
position: { top: number; left: number; right: number; bottom: number }; // ✅ Ensures position is a tuple
|
||||
}
|
||||
|
||||
export interface Zones {
|
||||
zoneName: string;
|
||||
zoneUuid: string;
|
||||
objects: DroppedObject[];
|
||||
}
|
||||
|
||||
export const use3DWidget = create<any>((set: any) => ({
|
||||
widgets3D: [],
|
||||
setWidgets3D: (x: any) => set({ widgets3D: x }),
|
||||
}));
|
||||
|
||||
export const useFloatingWidget = create<any>((set: any) => ({
|
||||
floatingWidget: [],
|
||||
setFloatingWidget: (x: any) => set({ floatingWidget: x }),
|
||||
}));
|
||||
122
app/src/store/visualization/useZone3DWidgetStore.ts
Normal file
122
app/src/store/visualization/useZone3DWidgetStore.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
type WidgetData = {
|
||||
id: string;
|
||||
type: string;
|
||||
position: [number, number, number];
|
||||
rotation?: [number, number, number];
|
||||
tempPosition?: [number, number, number];
|
||||
};
|
||||
|
||||
type ZoneWidgetStore = {
|
||||
zoneWidgetData: Record<string, WidgetData[]>;
|
||||
setZoneWidgetData: (zoneUuid: string, widgets: WidgetData[]) => void;
|
||||
addWidget: (zoneUuid: string, widget: WidgetData) => void;
|
||||
tempWidget: (zoneUuid: string, widget: WidgetData) => void;
|
||||
updateWidgetPosition: (zoneUuid: string, widgetId: string, newPosition: [number, number, number]) => void;
|
||||
tempWidgetPosition: (zoneUuid: string, widgetId: string, newPosition: [number, number, number]) => void;
|
||||
updateWidgetRotation: (zoneUuid: string, widgetId: string, newRotation: [number, number, number]) => void;
|
||||
};
|
||||
|
||||
export const useZoneWidgetStore = create<ZoneWidgetStore>((set) => ({
|
||||
zoneWidgetData: {},
|
||||
|
||||
setZoneWidgetData: (zoneUuid: string, widgets: WidgetData[]) =>
|
||||
set((state: ZoneWidgetStore) => ({
|
||||
zoneWidgetData: { ...state.zoneWidgetData, [zoneUuid]: widgets },
|
||||
})),
|
||||
|
||||
addWidget: (zoneUuid: string, widget: WidgetData) =>
|
||||
set((state: ZoneWidgetStore) => ({
|
||||
zoneWidgetData: {
|
||||
...state.zoneWidgetData,
|
||||
[zoneUuid]: [...(state.zoneWidgetData[zoneUuid] || []), { ...widget, rotation: widget.rotation || [0, 0, 0] }],
|
||||
},
|
||||
})),
|
||||
tempWidget: (zoneUuid: string, widget: WidgetData) =>
|
||||
set((state: ZoneWidgetStore) => ({
|
||||
zoneWidgetData: {
|
||||
...state.zoneWidgetData,
|
||||
[zoneUuid]: [...(state.zoneWidgetData[zoneUuid] || []), { ...widget, rotation: widget.rotation || [0, 0, 0] }],
|
||||
},
|
||||
})),
|
||||
|
||||
updateWidgetPosition: (zoneUuid: string, widgetId: string, newPosition: [number, number, number]) =>
|
||||
set((state: ZoneWidgetStore) => {
|
||||
const widgets = state.zoneWidgetData[zoneUuid] || [];
|
||||
return {
|
||||
zoneWidgetData: {
|
||||
...state.zoneWidgetData,
|
||||
[zoneUuid]: widgets.map((widget: WidgetData) =>
|
||||
widget.id === widgetId ? { ...widget, position: newPosition } : widget
|
||||
),
|
||||
},
|
||||
};
|
||||
}),
|
||||
tempWidgetPosition: (zoneUuid: string, widgetId: string, newPosition: [number, number, number]) =>
|
||||
set((state: ZoneWidgetStore) => {
|
||||
const widgets = state.zoneWidgetData[zoneUuid] || [];
|
||||
return {
|
||||
zoneWidgetData: {
|
||||
...state.zoneWidgetData,
|
||||
[zoneUuid]: widgets.map((widget: WidgetData) =>
|
||||
widget.id === widgetId ? { ...widget, position: newPosition } : widget
|
||||
),
|
||||
},
|
||||
};
|
||||
}),
|
||||
|
||||
updateWidgetRotation: (zoneUuid: string, widgetId: string, newRotation: [number, number, number]) =>
|
||||
set((state: ZoneWidgetStore) => {
|
||||
const widgets = state.zoneWidgetData[zoneUuid] || [];
|
||||
return {
|
||||
zoneWidgetData: {
|
||||
...state.zoneWidgetData,
|
||||
[zoneUuid]: widgets.map((widget: WidgetData) =>
|
||||
widget.id === widgetId ? { ...widget, rotation: newRotation } : widget
|
||||
),
|
||||
},
|
||||
};
|
||||
}),
|
||||
}));
|
||||
|
||||
|
||||
interface RightClickStore {
|
||||
rightClickSelected: string | null;
|
||||
setRightClickSelected: (x: string | null) => void;
|
||||
}
|
||||
|
||||
export const useRightClickSelected = create<RightClickStore>((set) => ({
|
||||
rightClickSelected: null, // Default to null
|
||||
setRightClickSelected: (x) => set({ rightClickSelected: x }),
|
||||
}));
|
||||
|
||||
export const useTopData = create<any>((set: any) => ({
|
||||
top: 0,
|
||||
setTop: (x: any) => set({ top: x }),
|
||||
}));
|
||||
|
||||
export const useLeftData = create<any>((set: any) => ({
|
||||
left: 0,
|
||||
setLeft: (x: any) => set({ left: x }),
|
||||
}));
|
||||
|
||||
interface RightSelectStore {
|
||||
rightSelect: string | null;
|
||||
setRightSelect: (x: string | null) => void;
|
||||
}
|
||||
|
||||
export const useRightSelected = create<RightSelectStore>((set) => ({
|
||||
rightSelect: null, // Default state is null
|
||||
setRightSelect: (x) => set({ rightSelect: x }),
|
||||
}));
|
||||
|
||||
interface EditWidgetOptionsStore {
|
||||
editWidgetOptions: boolean;
|
||||
setEditWidgetOptions: (value: boolean) => void;
|
||||
}
|
||||
|
||||
export const useEditWidgetOptionsStore = create<EditWidgetOptionsStore>((set) => ({
|
||||
editWidgetOptions: false, // Initial state
|
||||
setEditWidgetOptions: (value: boolean) => set({ editWidgetOptions: value }),
|
||||
}));
|
||||
68
app/src/store/visualization/useZoneStore.ts
Normal file
68
app/src/store/visualization/useZoneStore.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
type Side = "top" | "bottom" | "left" | "right";
|
||||
|
||||
interface Widget {
|
||||
id: string;
|
||||
type: string;
|
||||
title: string;
|
||||
panel: Side;
|
||||
data: any;
|
||||
}
|
||||
|
||||
interface SelectedZoneState {
|
||||
zoneName: string;
|
||||
activeSides: Side[];
|
||||
panelOrder: Side[];
|
||||
points: []
|
||||
lockedPanels: Side[];
|
||||
zoneUuid: string;
|
||||
zoneViewPortTarget: number[];
|
||||
zoneViewPortPosition: number[];
|
||||
widgets: Widget[];
|
||||
}
|
||||
|
||||
interface SelectedZoneStore {
|
||||
selectedZone: SelectedZoneState;
|
||||
setSelectedZone: (
|
||||
zone:
|
||||
| Partial<SelectedZoneState>
|
||||
| ((prev: SelectedZoneState) => SelectedZoneState)
|
||||
) => void;
|
||||
clearSelectedZone: () => void;
|
||||
}
|
||||
|
||||
export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
|
||||
selectedZone: {
|
||||
zoneName: "",
|
||||
activeSides: [],
|
||||
panelOrder: [],
|
||||
lockedPanels: [],
|
||||
points: [],
|
||||
zoneUuid: "",
|
||||
zoneViewPortTarget: [],
|
||||
zoneViewPortPosition: [],
|
||||
widgets: [],
|
||||
},
|
||||
setSelectedZone: (zone) =>
|
||||
set((state) => ({
|
||||
selectedZone:
|
||||
typeof zone === "function"
|
||||
? zone(state.selectedZone)
|
||||
: { ...state.selectedZone, ...zone },
|
||||
})),
|
||||
clearSelectedZone: () =>
|
||||
set(() => ({
|
||||
selectedZone: {
|
||||
zoneName: "",
|
||||
activeSides: [],
|
||||
panelOrder: [],
|
||||
lockedPanels: [],
|
||||
points: [],
|
||||
zoneUuid: "",
|
||||
zoneViewPortTarget: [],
|
||||
zoneViewPortPosition: [],
|
||||
widgets: [],
|
||||
},
|
||||
})),
|
||||
}));
|
||||
Reference in New Issue
Block a user