Dwinzo_dev/app/src/components/layout/sidebarRight/mechanics/VehicleMechanics.tsx

265 lines
11 KiB
TypeScript

import React, { useRef, useMemo } from "react";
import { InfoIcon } from "../../../icons/ExportCommonIcons";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
import * as SimulationTypes from '../../../../types/simulationTypes';
import PositionInput from "../customInput/PositionInputs";
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
import LabeledButton from "../../../ui/inputs/LabledButton";
const VehicleMechanics: React.FC = () => {
const { selectedActionSphere } = useSelectedActionSphere();
const { simulationStates, setSimulationStates } = useSimulationStates();
const { eyeDropMode, setEyeDropMode } = useEyeDropMode();
const { editingPoint, setEditingPoint } = useEditingPoint();
const { previewPosition, setPreviewPosition } = usePreviewPosition();
const { socket } = useSocketStore();
const propertiesContainerRef = useRef<HTMLDivElement>(null);
const { selectedPoint, connectedPointUuids } = useMemo(() => {
if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null, connectedPointUuids: [] };
const vehiclePaths = simulationStates.filter(
(path): path is SimulationTypes.VehicleEventsSchema => path.type === "Vehicle"
);
const points = vehiclePaths.find(
(path) => path.points.uuid === selectedActionSphere.points.uuid
)?.points;
if (!points) return { selectedPoint: null, connectedPointUuids: [] };
const connectedUuids: string[] = [];
if (points.connections?.targets) {
points.connections.targets.forEach(target => {
connectedUuids.push(target.pointUUID);
});
}
return {
selectedPoint: points,
connectedPointUuids: connectedUuids
};
}, [selectedActionSphere, simulationStates]);
const updateBackend = async (updatedPath: SimulationTypes.VehicleEventsSchema | undefined) => {
if (!updatedPath) return;
const email = localStorage.getItem("email");
const organization = email ? email.split("@")[1].split(".")[0] : "";
// await setEventApi(
// organization,
// updatedPath.modeluuid,
// { type: "Vehicle", points: updatedPath.points }
// );
const data = {
organization: organization,
modeluuid: updatedPath.modeluuid,
eventData: { type: "Vehicle", points: updatedPath.points }
}
socket.emit('v2:model-asset:updateEventData', data);
}
const handleActionUpdate = React.useCallback((updatedAction: Partial<SimulationTypes.VehicleEventsSchema['points']['actions']>) => {
if (!selectedActionSphere?.points?.uuid) return;
const updatedPaths = simulationStates.map((path) => {
if (path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid) {
return {
...path,
points: {
...path.points,
actions: {
...path.points.actions,
...updatedAction
}
}
};
}
return path;
});
const updatedPath = updatedPaths.find(
(path): path is SimulationTypes.VehicleEventsSchema =>
path.type === "Vehicle" &&
path.points.uuid === selectedActionSphere.points.uuid
);
updateBackend(updatedPath);
setSimulationStates(updatedPaths);
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
const handleHitCountChange = React.useCallback((hitCount: number) => {
handleActionUpdate({ hitCount });
}, [handleActionUpdate]);
const handleBufferChange = React.useCallback((buffer: number) => {
handleActionUpdate({ buffer });
}, [handleActionUpdate]);
const handleSpeedChange = React.useCallback((speed: number) => {
if (!selectedActionSphere?.points?.uuid) return;
const updatedPaths = simulationStates.map((path) => {
if (path.type === "Vehicle" && path.points.uuid === selectedActionSphere.points.uuid) {
return {
...path,
points: {
...path.points,
speed: speed
}
};
}
return path;
});
const updatedPath = updatedPaths.find(
(path): path is SimulationTypes.VehicleEventsSchema =>
path.type === "Vehicle" &&
path.points.uuid === selectedActionSphere.points.uuid
);
updateBackend(updatedPath);
setSimulationStates(updatedPaths);
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
const ResetVehicleState = React.useCallback(() => {
if (!selectedActionSphere?.points?.uuid) return;
const updatedPaths = simulationStates.map((state) => {
if (state.type === "Vehicle" && state.points.uuid === selectedActionSphere.points.uuid) {
return {
...state,
points: {
...state.points,
actions: { ...state.points.actions, start: {}, end: {} }
}
};
}
return state;
});
const updatedPath = updatedPaths.find(
(path): path is SimulationTypes.VehicleEventsSchema =>
path.type === "Vehicle" &&
path.points.uuid === selectedActionSphere.points.uuid
);
updateBackend(updatedPath);
setSimulationStates(updatedPaths);
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
const handleStartEyeDropClick = () => {
setEditingPoint('start');
setEyeDropMode(true);
};
const handleEndEyeDropClick = () => {
setEditingPoint('end');
setEyeDropMode(true);
};
return (
<div className="machine-mechanics-container" key={selectedPoint?.uuid}>
<div className="machine-mechanics-header">
{selectedActionSphere?.path?.modelName || "Vehicle point not found"}
</div>
<div className="machine-mechanics-content-container">
<div className="selected-properties-container" ref={propertiesContainerRef}>
<div className="properties-header">Vehicle Properties</div>
{selectedPoint && (
<>
<PositionInput
label="Start Point"
onChange={() => { }}
disabled={true}
value1={
editingPoint === 'start' && previewPosition
? parseFloat(previewPosition.x.toFixed(4))
: selectedPoint.actions.start && 'x' in selectedPoint.actions.start
? parseFloat(selectedPoint.actions.start.x.toFixed(4))
: 0
}
value2={
editingPoint === 'start' && previewPosition
? parseFloat(previewPosition.y.toFixed(4))
: selectedPoint.actions.start && 'y' in selectedPoint.actions.start
? parseFloat(selectedPoint.actions.start.y.toFixed(4))
: 0
}
isEyedrop={true}
handleEyeDropClick={handleStartEyeDropClick}
/>
<PositionInput
label="End Point"
onChange={() => { }}
disabled={true}
value1={
editingPoint === 'end' && previewPosition
? parseFloat(previewPosition.x.toFixed(4))
: selectedPoint.actions.end && 'x' in selectedPoint.actions.end
? parseFloat(selectedPoint.actions.end.x.toFixed(4))
: 0
}
value2={
editingPoint === 'end' && previewPosition
? parseFloat(previewPosition.y.toFixed(4))
: selectedPoint.actions.end && 'y' in selectedPoint.actions.end
? parseFloat(selectedPoint.actions.end.y.toFixed(4))
: 0
}
isEyedrop={true}
handleEyeDropClick={handleEndEyeDropClick}
/>
<LabeledButton
label="Reset"
value="Clear Points"
onClick={() => {
ResetVehicleState();
}}
/>
<InputWithDropDown
key={`hitcount-${selectedPoint.uuid}`}
label="Hit Count"
value={selectedPoint.actions.hitCount.toString()}
onChange={(value) => handleHitCountChange(parseInt(value))}
/>
<InputWithDropDown
key={`buffer-${selectedPoint.uuid}`}
label="Buffer Time"
value={selectedPoint.actions.buffer.toString()}
onChange={(value) => handleBufferChange(parseInt(value))}
/>
<InputWithDropDown
key={`speed-${selectedPoint.uuid}`}
label="Vehicle Speed"
value={selectedPoint.speed.toString()}
onChange={(value) => handleSpeedChange(parseFloat(value))}
/>
</>
)}
</div>
<div className="footer">
<InfoIcon />
Configure vehicle's movement and interaction properties.
</div>
</div>
</div>
);
};
export default React.memo(VehicleMechanics);