diff --git a/app/src/components/footer/shortcutHelper.tsx b/app/src/components/footer/shortcutHelper.tsx index afbaa0e..230dff2 100644 --- a/app/src/components/footer/shortcutHelper.tsx +++ b/app/src/components/footer/shortcutHelper.tsx @@ -55,6 +55,7 @@ interface ShortcutHelperProps { const ShortcutHelper: React.FC = ({ setShowShortcuts, }) => { + const shortcuts: ShortcutGroup[] = [ // Essential { @@ -310,6 +311,7 @@ const ShortcutHelper: React.FC = ({ > +
{shortcuts.map((group) => ( @@ -326,9 +328,8 @@ const ShortcutHelper: React.FC = ({
{activeShortcuts.map((item) => (
} - {(commentPositionState !== null || selectedComment !== null) && } + + { + (commentPositionState !== null || selectedComment !== null) && + + } ); diff --git a/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx b/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx index 4f76584..a62abda 100644 --- a/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/AssetProperties.tsx @@ -78,8 +78,8 @@ const AssetProperties: React.FC = () => {
User Data
- {userData.map((data) => ( -
+ {userData.map((data, i) => ( +
{
Animations
- {assets.map((asset) => { + {assets.map((asset, i) => { if (asset.modelUuid !== selectedFloorItem.uuid || !asset.animations) - return null; + return ( + i === 0 && ( +
+ Looks like there are no preset animations yet. Stay tuned for + future additions! +
+ ) + ); return asset.animations.map((animation, index) => (
diff --git a/app/src/components/layout/sidebarRight/resourceManagement/ResourceManagement.tsx b/app/src/components/layout/sidebarRight/resourceManagement/ResourceManagement.tsx index 3b0df8a..e5c0442 100644 --- a/app/src/components/layout/sidebarRight/resourceManagement/ResourceManagement.tsx +++ b/app/src/components/layout/sidebarRight/resourceManagement/ResourceManagement.tsx @@ -30,14 +30,6 @@ const ResourceManagement = () => {
{ }} /> -
- { }} - search={false} - /> -
{selectType === "assetManagement" ? : } diff --git a/app/src/components/layout/sidebarRight/resourceManagement/hrm/Hrm.tsx b/app/src/components/layout/sidebarRight/resourceManagement/hrm/Hrm.tsx index 2aeacc2..99828ae 100644 --- a/app/src/components/layout/sidebarRight/resourceManagement/hrm/Hrm.tsx +++ b/app/src/components/layout/sidebarRight/resourceManagement/hrm/Hrm.tsx @@ -1,96 +1,165 @@ -import { useState } from 'react' +import { useEffect, useState } from 'react' import { ClockThreeIcon, LocationPinIcon, TargetIcon } from '../../../../icons/ExportCommonIcons' +import { useSceneContext } from '../../../../../modules/scene/sceneContext'; +import { useProductContext } from '../../../../../modules/simulation/products/productContext'; +import RenameInput from '../../../../ui/inputs/RenameInput'; +import { useResourceManagementId } from '../../../../../store/builder/store'; +import { set } from 'immer/dist/internal'; // import NavigateCatagory from '../NavigateCatagory' const Hrm = () => { const [selectedCard, setSelectedCard] = useState(0); + const [workers, setWorkers] = useState([]); - const employee_details = [ - { - "employee": { - image: "", - "name": "John Doe", - "employee_id": "HR-204", - "status": "Active", + const { productStore } = useSceneContext(); + const { products, getProductById } = productStore(); + const { selectedProductStore } = useProductContext(); + const { selectedProduct } = selectedProductStore(); + const { setResourceManagementId } = useResourceManagementId(); - }, - "task": { - "status": "Ongoing", - "title": "Inspecting Machine X", - "location": { - "floor": 4, - "zone": "B" - }, - "planned_time_hours": 6, - "time_spent_hours": 2, - "total_tasks": 12, - "completed_tasks": 3 - }, - "actions": [ - "Assign Task", - "Reassign Task", - "Pause", - "Emergency Stop" - ], - "location": "Floor 4 . Zone B" - }, - { - "employee": { - image: "", - "name": "Alice Smith", - "employee_id": "HR-205", - "status": "Active", + useEffect(() => { + if (selectedProduct) { + const productDetails = getProductById(selectedProduct.productUuid); + const workerDetails = productDetails?.eventDatas || []; - }, - "task": { - "status": "Ongoing", - "title": "Calibrating Sensor Y", - "location": { - "floor": 2, - "zone": "A" - }, - "planned_time_hours": 4, - "time_spent_hours": 1.5, - "total_tasks": 10, - "completed_tasks": 2 - }, - "actions": [ - "Assign Task", - "Reassign Task", - "Pause", - "Emergency Stop" - ], - "location": "Floor 4 . Zone B" - }, - { - "employee": { - image: "", - "name": "Michael Lee", - "employee_id": "HR-206", - "status": "Active", + const formattedWorkers = workerDetails + .filter((worker: any) => worker.type === "human") + .map((worker: any, index: number) => ({ + employee: { + image: "", + name: worker.modelName, + modelId: worker.modelUuid, + employee_id: `HR-${204 + index}`, + status: "Active", + }, + task: { + status: "Ongoing", + title: worker.taskTitle || "No Task Assigned", + location: { + floor: worker.floor || 0, + zone: worker.zone || "N/A" + }, + planned_time_hours: worker.plannedTime || 0, + time_spent_hours: worker.timeSpent || 0, + total_tasks: worker.totalTasks || 0, + completed_tasks: worker.completedTasks || 0 + }, + actions: [ + "Assign Task", + "Reassign Task", + "Pause", + "Emergency Stop" + ], + location: `Floor ${worker.floor || "-"} . Zone ${worker.zone || "-"}` + })); + + setWorkers(formattedWorkers); + } + }, [selectedProduct, getProductById]); + + useEffect(() => { + // + }, [workers]); + + + + + // const employee_details = [ + // { + // "employee": { + // image: "", + // "name": "John Doe", + // "employee_id": "HR-204", + // "status": "Active", + + // }, + // "task": { + // "status": "Ongoing", + // "title": "Inspecting Machine X", + // "location": { + // "floor": 4, + // "zone": "B" + // }, + // "planned_time_hours": 6, + // "time_spent_hours": 2, + // "total_tasks": 12, + // "completed_tasks": 3 + // }, + // "actions": [ + // "Assign Task", + // "Reassign Task", + // "Pause", + // "Emergency Stop" + // ], + // "location": "Floor 4 . Zone B" + // }, + // { + // "employee": { + // image: "", + // "name": "Alice Smith", + // "employee_id": "HR-205", + // "status": "Active", + + // }, + // "task": { + // "status": "Ongoing", + // "title": "Calibrating Sensor Y", + // "location": { + // "floor": 2, + // "zone": "A" + // }, + // "planned_time_hours": 4, + // "time_spent_hours": 1.5, + // "total_tasks": 10, + // "completed_tasks": 2 + // }, + // "actions": [ + // "Assign Task", + // "Reassign Task", + // "Pause", + // "Emergency Stop" + // ], + // "location": "Floor 4 . Zone B" + // }, + // { + // "employee": { + // image: "", + // "name": "Michael Lee", + // "employee_id": "HR-206", + // "status": "Active", + + // }, + // "task": { + // "status": "Ongoing", + // "title": "Testing Conveyor Belt Z", + // "location": { + // "floor": 5, + // "zone": "C" + // }, + // "planned_time_hours": 5, + // "time_spent_hours": 3, + // "total_tasks": 8, + // "completed_tasks": 5 + // }, + // "actions": [ + // "Assign Task", + // "Reassign Task", + // "Pause", + // "Emergency Stop" + // ], + // "location": "Floor 4 . Zone B" + // }, + // ] + function handleRenameWorker(newName: string) { + // + + } + function handleHumanClick(employee: any) { + if (employee.modelId) { + setResourceManagementId(employee.modelId); + } + } - }, - "task": { - "status": "Ongoing", - "title": "Testing Conveyor Belt Z", - "location": { - "floor": 5, - "zone": "C" - }, - "planned_time_hours": 5, - "time_spent_hours": 3, - "total_tasks": 8, - "completed_tasks": 5 - }, - "actions": [ - "Assign Task", - "Reassign Task", - "Pause", - "Emergency Stop" - ], - "location": "Floor 4 . Zone B" - }, - ] return ( <> @@ -101,7 +170,7 @@ const Hrm = () => { /> */}
- {employee_details.map((employee, index) => ( + {workers.map((employee, index) => (
setSelectedCard(index)} @@ -113,13 +182,14 @@ const Hrm = () => {
-
-
{employee.employee.name}
+
+ {/*
{employee.employee.name}
*/} +
{employee.employee.employee_id}
-
View more
+
{ handleHumanClick(employee.employee) }}>View in Scene
diff --git a/app/src/components/layout/sidebarRight/resourceManagement/hrm/assetManagement/AssetManagement.tsx b/app/src/components/layout/sidebarRight/resourceManagement/hrm/assetManagement/AssetManagement.tsx index 4daa7aa..faa6015 100644 --- a/app/src/components/layout/sidebarRight/resourceManagement/hrm/assetManagement/AssetManagement.tsx +++ b/app/src/components/layout/sidebarRight/resourceManagement/hrm/assetManagement/AssetManagement.tsx @@ -1,73 +1,145 @@ -import { useState } from 'react' +import { useEffect, useState } from 'react' // import NavigateCatagory from '../../NavigateCatagory' import { EyeIcon, ForkLiftIcon, KebabIcon, LocationPinIcon, RightHalfFillCircleIcon } from '../../../../../icons/ExportCommonIcons'; import assetImage from "../../../../../../assets/image/asset-image.png" +import { useSceneContext } from '../../../../../../modules/scene/sceneContext'; +import { useProductContext } from '../../../../../../modules/simulation/products/productContext'; +import RenameInput from '../../../../../ui/inputs/RenameInput'; +import { useResourceManagementId } from '../../../../../../store/builder/store'; const AssetManagement = () => { // const [selectedCategory, setSelectedCategory] = useState("All Assets"); const [expandedAssetId, setExpandedAssetId] = useState(null); + const [assets, setAssets] = useState([]); - const dummyAssets = [ - { - id: '1', - name: 'Forklift Model X200', - model: 'FLK-0025', - status: 'Online', - usageRate: 15, - level: 'Level 1', - image: assetImage, - description: 'Electric forklift used for moving goods and materials in warehouse operations.', - cost: 122000, - count: 5, - }, - { - id: '2', - name: 'Warehouse Robot WR-300', - model: 'WRB-3001', - status: 'Online', - usageRate: 50, - level: 'Level 2', - image: assetImage, - description: 'Automated robot for handling packages and inventory in the warehouse.', - cost: 85000, - count: 3, - }, - { - id: '3', - name: 'Conveyor Belt System CB-150', - model: 'CBS-150X', - status: 'Online', - usageRate: 95, - level: 'Level 3', - image: assetImage, - description: 'High-speed conveyor belt system for efficient material handling.', - cost: 45000, - count: 2, - }, - ]; + const { productStore } = useSceneContext(); + const { products, getProductById } = productStore(); + const { selectedProductStore } = useProductContext(); + const { selectedProduct } = selectedProductStore(); + const { setResourceManagementId } = useResourceManagementId(); + + + + useEffect(() => { + if (selectedProduct) { + const productDetails = getProductById(selectedProduct.productUuid); + const productAssets = productDetails?.eventDatas || []; + const grouped: Record = {}; + productAssets.forEach((asset: any) => { + if (asset.type === "storageUnit" || asset.type === "human") return; + if (!grouped[asset.modelName]) { + grouped[asset.modelName] = { + id: asset.modelUuid, + name: asset.modelName, + model: asset.modelCode || "N/A", + status: asset.status || "Online", + usageRate: asset.usageRate || 15, + level: asset.level || "Level 1", + image: assetImage, + description: asset.description || "No description", + cost: asset.cost || 0, + count: 1, + }; + } else { + grouped[asset.modelName].count += 1; + } + }); + + setAssets(Object.values(grouped)); + } + }, [selectedProduct]); + + function handleRenameAsset(newName: string) { + // + // if (expandedAssetId) { + // setAssets(prevAssets => + // prevAssets.map(asset => + // asset.id === expandedAssetId ? { ...asset, name: newName } : asset + // ) + // ); + // } + } + + useEffect(() => { + + + }, [assets]); + + function handleAssetClick(id: string) { + + + setResourceManagementId(id); + } + + // const dummyAssets = [ + // { + // id: '1', + // name: 'Forklift Model X200', + // model: 'FLK-0025', + // status: 'Online', + // usageRate: 15, + // level: 'Level 1', + // image: assetImage, + // description: 'Electric forklift used for moving goods and materials in warehouse operations.', + // cost: 122000, + // count: 5, + // }, + // { + // id: '2', + // name: 'Warehouse Robot WR-300', + // model: 'WRB-3001', + // status: 'Online', + // usageRate: 50, + // level: 'Level 2', + // image: assetImage, + // description: 'Automated robot for handling packages and inventory in the warehouse.', + // cost: 85000, + // count: 3, + // }, + // { + // id: '3', + // name: 'Conveyor Belt System CB-150', + // model: 'CBS-150X', + // status: 'Online', + // usageRate: 95, + // level: 'Level 3', + // image: assetImage, + // description: 'High-speed conveyor belt system for efficient material handling.', + // cost: 45000, + // count: 2, + // }, + // ]; return ( <> {/* */} + category={["All Assets", "Machines", "Workstation", "Vehicles"]} + selectedCategory={selectedCategory} + setSelectedCategory={setSelectedCategory} + /> */}
- {dummyAssets.map((asset, index) => ( + {assets.map((asset, index) => (
{expandedAssetId === asset.id ? - + <> +
setExpandedAssetId(null)}>▾
+ + :
}
-
-
{asset.name}
+
+ {/*
{asset.name}
*/} + + {asset.count !== 1 &&
+ x + {asset.count} +
}
{asset.model}
@@ -98,9 +170,9 @@ const AssetManagement = () => {
-
setExpandedAssetId(null)}> +
-
View in Scene
+
handleAssetClick(asset.id)}>View in Scene
diff --git a/app/src/components/ui/Tools.tsx b/app/src/components/ui/Tools.tsx index e834f28..d5d49e4 100644 --- a/app/src/components/ui/Tools.tsx +++ b/app/src/components/ui/Tools.tsx @@ -36,6 +36,7 @@ import { } from "../../store/visualization/useDroppedObjectsStore"; import { useParams } from "react-router-dom"; import { useVersionContext } from "../../modules/builder/version/versionContext"; +import { MoveIcon, RotateIcon } from "../icons/ShortcutIcons"; // Utility component const ToolButton = ({ @@ -65,12 +66,8 @@ const Tools: React.FC = () => { const { isPlaying, setIsPlaying } = usePlayButtonStore(); const { showShortcuts } = useShortcutStore(); - const { - activeTool, - setActiveTool, - setToolMode, - setAddAction, - } = useStoreHooks(); + const { activeTool, setActiveTool, setToolMode, setAddAction } = + useStoreHooks(); const { setActiveSubTool, activeSubTool } = useActiveSubTool(); const { setSelectedWallItem } = useSelectedWallItem(); @@ -81,14 +78,15 @@ const Tools: React.FC = () => { const { selectedZone } = useSelectedZoneStore(); const { floatingWidget } = useFloatingWidget(); const { widgets3D } = use3DWidget(); - const { visualizationSocket } = useSocketStore(); - const dropdownRef = useRef(null); - const [openDrop, setOpenDrop] = useState(false); + const { visualizationSocket } = useSocketStore(); const { selectedVersionStore } = useVersionContext(); const { selectedVersion } = selectedVersionStore(); const { projectId } = useParams(); + const dropdownRef = useRef(null); + const [openDrop, setOpenDrop] = useState(false); + // 1. Set UI toggles on initial render useEffect(() => { setToggleUI( @@ -155,7 +153,7 @@ const Tools: React.FC = () => { if (!is2D) setAddAction("Pillar"); break; case "delete": - is2D ? setToolMode('2D-Delete') : setToolMode('3D-Delete'); + is2D ? setToolMode("2D-Delete") : setToolMode("3D-Delete"); break; } }; @@ -251,7 +249,7 @@ const Tools: React.FC = () => { templates, visualizationSocket, projectId, - versionId: selectedVersion?.versionId || '' + versionId: selectedVersion?.versionId || "", }) } /> @@ -278,6 +276,10 @@ const Tools: React.FC = () => { return FreeMoveIcon; case "delete": return DeleteIcon; + case "move": + return MoveIcon; + case "rotate": + return RotateIcon; default: return CursorIcon; } @@ -304,6 +306,10 @@ const Tools: React.FC = () => { return ; case "delete": return ; + case "move": + return ; + case "rotate": + return ; default: return null; } @@ -362,6 +368,24 @@ const Tools: React.FC = () => { )}
+ {activeModule !== "visualization" && ( + <> +
+
+ {["move", "rotate"].map((tool) => ( + setActiveTool(tool)} + /> + ))} +
+ + )} +
{activeModule === "builder" && renderBuilderTools()} {activeModule === "simulation" && renderSimulationTools()} diff --git a/app/src/components/ui/collaboration/Messages.tsx b/app/src/components/ui/collaboration/Messages.tsx index b3f37e1..11e87b2 100644 --- a/app/src/components/ui/collaboration/Messages.tsx +++ b/app/src/components/ui/collaboration/Messages.tsx @@ -231,7 +231,10 @@ const Messages: React.FC = ({ val, i, setMessages, mode, setIsEdit
{isEditableThread ? getRelativeTime(val.createdAt) : val.createdAt}
{(val as Reply).creatorId === userId && ( -
+
setOpenOptions(false)} + > + {openOptions && (
- {!(isEditableThread) && } + + {!isEditableThread && ( + + )}
)}
)} +
{"comment" in val ? val.comment : val.threadTitle}
+
)} diff --git a/app/src/components/ui/collaboration/ThreadChat.tsx b/app/src/components/ui/collaboration/ThreadChat.tsx index 8e4b24b..5370689 100644 --- a/app/src/components/ui/collaboration/ThreadChat.tsx +++ b/app/src/components/ui/collaboration/ThreadChat.tsx @@ -131,9 +131,10 @@ const ThreadChat: React.FC = () => { if (dragging) updatePosition(e, true); }; - useEffect(() => { - updatePosition({ clientX: position.x, clientY: position.y }, true); - }, [selectedComment]); + // Commented this useEffect to prevent offset after user saved the comment + // useEffect(() => { + // updatePosition({ clientX: position.x, clientY: position.y }, true); + // }, [selectedComment]); const handlePointerUp = (event: React.PointerEvent) => { @@ -144,6 +145,10 @@ const ThreadChat: React.FC = () => { }; const handleCreateComments = async (e: any) => { + // Continue send or create message only there is only value avalibale + // To prevent empty value + + if (!value) return; e.preventDefault(); try { // const createComments = await addCommentsApi(projectId, value, selectedComment?.threadId, selectedVersion?.versionId || "")/ @@ -163,6 +168,7 @@ const ThreadChat: React.FC = () => { // } + if (threadSocket && mode === "create") { const addComment = { versionId: selectedVersion?.versionId || "", @@ -190,7 +196,7 @@ const ThreadChat: React.FC = () => { // removeComment(selectedComment?.threadId) // setSelectedComment([]) // } - console.log('threadSocket:threadChat ', threadSocket); + if (threadSocket) { // projectId, userId, organization, threadId const deleteThread = { @@ -258,7 +264,7 @@ const ThreadChat: React.FC = () => { }; if (threadSocket) { - console.log('createThread: ', createThread); + setInputActive(false); threadSocket.emit("v1:thread:create", createThread); diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx index 6792fa4..8f38189 100644 --- a/app/src/components/ui/list/List.tsx +++ b/app/src/components/ui/list/List.tsx @@ -57,6 +57,7 @@ const List: React.FC = ({ items = [], remove }) => { const { zoneStore } = useSceneContext(); const { zones, setZoneName } = zoneStore(); + useEffect(() => { useSelectedZoneStore.getState().setSelectedZone({ zoneName: "", @@ -121,6 +122,7 @@ const List: React.FC = ({ items = [], remove }) => { } function handleAssetClick(asset: Asset) { + setZoneAssetId(asset); } @@ -157,8 +159,9 @@ const List: React.FC = ({ items = [], remove }) => { modelUuid: zoneAssetId.id, modelName: newName, projectId, + versionId: selectedVersion?.versionId || '' + }); - // console.log("response: ", response); setName(zoneAssetId.id, response.modelName); } @@ -255,9 +258,8 @@ const List: React.FC = ({ items = [], remove }) => { }} >