feat: Enhance conveyor and material handling with pause functionality and state management

This commit is contained in:
2025-05-06 19:12:58 +05:30
parent 815a9a94ca
commit 53912b2597
17 changed files with 202 additions and 69 deletions

View File

@@ -28,22 +28,11 @@ function RoboticArmMechanics() {
selectedEventData.data.modelUuid, selectedEventData.data.modelUuid,
selectedEventData.selectedPoint selectedEventData.selectedPoint
) as RoboticArmPointSchema | undefined; ) as RoboticArmPointSchema | undefined;
const action = getActionByUuid(selectedProduct.productId, selectedAction.actionId) as RoboticArmPointSchema["actions"][0] | undefined; if (point?.actions) {
if (action) { setSelectedPointData(point);
if (point?.actions) { if (point.actions.length > 0) {
setSelectedPointData(point); setActiveOption(point.actions[0].actionType as "default" | "pickAndPlace");
if (point.actions.length > 0 && action) { setSelectedAction(point.actions[0].actionUuid, point.actions[0].actionName);
setActiveOption(action.actionType as "default" | "pickAndPlace");
setSelectedAction(selectedAction.actionId, selectedAction.actionName);
}
}
} else {
if (point?.actions) {
setSelectedPointData(point);
if (point.actions.length > 0) {
setActiveOption(point.actions[0].actionType as "default" | "pickAndPlace");
setSelectedAction(point.actions[0].actionUuid, point.actions[0].actionName);
}
} }
} }
} else { } else {

View File

@@ -38,6 +38,14 @@ const SimulationPlayer: React.FC = () => {
const { isReset, setReset } = useResetButtonStore(); const { isReset, setReset } = useResetButtonStore();
const { subModule } = useSubModuleStore(); const { subModule } = useSubModuleStore();
useEffect(() => {
if (isReset) {
setTimeout(()=>{
setReset(false);
},0)
}
}, [isReset])
// Button functions // Button functions
const handleReset = () => { const handleReset = () => {
setReset(true); setReset(true);

View File

@@ -1,6 +1,7 @@
import { useCallback, useEffect, useRef } from "react"; import { useCallback, useEffect, useRef } from "react";
import { useFrame } from "@react-three/fiber"; import { useFrame } from "@react-three/fiber";
import { usePlayButtonStore, usePauseButtonStore } from "../../../../../store/usePlayButtonStore"; import { usePlayButtonStore, usePauseButtonStore, useResetButtonStore } from "../../../../../store/usePlayButtonStore";
import { useMaterialStore } from "../../../../../store/simulation/useMaterialStore";
interface DelayInstance { interface DelayInstance {
delayEndTime: number; delayEndTime: number;
@@ -13,6 +14,8 @@ interface DelayInstance {
export function useDelayHandler() { export function useDelayHandler() {
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { isPaused } = usePauseButtonStore(); const { isPaused } = usePauseButtonStore();
const { isReset } = useResetButtonStore();
const { setIsPaused } = useMaterialStore();
const activeDelays = useRef<Map<string, DelayInstance>>(new Map()); const activeDelays = useRef<Map<string, DelayInstance>>(new Map());
const cleanupDelay = useCallback(() => { const cleanupDelay = useCallback(() => {
@@ -20,12 +23,15 @@ export function useDelayHandler() {
}, []); }, []);
useEffect(() => { useEffect(() => {
return () => { if (isReset) {
cleanupDelay(); cleanupDelay();
}; }
}, [cleanupDelay]); }, [isReset, cleanupDelay]);
const delayLogStatus = (materialUuid: string, status: string) => {
// console.log(`${materialUuid}, ${status}`);
}
// Handle pause/resume for all delays
useEffect(() => { useEffect(() => {
const currentTime = performance.now(); const currentTime = performance.now();
@@ -48,8 +54,9 @@ export function useDelayHandler() {
const completedDelays: string[] = []; const completedDelays: string[] = [];
activeDelays.current.forEach((delay, key) => { activeDelays.current.forEach((delay, key) => {
if (!delay.isPaused && currentTime >= delay.delayEndTime) { if (!delay.isPaused && currentTime >= delay.delayEndTime && delay.materialId) {
console.log(`Delay completed for material ${delay.materialId || 'unknown'}`); delayLogStatus(delay.materialId, `Delay completed}`);
setIsPaused(delay.materialId, false);
completedDelays.push(key); completedDelays.push(key);
} }
}); });
@@ -60,7 +67,7 @@ export function useDelayHandler() {
}); });
const handleDelay = useCallback((action: ConveyorAction, materialId?: string) => { const handleDelay = useCallback((action: ConveyorAction, materialId?: string) => {
if (!action || action.actionType !== 'delay' || !isPlaying) return; if (!action || action.actionType !== 'delay' || !isPlaying || !materialId) return;
const delayMs = (action.delay || 0) * 1000; const delayMs = (action.delay || 0) * 1000;
if (delayMs <= 0) return; if (delayMs <= 0) return;
@@ -80,10 +87,17 @@ export function useDelayHandler() {
remainingTime: 0 remainingTime: 0
}); });
console.log(`Started ${delayMs}ms delay for material ${materialId || 'unknown'}`); delayLogStatus(materialId, `Started ${delayMs * 1000}s delay`);
setIsPaused(materialId, true);
}, [isPlaying]); }, [isPlaying]);
useEffect(() => {
return () => {
cleanupDelay();
};
}, [cleanupDelay]);
return { return {
handleDelay, handleDelay,
cleanupDelay cleanupDelay

View File

@@ -5,6 +5,7 @@ import { useMaterialStore } from "../../../../../store/simulation/useMaterialSto
import { useProductStore } from "../../../../../store/simulation/useProductStore"; import { useProductStore } from "../../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore"; import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
import { usePlayButtonStore, useAnimationPlaySpeed, usePauseButtonStore, useResetButtonStore } from "../../../../../store/usePlayButtonStore"; import { usePlayButtonStore, useAnimationPlaySpeed, usePauseButtonStore, useResetButtonStore } from "../../../../../store/usePlayButtonStore";
import { useConveyorStore } from "../../../../../store/simulation/useConveyorStore";
interface SpawnInstance { interface SpawnInstance {
lastSpawnTime: number | null; lastSpawnTime: number | null;
@@ -23,6 +24,7 @@ interface SpawnInstance {
export function useSpawnHandler() { export function useSpawnHandler() {
const { addMaterial } = useMaterialStore(); const { addMaterial } = useMaterialStore();
const { getConveyorById } = useConveyorStore();
const { getModelUuidByActionUuid, getPointUuidByActionUuid } = useProductStore(); const { getModelUuidByActionUuid, getPointUuidByActionUuid } = useProductStore();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { isPaused } = usePauseButtonStore(); const { isPaused } = usePauseButtonStore();
@@ -57,6 +59,7 @@ export function useSpawnHandler() {
materialType: materialType, materialType: materialType,
isActive: false, isActive: false,
isVisible: true, isVisible: true,
isPaused: false,
isRendered: true, isRendered: true,
current: { current: {
modelUuid: modelUuid, modelUuid: modelUuid,
@@ -81,6 +84,15 @@ export function useSpawnHandler() {
return newMaterial; return newMaterial;
}, [addMaterial, getModelUuidByActionUuid, getPointUuidByActionUuid, selectedProduct.productId]); }, [addMaterial, getModelUuidByActionUuid, getPointUuidByActionUuid, selectedProduct.productId]);
const getConveyorPausedState = useCallback((action: ConveyorAction) => {
const modelUuid = getModelUuidByActionUuid(selectedProduct.productId, action.actionUuid);
if (!modelUuid) return false;
const conveyor = getConveyorById(modelUuid);
return conveyor?.isPaused ?? false;
}, [getConveyorById, getModelUuidByActionUuid, selectedProduct.productId]);
useEffect(() => { useEffect(() => {
const currentTime = performance.now(); const currentTime = performance.now();

View File

@@ -9,7 +9,6 @@ export function useConveyorActions() {
const { handleDelay, cleanupDelay } = useDelayHandler(); const { handleDelay, cleanupDelay } = useDelayHandler();
const handleDefaultAction = useCallback((action: ConveyorAction) => { const handleDefaultAction = useCallback((action: ConveyorAction) => {
console.log(`Default conveyor action ${action.actionUuid}`);
}, []); }, []);
const handleSpawnAction = useCallback((action: ConveyorAction) => { const handleSpawnAction = useCallback((action: ConveyorAction) => {

View File

@@ -1,6 +1,33 @@
import React from 'react' import React, { useEffect } from 'react'
import { useMaterialStore } from '../../../../../store/simulation/useMaterialStore';
import { useConveyorStore } from '../../../../../store/simulation/useConveyorStore';
import { useResetButtonStore } from '../../../../../store/usePlayButtonStore';
function ConveyorInstance({ conveyor }: { conveyor: ConveyorStatus }) {
const { materials, getMaterialsByCurrentModelUuid } = useMaterialStore();
const { isReset } = useResetButtonStore();
const { setConveyorPaused } = useConveyorStore();
useEffect(() => {
const conveyorMaterials = getMaterialsByCurrentModelUuid(conveyor.modelUuid);
if (conveyorMaterials && conveyorMaterials?.length > 0) {
const hasPausedMaterials = conveyorMaterials.some(material => material.isPaused);
if (hasPausedMaterials) {
setConveyorPaused(conveyor.modelUuid, true);
} else {
setConveyorPaused(conveyor.modelUuid, false);
}
}
}, [materials, conveyor.modelUuid, getMaterialsByCurrentModelUuid, setConveyorPaused, isReset]);
useEffect(() => {
// console.log('conveyor: ', conveyor);
}, [conveyor])
function ConveyorInstance() {
return ( return (
<> <>
</> </>

View File

@@ -1,11 +1,17 @@
import React from 'react' import React from 'react'
import ConveyorInstance from './conveyorInstance/conveyorInstance' import ConveyorInstance from './conveyorInstance/conveyorInstance'
import { useConveyorStore } from '../../../../store/simulation/useConveyorStore'
function ConveyorInstances() { function ConveyorInstances() {
const { conveyors } = useConveyorStore();
return ( return (
<> <>
<ConveyorInstance /> {conveyors.map((conveyor: ConveyorStatus) =>
<ConveyorInstance conveyor={conveyor} key={conveyor.modelUuid} />
)}
</> </>
) )

View File

@@ -2,6 +2,7 @@ import React, { useEffect, useState, useRef } from 'react';
import * as THREE from 'three'; import * as THREE from 'three';
import { useFrame, useThree } from '@react-three/fiber'; import { useFrame, useThree } from '@react-three/fiber';
import { usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore'; import { usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useConveyorStore } from '../../../../../store/simulation/useConveyorStore';
interface MaterialAnimatorProps { interface MaterialAnimatorProps {
matRef: React.RefObject<THREE.Mesh>; matRef: React.RefObject<THREE.Mesh>;
@@ -19,6 +20,7 @@ function MaterialAnimator({
const { scene } = useThree(); const { scene } = useThree();
const [targetPosition, setTargetPosition] = useState<THREE.Vector3 | null>(null); const [targetPosition, setTargetPosition] = useState<THREE.Vector3 | null>(null);
const [isAnimating, setIsAnimating] = useState(false); const [isAnimating, setIsAnimating] = useState(false);
const { getConveyorById } = useConveyorStore();
const animationState = useRef({ const animationState = useRef({
startTime: 0, startTime: 0,
startPosition: new THREE.Vector3(), startPosition: new THREE.Vector3(),
@@ -29,7 +31,10 @@ function MaterialAnimator({
}); });
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { isPaused } = usePauseButtonStore(); const { isPaused: isGlobalPaused } = usePauseButtonStore();
const conveyor = getConveyorById(material.current.modelUuid);
const shouldPause = isGlobalPaused || material.isPaused || conveyor?.isPaused;
const getWorldPosition = (uuid: string): THREE.Vector3 | null => { const getWorldPosition = (uuid: string): THREE.Vector3 | null => {
const obj = scene.getObjectByProperty('uuid', uuid); const obj = scene.getObjectByProperty('uuid', uuid);
@@ -58,18 +63,20 @@ function MaterialAnimator({
}, [material.next?.pointUuid, isPlaying]); }, [material.next?.pointUuid, isPlaying]);
useEffect(() => { useEffect(() => {
if (isPaused) { if (shouldPause) {
// Pause the animation
animationState.current.isPaused = true; animationState.current.isPaused = true;
setIsAnimating(false); setIsAnimating(false);
animationState.current.pausedTime = performance.now() - animationState.current.startTime; animationState.current.pausedTime = performance.now() - animationState.current.startTime;
} else { } else {
// Resume the animation
animationState.current.isPaused = false; animationState.current.isPaused = false;
if (isPlaying && targetPosition && !isAnimating) { if (isPlaying && targetPosition && !isAnimating) {
animationState.current.startTime = performance.now() - animationState.current.pausedTime; animationState.current.startTime = performance.now() - animationState.current.pausedTime;
setIsAnimating(true); setIsAnimating(true);
} }
} }
}, [isPaused]); }, [shouldPause, isPlaying]);
useFrame(() => { useFrame(() => {
if (!matRef.current || !targetPosition || !isAnimating || animationState.current.isPaused || !isPlaying) { if (!matRef.current || !targetPosition || !isAnimating || animationState.current.isPaused || !isPlaying) {
@@ -97,7 +104,7 @@ function MaterialAnimator({
pausedTime: 0, pausedTime: 0,
isPaused: false, isPaused: false,
lastFrameTime: 0 lastFrameTime: 0
} };
} }
}); });

View File

@@ -39,12 +39,12 @@ function MaterialInstance({ material }: { material: MaterialSchema }) {
const point = getPointByUuid(selectedProduct.productId, modelUuid, material.current.pointUuid); const point = getPointByUuid(selectedProduct.productId, modelUuid, material.current.pointUuid);
if (!point) { if (!point) {
return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), currentSpeed: 1 }; return { position: new THREE.Vector3(0, 0, 0), rotation: new THREE.Vector3(0, 0, 0), currentSpeed: currentSpeed || 1 };
} }
const position = getWorldPositionFromScene(point.uuid); const position = getWorldPositionFromScene(point.uuid);
if (position) { if (position) {
return { position: position, rotation: new THREE.Vector3(0, 0, 0), currentSpeed: 1 }; return { position: position, rotation: new THREE.Vector3(0, 0, 0), currentSpeed: currentSpeed || 1 };
} }
return { return {
@@ -54,6 +54,7 @@ function MaterialInstance({ material }: { material: MaterialSchema }) {
}; };
}, [material, getPointByUuid]); }, [material, getPointByUuid]);
function getCurrentSpeed(productId: string, modelUuid: string) { function getCurrentSpeed(productId: string, modelUuid: string) {
const event = getEventByModelUuid(productId, modelUuid) const event = getEventByModelUuid(productId, modelUuid)
if (event) { if (event) {

View File

@@ -7,12 +7,14 @@ import { upsertProductOrEventApi } from '../../../services/simulation/UpsertProd
import { getAllProductsApi } from '../../../services/simulation/getallProductsApi'; import { getAllProductsApi } from '../../../services/simulation/getallProductsApi';
import { useVehicleStore } from '../../../store/simulation/useVehicleStore'; import { useVehicleStore } from '../../../store/simulation/useVehicleStore';
import { useArmBotStore } from '../../../store/simulation/useArmBotStore'; import { useArmBotStore } from '../../../store/simulation/useArmBotStore';
import { useConveyorStore } from '../../../store/simulation/useConveyorStore';
function Products() { function Products() {
const { products, getProductById, addProduct, setProducts } = useProductStore(); const { products, getProductById, addProduct, setProducts } = useProductStore();
const { selectedProduct, setSelectedProduct } = useSelectedProduct(); const { selectedProduct, setSelectedProduct } = useSelectedProduct();
const { addVehicle, clearvehicles } = useVehicleStore(); const { addVehicle, clearvehicles } = useVehicleStore();
const { addArmBot, clearArmBots } = useArmBotStore(); const { addArmBot, clearArmBots } = useArmBotStore();
const { addConveyor, clearConveyors } = useConveyorStore();
useEffect(() => { useEffect(() => {
const email = localStorage.getItem('email') const email = localStorage.getItem('email')
@@ -59,6 +61,20 @@ function Products() {
} }
}, [selectedProduct, products]); }, [selectedProduct, products]);
useEffect(() => {
if (selectedProduct.productId) {
const product = getProductById(selectedProduct.productId);
if (product) {
clearConveyors();
product.eventDatas.forEach(events => {
if (events.type === 'transfer') {
addConveyor(selectedProduct.productId, events);
}
});
}
}
}, [selectedProduct, products]);
return ( return (
<> <>

View File

@@ -1,24 +1,37 @@
import { useEffect } from "react"; import { useEffect, useState } from "react";
import RoboticArmInstances from "./instances/roboticArmInstances";
import { useArmBotStore } from "../../../store/simulation/useArmBotStore"; import { useArmBotStore } from "../../../store/simulation/useArmBotStore";
import { useSelectedEventData, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore"; import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import ArmBotUI from "../ui/arm/armBotUI"; import ArmBotUI from "../ui/arm/armBotUI";
import RoboticArmInstances from "./instances/roboticArmInstances";
function RoboticArm() { function RoboticArm() {
const { armBots } = useArmBotStore(); const { armBots, getArmBotById } = useArmBotStore();
const { selectedEventSphere } = useSelectedEventSphere(); const { selectedEventSphere } = useSelectedEventSphere();
const { selectedEventData } = useSelectedEventData(); const { isPlaying } = usePlayButtonStore();
const [isArmBotSelected, setIsArmBotSelected] = useState(false);
useEffect(() => { useEffect(() => {
// console.log('armBots: ', armBots); // console.log('armBots: ', armBots);
}, [armBots]) }, [armBots])
useEffect(() => {
if (selectedEventSphere) {
const selectedArmBot = getArmBotById(selectedEventSphere.userData.modelUuid);
if (selectedArmBot) {
setIsArmBotSelected(true);
} else {
setIsArmBotSelected(false);
}
}
}, [selectedEventSphere])
return ( return (
<> <>
<RoboticArmInstances /> <RoboticArmInstances />
{selectedEventSphere && selectedEventData?.data.type === "roboticArm" && {isArmBotSelected && !isPlaying &&
< ArmBotUI /> < ArmBotUI />
} }

View File

@@ -10,7 +10,7 @@ interface VehicleAnimatorProps {
handleCallBack: () => void; handleCallBack: () => void;
reset: () => void; reset: () => void;
currentPhase: string; currentPhase: string;
agvUuid: number; agvUuid: string;
agvDetail: VehicleStatus; agvDetail: VehicleStatus;
} }

View File

@@ -7,7 +7,7 @@ import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore';
import MaterialAnimator from '../animator/materialAnimator'; import MaterialAnimator from '../animator/materialAnimator';
function VehicleInstance({ agvDetail }: any) { function VehicleInstance({ agvDetail }: { agvDetail: VehicleStatus }) {
const { navMesh } = useNavMesh(); const { navMesh } = useNavMesh();
const vehicleRef: any = useRef(); const vehicleRef: any = useRef();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
@@ -74,28 +74,32 @@ function VehicleInstance({ agvDetail }: any) {
if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity && agvDetail.materialType) { if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity && agvDetail.materialType) {
const toDrop = computePath( if (agvDetail.point.action.pickUpPoint && agvDetail.point.action.unLoadPoint) {
agvDetail.point.action.pickUpPoint.position, const toDrop = computePath(
agvDetail.point.action.unLoadPoint.position agvDetail.point.action.pickUpPoint.position,
); agvDetail.point.action.unLoadPoint.position
setPath(toDrop); );
setCurrentPhase('pickup-drop'); setPath(toDrop);
setVehicleState(agvDetail.modelUuid, 'running'); setCurrentPhase('pickup-drop');
setVehicleActive(agvDetail.modelUuid, true); setVehicleState(agvDetail.modelUuid, 'running');
vehicleStatus(agvDetail.modelUuid, 'Started from pickup point, heading to drop point'); setVehicleActive(agvDetail.modelUuid, true);
vehicleStatus(agvDetail.modelUuid, 'Started from pickup point, heading to drop point');
}
} }
} else if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'dropping' && agvDetail.currentLoad === 0) { } else if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'dropping' && agvDetail.currentLoad === 0) {
const dropToPickup = computePath( if (agvDetail.point.action.pickUpPoint && agvDetail.point.action.unLoadPoint) {
agvDetail.point.action.unLoadPoint.position, const dropToPickup = computePath(
agvDetail.point.action.pickUpPoint.position agvDetail.point.action.unLoadPoint.position,
); agvDetail.point.action.pickUpPoint.position
setPath(dropToPickup); );
setCurrentPhase('drop-pickup'); setPath(dropToPickup);
setVehicleState(agvDetail.modelUuid, 'running'); setCurrentPhase('drop-pickup');
setVehicleActive(agvDetail.modelUuid, true); setVehicleState(agvDetail.modelUuid, 'running');
vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point'); setVehicleActive(agvDetail.modelUuid, true);
vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point');
isIncrememtable.current = true; isIncrememtable.current = true;
}
} }
} else { } else {
reset() reset()

View File

@@ -1,26 +1,37 @@
import { useEffect } from "react"; import { useEffect, useState } from "react";
import VehicleInstances from "./instances/vehicleInstances";
import { useVehicleStore } from "../../../store/simulation/useVehicleStore"; import { useVehicleStore } from "../../../store/simulation/useVehicleStore";
import { useSelectedEventData, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore"; import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
import VehicleUI from "../ui/vehicle/vehicleUI";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import VehicleUI from "../ui/vehicle/vehicleUI";
import VehicleInstances from "./instances/vehicleInstances";
function Vehicles() { function Vehicles() {
const { vehicles } = useVehicleStore(); const { vehicles, getVehicleById } = useVehicleStore();
const { selectedEventSphere } = useSelectedEventSphere(); const { selectedEventSphere } = useSelectedEventSphere();
const { selectedEventData } = useSelectedEventData();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const [isVehicleSelected, setIsVehicleSelected] = useState(false);
useEffect(() => { useEffect(() => {
// console.log('vehicles: ', vehicles); // console.log('vehicles: ', vehicles);
}, [vehicles]) }, [vehicles])
useEffect(() => {
if (selectedEventSphere) {
const selectedVehicle = getVehicleById(selectedEventSphere.userData.modelUuid);
if (selectedVehicle) {
setIsVehicleSelected(true);
} else {
setIsVehicleSelected(false);
}
}
}, [selectedEventSphere])
return ( return (
<> <>
<VehicleInstances /> <VehicleInstances />
{selectedEventSphere && selectedEventData?.data.type === "vehicle" && !isPlaying && {isVehicleSelected && !isPlaying &&
< VehicleUI /> < VehicleUI />
} }

View File

@@ -14,6 +14,7 @@ interface ConveyorStore {
setConveyorActive: (modelUuid: string, isActive: boolean) => void; setConveyorActive: (modelUuid: string, isActive: boolean) => void;
setConveyorState: (modelUuid: string, newState: ConveyorStatus['state']) => void; setConveyorState: (modelUuid: string, newState: ConveyorStatus['state']) => void;
setConveyorPaused: (modelUuid: string, isPaused: boolean) => void;
incrementActiveTime: (modelUuid: string, incrementBy: number) => void; incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
incrementIdleTime: (modelUuid: string, incrementBy: number) => void; incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
@@ -37,6 +38,7 @@ export const useConveyorStore = create<ConveyorStore>()(
...event, ...event,
productId, productId,
isActive: false, isActive: false,
isPaused: false,
idleTime: 0, idleTime: 0,
activeTime: 0, activeTime: 0,
state: 'idle', state: 'idle',
@@ -84,6 +86,15 @@ export const useConveyorStore = create<ConveyorStore>()(
}); });
}, },
setConveyorPaused: (modelUuid, isPaused) => {
set((state) => {
const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);
if (conveyor) {
conveyor.isPaused = isPaused;
}
});
},
incrementActiveTime: (modelUuid, incrementBy) => { incrementActiveTime: (modelUuid, incrementBy) => {
set((state) => { set((state) => {
const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid); const conveyor = state.conveyors.find(c => c.modelUuid === modelUuid);

View File

@@ -33,6 +33,7 @@ type MaterialsStore = {
setWeight: (materialId: string, weight: number) => MaterialSchema | undefined; setWeight: (materialId: string, weight: number) => MaterialSchema | undefined;
setIsActive: (materialId: string, isActive: boolean) => MaterialSchema | undefined; setIsActive: (materialId: string, isActive: boolean) => MaterialSchema | undefined;
setIsVisible: (materialId: string, isVisible: boolean) => MaterialSchema | undefined; setIsVisible: (materialId: string, isVisible: boolean) => MaterialSchema | undefined;
setIsPaused: (materialId: string, isPlaying: boolean) => MaterialSchema | undefined;
setIsRendered: (materialId: string, isRendered: boolean) => MaterialSchema | undefined; setIsRendered: (materialId: string, isRendered: boolean) => MaterialSchema | undefined;
getMaterialById: (materialId: string) => MaterialSchema | undefined; getMaterialById: (materialId: string) => MaterialSchema | undefined;
@@ -192,6 +193,18 @@ export const useMaterialStore = create<MaterialsStore>()(
return updatedMaterial; 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) => { setIsRendered: (materialId, isRendered) => {
let updatedMaterial: MaterialSchema | undefined; let updatedMaterial: MaterialSchema | undefined;
set((state) => { set((state) => {

View File

@@ -145,6 +145,7 @@ type productsSchema = {
interface ConveyorStatus extends ConveyorEventSchema { interface ConveyorStatus extends ConveyorEventSchema {
productId: string; productId: string;
isActive: boolean; isActive: boolean;
isPaused: boolean;
idleTime: number; idleTime: number;
activeTime: number; activeTime: number;
} }
@@ -198,6 +199,7 @@ interface MaterialSchema {
materialType: string; materialType: string;
isActive: boolean; isActive: boolean;
isVisible: boolean; isVisible: boolean;
isPaused: boolean;
isRendered: boolean; isRendered: boolean;
startTime?: string; startTime?: string;
endTime?: string; endTime?: string;