Merge remote-tracking branch 'origin/dev-resourceManagement' into main-demo
This commit is contained in:
@@ -336,18 +336,35 @@ export const MachineIcon = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const CraneIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M18.5 5.7502L12.875 1.3752C12.6875 1.1877 12.375 1.1877 12.125 1.3127L5.4375 5.6252H1.875C1.5 5.6252 1.25 5.8752 1.25 6.2502C1.25 6.6252 1.5 6.8752 1.875 6.8752H4.375V10.0002H1.875C1.5 10.0002 1.25 10.2502 1.25 10.6252V13.7502C1.25 14.1252 1.5 14.3752 1.875 14.3752H8.125C8.5 14.3752 8.75 14.1252 8.75 13.7502V10.6252C8.75 10.2502 8.5 10.0002 8.125 10.0002H5.625V6.8752H10.625V15.9377L8.375 17.6252C8.1875 17.8127 8.0625 18.0627 8.1875 18.3127C8.25 18.5627 8.5 18.7502 8.75 18.7502H16.25C16.5 18.7502 16.75 18.5627 16.8125 18.3127C16.875 18.0627 16.8125 17.7502 16.625 17.6252L14.375 15.9377V6.8752H18.125C18.375 6.8752 18.625 6.6877 18.6875 6.4377C18.8125 6.1877 18.75 5.9377 18.5 5.7502ZM3.6875 11.2502L2.5 12.7502V11.2502H3.6875ZM5 11.6252L6.1875 13.1252H3.8125L5 11.6252ZM7.5 12.7502L6.3125 11.2502H7.5V12.7502ZM11.875 3.0002V5.6252H11.25H7.75L11.875 3.0002ZM13.75 5.6252H13.125V3.1252L16.3125 5.6252H13.75Z"
|
||||||
|
fill="white"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type TypeBasedAssetIconsProps = {
|
type TypeBasedAssetIconsProps = {
|
||||||
assetType: string;
|
assetType: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function TypeBasedAssetIcons({ assetType }: TypeBasedAssetIconsProps) {
|
export function TypeBasedAssetIcons({ assetType }: TypeBasedAssetIconsProps) {
|
||||||
console.log("assetType: ", assetType);
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{assetType === "machine" && <MachineIcon />}
|
{assetType === "StaticMachine" && <MachineIcon />}
|
||||||
{assetType === "vehicle" && <ForkLiftIcon />}
|
{assetType === "Vehicle" && <ForkLiftIcon />}
|
||||||
{assetType === "transfer" && <ConveyorIcon />}
|
{assetType === "Conveyor" && <ConveyorIcon />}
|
||||||
{assetType === "roboticArm" && <RoboticArmIcon />}
|
{assetType === "Crane" && <CraneIcon />}
|
||||||
|
{assetType === "ArmBot" && <RoboticArmIcon />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,199 +1,200 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { ClockThreeIcon, LocationPinIcon, TargetIcon } from '../../../../icons/ExportCommonIcons'
|
import { ClockThreeIcon, LocationPinIcon, TargetIcon } from '../../../../icons/ExportCommonIcons'
|
||||||
import { useSceneContext } from '../../../../../modules/scene/sceneContext';
|
import { useSceneContext } from '../../../../../modules/scene/sceneContext';
|
||||||
import { useProductContext } from '../../../../../modules/simulation/products/productContext';
|
|
||||||
import RenameInput from '../../../../ui/inputs/RenameInput';
|
import RenameInput from '../../../../ui/inputs/RenameInput';
|
||||||
import { useResourceManagementId } from '../../../../../store/builder/store';
|
import { useResourceManagementId } from '../../../../../store/builder/store';
|
||||||
import { set } from 'immer/dist/internal';
|
import { getAssetThumbnail } from '../../../../../services/factoryBuilder/asset/assets/getAssetThumbnail';
|
||||||
// import NavigateCatagory from '../NavigateCatagory'
|
// import NavigateCatagory from '../NavigateCatagory'
|
||||||
|
|
||||||
const Hrm = () => {
|
const Hrm = () => {
|
||||||
const [selectedCard, setSelectedCard] = useState(0);
|
const [selectedCard, setSelectedCard] = useState(0);
|
||||||
const [workers, setWorkers] = useState<any[]>([]);
|
const [workers, setWorkers] = useState<any[]>([]);
|
||||||
|
|
||||||
const { productStore } = useSceneContext();
|
|
||||||
const { products, getProductById } = productStore();
|
|
||||||
const { selectedProductStore } = useProductContext();
|
|
||||||
const { selectedProduct } = selectedProductStore();
|
|
||||||
const { setResourceManagementId } = useResourceManagementId();
|
const { setResourceManagementId } = useResourceManagementId();
|
||||||
|
const { assetStore } = useSceneContext();
|
||||||
|
const { assets: allAssets } = assetStore();
|
||||||
|
|
||||||
useEffect(() => {
|
async function getAsset(assetId: string) {
|
||||||
if (selectedProduct) {
|
let thumbnail = await getAssetThumbnail(assetId)
|
||||||
const productDetails = getProductById(selectedProduct.productUuid);
|
if (thumbnail.thumbnail) {
|
||||||
const workerDetails = productDetails?.eventDatas || [];
|
let assetImage = thumbnail.thumbnail
|
||||||
|
return assetImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const formattedWorkers = workerDetails
|
useEffect(() => {
|
||||||
.filter((worker: any) => worker.type === "human")
|
if (allAssets.length > 0) {
|
||||||
.map((worker: any, index: number) => ({
|
const fetchWorkers = async () => {
|
||||||
employee: {
|
const humans = allAssets.filter((worker: any) => worker.eventData.type === "Human");
|
||||||
image: "",
|
|
||||||
name: worker.modelName,
|
const formattedWorkers = await Promise.all(
|
||||||
modelId: worker.modelUuid,
|
humans.map(async (worker: any, index: number) => {
|
||||||
employee_id: `HR-${204 + index}`,
|
const assetImage = await getAsset(worker.assetId);
|
||||||
status: "Active",
|
|
||||||
},
|
return {
|
||||||
task: {
|
employee: {
|
||||||
status: "Ongoing",
|
image: assetImage,
|
||||||
title: worker.taskTitle || "No Task Assigned",
|
name: worker.modelName,
|
||||||
location: {
|
modelId: worker.modelUuid,
|
||||||
floor: worker.floor || 0,
|
employee_id: `HR-${204 + index}`,
|
||||||
zone: worker.zone || "N/A"
|
status: "Active",
|
||||||
},
|
},
|
||||||
planned_time_hours: worker.plannedTime || 0,
|
task: {
|
||||||
time_spent_hours: worker.timeSpent || 0,
|
status: "Ongoing",
|
||||||
total_tasks: worker.totalTasks || 0,
|
title: worker.taskTitle ?? "No Task Assigned",
|
||||||
completed_tasks: worker.completedTasks || 0
|
location: {
|
||||||
},
|
floor: worker.floor ?? 0,
|
||||||
actions: [
|
zone: worker.zone ?? "N/A",
|
||||||
"Assign Task",
|
},
|
||||||
"Reassign Task",
|
planned_time_hours: worker.plannedTime ?? 0,
|
||||||
"Pause",
|
time_spent_hours: worker.timeSpent ?? 0,
|
||||||
"Emergency Stop"
|
total_tasks: worker.totalTasks ?? 0,
|
||||||
],
|
completed_tasks: worker.completedTasks ?? 0,
|
||||||
location: `Floor ${worker.floor || "-"} . Zone ${worker.zone || "-"}`
|
},
|
||||||
}));
|
actions: ["Assign Task", "Reassign Task", "Pause", "Emergency Stop"],
|
||||||
|
location: `Floor ${worker.floor || "-"} . Zone ${worker.zone || "-"}`,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
setWorkers(formattedWorkers);
|
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) {
|
|
||||||
//
|
|
||||||
|
|
||||||
|
fetchWorkers();
|
||||||
}
|
}
|
||||||
function handleHumanClick(employee: any) {
|
}, [allAssets]);
|
||||||
if (employee.modelId) {
|
|
||||||
setResourceManagementId(employee.modelId);
|
|
||||||
}
|
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* <NavigateCatagory
|
{/* <NavigateCatagory
|
||||||
category={["All People", "Technician", "Operator", "Supervisor", "Safety Officer"]}
|
category={["All People", "Technician", "Operator", "Supervisor", "Safety Officer"]}
|
||||||
selectedCategory={selectedCategory}
|
selectedCategory={selectedCategory}
|
||||||
setSelectedCategory={setSelectedCategory}
|
setSelectedCategory={setSelectedCategory}
|
||||||
/> */}
|
/> */}
|
||||||
|
|
||||||
<div className='hrm-container assetManagement-wrapper'>
|
<div className='hrm-container assetManagement-wrapper'>
|
||||||
{workers.map((employee, index) => (
|
{workers.map((employee, index) => (
|
||||||
<div
|
<div
|
||||||
className={`analysis-wrapper ${selectedCard === index ? "active" : ""}`}
|
className={`analysis-wrapper ${selectedCard === index ? "active" : ""}`}
|
||||||
onClick={() => setSelectedCard(index)}
|
onClick={() => setSelectedCard(index)}
|
||||||
key={index}
|
key={index}
|
||||||
>
|
>
|
||||||
<header>
|
<header>
|
||||||
<div className="user-details">
|
<div className="user-details">
|
||||||
<div className="user-image-wrapper">
|
<div className="user-image-wrapper">
|
||||||
<img className='user-image' src={employee.employee.image} alt="" />
|
<img className='user-image' src={employee.employee.image} alt="" />
|
||||||
<div className={`status ${employee.employee.status}`}></div>
|
<div className={`status ${employee.employee.status}`}></div>
|
||||||
</div>
|
|
||||||
<div className="details" >
|
|
||||||
{/* <div className="employee-name">{employee.employee.name}</div> */}
|
|
||||||
<RenameInput value={employee.employee.name} onRename={handleRenameWorker} />
|
|
||||||
<div className="employee-id">{employee.employee.employee_id}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="details" >
|
||||||
|
{/* <div className="employee-name">{employee.employee.name}</div> */}
|
||||||
|
<RenameInput value={employee.employee.name} onRename={handleRenameWorker} />
|
||||||
|
<div className="employee-id">{employee.employee.employee_id}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="see-more" onClick={() => { handleHumanClick(employee.employee) }}>View in Scene</div>
|
<div className="see-more" onClick={() => { handleHumanClick(employee.employee) }}>View in Scene</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className="content">
|
<div className="content">
|
||||||
{/* <div className="task-info">
|
{/* <div className="task-info">
|
||||||
<div className="task-wrapper">
|
<div className="task-wrapper">
|
||||||
<div className="task-label">
|
<div className="task-label">
|
||||||
<span className='label-icon'><ListTaskIcon /></span>
|
<span className='label-icon'><ListTaskIcon /></span>
|
||||||
@@ -214,17 +215,17 @@ const Hrm = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|
||||||
<div className="task-stats">
|
<div className="task-stats">
|
||||||
<div className="stat-item">
|
<div className="stat-item">
|
||||||
|
|
||||||
<div className="stat-wrapper">
|
<div className="stat-wrapper">
|
||||||
<span className="stat-icon"><ClockThreeIcon /></span>
|
<span className="stat-icon"><ClockThreeIcon /></span>
|
||||||
<span>Planned time:</span>
|
<span>Planned time:</span>
|
||||||
</div>
|
|
||||||
|
|
||||||
<span className='stat-value'>{employee.task.planned_time_hours} hr</span>
|
|
||||||
</div>
|
</div>
|
||||||
{/* <div className="stat-item">
|
|
||||||
|
<span className='stat-value'>{employee.task.planned_time_hours} hr</span>
|
||||||
|
</div>
|
||||||
|
{/* <div className="stat-item">
|
||||||
|
|
||||||
<div className="stat-wrapper">
|
<div className="stat-wrapper">
|
||||||
<span className="stat-icon"><SlectedTickIcon /></span>
|
<span className="stat-icon"><SlectedTickIcon /></span>
|
||||||
@@ -242,39 +243,39 @@ const Hrm = () => {
|
|||||||
|
|
||||||
<span className='stat-value'>{employee.task.time_spent_hours} hr</span>
|
<span className='stat-value'>{employee.task.time_spent_hours} hr</span>
|
||||||
</div> */}
|
</div> */}
|
||||||
<div className="stat-item">
|
<div className="stat-item">
|
||||||
|
|
||||||
<div className="stat-wrapper">
|
<div className="stat-wrapper">
|
||||||
<span className="stat-icon"><TargetIcon /></span>
|
<span className="stat-icon"><TargetIcon /></span>
|
||||||
<span>Cost per hr:</span>
|
<span>Cost per hr:</span>
|
||||||
</div>
|
|
||||||
|
|
||||||
<span className='stat-value'>{employee.task.completed_tasks}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="location-wrapper">
|
<span className='stat-value'>{employee.task.completed_tasks}</span>
|
||||||
<div className="location-header">
|
|
||||||
<div className="icon">
|
|
||||||
<LocationPinIcon />
|
|
||||||
</div>
|
|
||||||
<div className="header">Location:</div>
|
|
||||||
</div>
|
|
||||||
<div className="location-value">{employee.location}</div>
|
|
||||||
</div>
|
|
||||||
<div className="task-actions">
|
|
||||||
{/* <button className="btn btn-default">Assign Task</button>
|
|
||||||
<button className="btn btn-default">Reassign Task</button> */}
|
|
||||||
<button className="btn btn-default">Pause</button>
|
|
||||||
<button className="btn btn-danger">Emergency Stop</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="location-wrapper">
|
||||||
|
<div className="location-header">
|
||||||
|
<div className="icon">
|
||||||
|
<LocationPinIcon />
|
||||||
|
</div>
|
||||||
|
<div className="header">Location:</div>
|
||||||
|
</div>
|
||||||
|
<div className="location-value">{employee.location}</div>
|
||||||
|
</div>
|
||||||
|
<div className="task-actions">
|
||||||
|
{/* <button className="btn btn-default">Assign Task</button>
|
||||||
|
<button className="btn btn-default">Reassign Task</button> */}
|
||||||
|
<button className="btn btn-default">Pause</button>
|
||||||
|
<button className="btn btn-danger">Emergency Stop</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
))}
|
||||||
)
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Hrm
|
export default Hrm
|
||||||
|
|||||||
@@ -1,65 +1,70 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
// import NavigateCatagory from '../../NavigateCatagory'
|
// import NavigateCatagory from '../../NavigateCatagory'
|
||||||
import { EyeIcon, KebabIcon, LocationPinIcon, RightHalfFillCircleIcon } from '../../../../../icons/ExportCommonIcons';
|
import { EyeIcon, KebabIcon, LocationPinIcon, RightHalfFillCircleIcon } from '../../../../../icons/ExportCommonIcons';
|
||||||
import assetImage from "../../../../../../assets/image/asset-image.png"
|
import assetImageFallback from "../../../../../../assets/image/asset-image.png"
|
||||||
import { useSceneContext } from '../../../../../../modules/scene/sceneContext';
|
import { useSceneContext } from '../../../../../../modules/scene/sceneContext';
|
||||||
import { useProductContext } from '../../../../../../modules/simulation/products/productContext';
|
|
||||||
import RenameInput from '../../../../../ui/inputs/RenameInput';
|
import RenameInput from '../../../../../ui/inputs/RenameInput';
|
||||||
import { useResourceManagementId } from '../../../../../../store/builder/store';
|
import { useResourceManagementId } from '../../../../../../store/builder/store';
|
||||||
|
import { getAssetThumbnail } from '../../../../../../services/factoryBuilder/asset/assets/getAssetThumbnail';
|
||||||
import { TypeBasedAssetIcons } from '../../../../../icons/AssetTypeIcons';
|
import { TypeBasedAssetIcons } from '../../../../../icons/AssetTypeIcons';
|
||||||
|
|
||||||
const AssetManagement = () => {
|
const AssetManagement = () => {
|
||||||
// const [selectedCategory, setSelectedCategory] = useState("All Assets");
|
// const [selectedCategory, setSelectedCategory] = useState("All Assets");
|
||||||
const [expandedAssetId, setExpandedAssetId] = useState<string | null>(null);
|
const [expandedAssetId, setExpandedAssetId] = useState<string | null>(null);
|
||||||
const [assets, setAssets] = useState<any[]>([]);
|
const [assets, setAssets] = useState<any[]>([]);
|
||||||
|
|
||||||
const { productStore } = useSceneContext();
|
|
||||||
const { getProductById } = productStore();
|
|
||||||
const { selectedProductStore } = useProductContext();
|
|
||||||
const { selectedProduct } = selectedProductStore();
|
|
||||||
const { setResourceManagementId } = useResourceManagementId();
|
const { setResourceManagementId } = useResourceManagementId();
|
||||||
|
const { assetStore } = useSceneContext();
|
||||||
|
const { assets: allAssets } = assetStore();
|
||||||
|
|
||||||
|
async function getAsset(assetId: string) {
|
||||||
|
let thumbnail = await getAssetThumbnail(assetId)
|
||||||
|
if (thumbnail.thumbnail) {
|
||||||
|
let assetImage = thumbnail.thumbnail ?? assetImageFallback;
|
||||||
|
return assetImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedProduct) {
|
if (allAssets.length > 0) {
|
||||||
const productDetails = getProductById(selectedProduct.productUuid);
|
const fetchAssets = async () => {
|
||||||
const productAssets = productDetails?.eventDatas || [];
|
const grouped: Record<string, any> = {};
|
||||||
const grouped: Record<string, any> = {};
|
|
||||||
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,
|
|
||||||
type: asset.type,
|
|
||||||
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));
|
// Use Promise.all to handle all async operations
|
||||||
|
await Promise.all(allAssets.map(async (asset: any) => {
|
||||||
|
|
||||||
|
if (asset.eventData.type === "Storage" || asset.eventData.type === "Human") return;
|
||||||
|
|
||||||
|
const assetImage = await getAsset(asset.assetId);
|
||||||
|
|
||||||
|
if (!grouped[asset.assetId]) {
|
||||||
|
//
|
||||||
|
grouped[asset.assetId] = {
|
||||||
|
id: asset.modelUuid,
|
||||||
|
assetId: asset.assetId,
|
||||||
|
name: asset.modelName,
|
||||||
|
type: asset.eventData.type,
|
||||||
|
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.assetId].count += 1;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
setAssets(Object.values(grouped));
|
||||||
|
}
|
||||||
|
fetchAssets();
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line
|
}, [allAssets]);
|
||||||
}, [selectedProduct]);
|
|
||||||
|
|
||||||
function handleRenameAsset(newName: string) {
|
function handleRenameAsset(newName: string) {
|
||||||
//
|
|
||||||
// if (expandedAssetId) {
|
|
||||||
// setAssets(prevAssets =>
|
|
||||||
// prevAssets.map(asset =>
|
|
||||||
// asset.id === expandedAssetId ? { ...asset, name: newName } : asset
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -68,8 +73,6 @@ const AssetManagement = () => {
|
|||||||
}, [assets]);
|
}, [assets]);
|
||||||
|
|
||||||
function handleAssetClick(id: string) {
|
function handleAssetClick(id: string) {
|
||||||
|
|
||||||
|
|
||||||
setResourceManagementId(id);
|
setResourceManagementId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +129,6 @@ const AssetManagement = () => {
|
|||||||
<div className={`assetManagement-card-wrapper ${expandedAssetId === asset.id ? "openViewMore" : ""}`} key={index}>
|
<div className={`assetManagement-card-wrapper ${expandedAssetId === asset.id ? "openViewMore" : ""}`} key={index}>
|
||||||
<header>
|
<header>
|
||||||
<div className="header-wrapper">
|
<div className="header-wrapper">
|
||||||
|
|
||||||
{expandedAssetId === asset.id ?
|
{expandedAssetId === asset.id ?
|
||||||
<>
|
<>
|
||||||
<div className="drop-icon" onClick={() => setExpandedAssetId(null)}>▾</div>
|
<div className="drop-icon" onClick={() => setExpandedAssetId(null)}>▾</div>
|
||||||
@@ -173,9 +175,9 @@ const AssetManagement = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="asset-estimate__view-button">
|
<div className="asset-estimate__view-button" onClick={() => handleAssetClick(asset.id)}>
|
||||||
<EyeIcon isClosed={false} />
|
<EyeIcon isClosed={false} />
|
||||||
<div className="asset-estimate__view-text" onClick={() => handleAssetClick(asset.id)}>View in Scene</div>
|
<div className="asset-estimate__view-text">View in Scene</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||||
|
|
||||||
|
export const getAssetThumbnail = async (assetId: String) => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${url_Backend_dwinzo}/api/v2/getAssetThumbnail/${assetId}`,
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer <access_token>",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
token: localStorage.getItem("token") || "",
|
||||||
|
refresh_token: localStorage.getItem("refreshToken") || "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const newAccessToken = response.headers.get("x-access-token");
|
||||||
|
if (newAccessToken) {
|
||||||
|
localStorage.setItem("token", newAccessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to fetch assets");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return await response.json();
|
||||||
|
} catch (error: any) {
|
||||||
|
echo.error("Failed to get asset image");
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -117,6 +117,12 @@
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
.user-image{
|
||||||
|
height: 300%;
|
||||||
|
width: 300%;
|
||||||
|
transform: translate(-26px, -12px);
|
||||||
|
}
|
||||||
|
|
||||||
.status {
|
.status {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|||||||
Reference in New Issue
Block a user