feat: Add Resource Management module with HRM and Asset Management features

- Introduced FilePackageIcon component for resource management.
- Updated MainScene to include resource management functionality.
- Enhanced SideBarRight to support resource management display.
- Created NavigateCategory component for category navigation in resource management.
- Developed ResourceManagement component to switch between HRM and Asset Management views.
- Implemented Hrm component to display employee details and tasks.
- Added AssetManagement component to manage and display asset information.
- Updated useModuleStore to include resourceManagement as a submodule.
- Created resourceManagement.scss for styling the new module.
- Removed hrm.scss as its styles have been integrated into resourceManagement.scss.
- Updated main.scss to import resourceManagement styles instead of hrm.
This commit is contained in:
Nalvazhuthi
2025-08-22 12:44:55 +05:30
parent 31c07e92b4
commit dc873a8c59
15 changed files with 873 additions and 328 deletions

View File

@@ -3,6 +3,7 @@ import Header from "./Header";
import useModuleStore, { useSubModuleStore } from "../../../store/useModuleStore";
import {
AnalysisIcon,
FilePackageIcon,
MechanicsIcon,
PropertiesIcon,
SimulationIcon,
@@ -33,7 +34,7 @@ import FloorProperties from "./properties/FloorProperties";
import SelectedWallProperties from "./properties/SelectedWallProperties";
import SelectedFloorProperties from "./properties/SelectedFloorProperties";
import DecalTransformation from "./decals/DecalTransformation";
import Hrm from "./hrm/Hrm";
import ResourceManagement from "./resourceManagement/ResourceManagement";
type DisplayComponent =
| "versionHistory"
@@ -50,6 +51,7 @@ type DisplayComponent =
| "analysis"
| "visualization"
| "decals"
| "resourceManagement"
| "none";
const SideBarRight: React.FC = () => {
@@ -105,6 +107,19 @@ const SideBarRight: React.FC = () => {
setDisplayComponent("analysis");
return;
}
if (subModule === "resourceManagement") {
setDisplayComponent("resourceManagement");
return;
}
}
if (activeModule === "simulation" || activeModule === "builder") {
if (subModule === "resourceManagement") {
setDisplayComponent("resourceManagement");
return;
}
}
if (subModule === "properties" && activeModule !== "visualization") {
@@ -129,7 +144,7 @@ const SideBarRight: React.FC = () => {
return;
}
if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedSubCategory) {
console.log('selectedSubCategory: ', selectedSubCategory);
if (toolMode === "Aisle") {
setDisplayComponent("aisleProperties");
@@ -146,6 +161,7 @@ const SideBarRight: React.FC = () => {
setDisplayComponent("globalProperties");
return;
}
}
if (subModule === "zoneProperties" && (activeModule === "builder" || activeModule === "simulation")) {
@@ -157,6 +173,7 @@ const SideBarRight: React.FC = () => {
}, [viewVersionHistory, activeModule, subModule, isVersionSaved, selectedFloorItem, selectedWall, selectedFloor, selectedAisle, toolMode, selectedSubCategory]);
const renderComponent = () => {
switch (displayComponent) {
case "versionHistory":
return <VersionHistory />;
@@ -186,6 +203,8 @@ const SideBarRight: React.FC = () => {
return <Visualization />;
case "decals":
return <DecalTransformation />;
case "resourceManagement":
return <ResourceManagement />;
default:
return null;
}
@@ -201,19 +220,23 @@ const SideBarRight: React.FC = () => {
<>
{(!isVersionSaved || activeModule !== "simulation") && (
<div className="sidebar-actions-container">
{activeModule !== "simulation" && (
<button
id="sidebar-action-list-properties"
className={`sidebar-action-list ${subModule === "properties" ? "active" : ""}`}
onClick={() => {
setSubModule("properties");
setVersionHistoryVisible(false);
}}
>
<div className="tooltip">properties</div>
<PropertiesIcon isActive={subModule === "properties"} />
</button>
<>
<button
id="sidebar-action-list-properties"
className={`sidebar-action-list ${subModule === "properties" ? "active" : ""}`}
onClick={() => {
setSubModule("properties");
setVersionHistoryVisible(false);
}}
>
<div className="tooltip">properties</div>
<PropertiesIcon isActive={subModule === "properties"} />
</button>
</>
)}
{activeModule === "simulation" && (
<>
<button
@@ -251,6 +274,21 @@ const SideBarRight: React.FC = () => {
</button>
</>
)}
{(activeModule === "builder" || activeModule === "simulation") && (
<button
id="sidebar-action-list-properties"
className={`sidebar-action-list ${subModule === "resourceManagement" ? "active" : ""}`}
onClick={() => {
setSubModule("resourceManagement");
setVersionHistoryVisible(false);
}}
>
<div className="tooltip">Resource Management</div>
<FilePackageIcon isActive={subModule === "resourceManagement"} />
</button>
)}
</div>
)}
@@ -258,7 +296,7 @@ const SideBarRight: React.FC = () => {
<div className="sidebar-right-container">
<div className="sidebar-right-content-container">
{renderComponent()}
{/* <Hrm /> */}
{/* <ResourceManagement /> */}
</div>
</div>
)}

View File

@@ -0,0 +1,25 @@
import React from 'react';
interface Props {
category: string[];
selectedCategory: string;
setSelectedCategory: (cat: string) => void;
}
const NavigateCategory = ({ category, selectedCategory, setSelectedCategory }: Props) => {
return (
<div className="category-wrapper">
{category.map((cat) => (
<div
key={cat}
className={`category ${selectedCategory === cat ? "active" : ''}`}
onClick={() => setSelectedCategory(cat)}
>
{cat}
</div>
))}
</div>
);
};
export default NavigateCategory;

View File

@@ -0,0 +1,48 @@
import React, { useState } from 'react'
import Search from '../../../ui/inputs/Search'
import RegularDropDown from '../../../ui/inputs/RegularDropDown'
import Hrm from './hrm/Hrm'
import AssetManagement from './hrm/assetManagement/AssetManagement'
const ResourceManagement = () => {
type DisplayType = "hrm" | "asset";
const [selectType, setSelectType] = useState("assetManagement")
const [display, setDisplay] = useState<DisplayType>("asset");
return (
<div className='resourceManagement-container'>
<div className="navigation-wrapper">
<div
className={`navigation ${selectType === "assetManagement" ? "active" : ""}`}
onClick={() => setSelectType("assetManagement")}
>
Asset Management
</div>
<div
className={`navigation ${selectType === "peopleOperation" ? "active" : ""}`}
onClick={() => setSelectType("peopleOperation")}
>
People Operations
</div>
</div>
<div className="search-container">
<Search onChange={() => { }} />
<div className="select-catagory">
<RegularDropDown
header={"floor"}
options={["floor"]} // Pass layout names as options
onSelect={() => { }}
search={false}
/>
</div>
</div>
{selectType === "assetManagement" ? <AssetManagement /> : <Hrm />}
</div>
)
}
export default ResourceManagement

View File

@@ -1,11 +1,10 @@
import React, { useState } from 'react'
import Search from '../../../ui/inputs/Search'
import RegularDropDown from '../../../ui/inputs/RegularDropDown'
import { ClockThreeIcon, HourGlassIcon, ListTaskIcon, LocationPinIcon, SlectedTickIcon, TargetIcon } from '../../../icons/ExportCommonIcons'
import Search from '../../../../ui/inputs/Search'
import RegularDropDown from '../../../../ui/inputs/RegularDropDown'
import { ClockThreeIcon, HourGlassIcon, ListTaskIcon, LocationPinIcon, SlectedTickIcon, TargetIcon } from '../../../../icons/ExportCommonIcons'
import NavigateCatagory from '../NavigateCatagory'
const Hrm = () => {
const [selectType, setSelectType] = useState("assetManagement")
const [selectcatogory, setSelectCatogary] = useState("All People")
const employee_details = [
{
"employee": {
@@ -93,50 +92,23 @@ const Hrm = () => {
}
]
const [selectedCard, setSelectedCard] = useState(0);
console.log('selectedCard: ', selectedCard);
return (
<div className='hrm-container'>
<div className="navigation-wrapper">
<div
className={`navigation ${selectType === "assetManagement" ? "active" : ""}`}
onClick={() => setSelectType("assetManagement")}
>
Asset Management
</div>
<div
className={`navigation ${selectType === "peopleOperation" ? "active" : ""}`}
onClick={() => setSelectType("peopleOperation")}
>
People Operations
</div>
</div>
<>
{/* <NavigateCatagory
category={["All People", "Technician", "Operator", "Supervisor", "Safety Officer"]}
selectedCategory={selectedCategory}
setSelectedCategory={setSelectedCategory}
/> */}
<div className="search-container">
<Search onChange={() => { }} />
<div className="select-catagory">
<RegularDropDown
header={"floor"}
options={["floor"]} // Pass layout names as options
onSelect={() => { }}
search={false}
/>
</div>
</div>
<div className="catagories-wrapper">
{["All People", "Technician", "Operator", "Supervisor", "Safety Officer"].map((cat, index) => (
<div
key={cat}
className={`catagory ${selectcatogory === cat ? "active" : ''}`}
onClick={() => setSelectCatogary(cat)}
>
{cat}
</div>
))}
</div>
<div className="analysis-container">
<div className='hrm-container assetManagement-wrapper'>
{employee_details.map((employee, index) => (
<div className="analysis-wrapper">
<div
className={`analysis-wrapper ${selectedCard === index ? "active" : ""}`}
onClick={() => setSelectedCard(index)}
>
<header>
<div className="user-details">
<div className="user-image-wrapper">
@@ -206,7 +178,7 @@ const Hrm = () => {
<div className="stat-wrapper">
<span className="stat-icon"><TargetIcon /></span>
<span>Completed Tasks:</span>
<span>Cost per hr:</span>
</div>
<span className='stat-value'>{employee.task.completed_tasks}</span>
@@ -233,7 +205,7 @@ const Hrm = () => {
</div>
))}
</div>
</div>
</>
)
}

View File

@@ -0,0 +1,159 @@
import React, { useState } from 'react'
import NavigateCatagory from '../../NavigateCatagory'
import { EyeIcon, ForkLiftIcon, KebabIcon, LocationPinIcon, RightHalfFillCircleIcon } from '../../../../../icons/ExportCommonIcons';
import assetImage from "../../../../../../assets/image/asset-image.png"
const AssetManagement = () => {
const [selectedCategory, setSelectedCategory] = useState("All Assets");
const [expandedAssetId, setExpandedAssetId] = useState<string | null>(null);
const dummyAssets = [
{
id: '1',
name: 'Forklift Model X200',
model: 'FLK-0025',
status: 'Online',
usageRate: 89,
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: 76,
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 (
<>
{/* <NavigateCatagory
category={["All Assets", "Machines", "Workstation", "Vehicles"]}
selectedCategory={selectedCategory}
setSelectedCategory={setSelectedCategory}
/> */}
<div className='assetManagement-container'>
{dummyAssets.map((asset, index) => (
<div className={`assetManagement-wrapper ${expandedAssetId === asset.id ? "openViewMore" : ""}`}>
<header>
<div className="header-wrapper">
{expandedAssetId === asset.id ?
<img className='asset-image' src={asset.image} alt="" />
:
<div className="icon"><ForkLiftIcon /></div>
}
<div className="asset-details-container">
<div className="asset-details">
<div className="asset-name">{asset.name}</div>
<div className="asset-model">{asset.model}</div>
</div>
<div className="asset-status-wrapper">
<div className={`indication ${asset.status}`}></div>
<div className="status">{asset.status}</div>
</div>
</div>
</div>
{expandedAssetId === asset.id && <div className="description">{asset.description}</div>}
</header>
{expandedAssetId === asset.id ? (
<div className="asset-estimate">
<div className="asset-estimate__unit-cost">
<div className="asset-estimate__label">Cost of Asset</div>
<div className="asset-estimate__value"> 1,22,000</div>
</div>
<div className="asset-estimate__breakdown">
<div className="asset-estimate__in-scene">
<div className="asset-estimate__label">In Scene</div>
<div className="asset-estimate__value">5 items</div>
</div>
<div className="asset-estimate__total-cost">
<div className="asset-estimate__label">Total Cost</div>
<div className="asset-estimate__value"> 6,10,000</div>
</div>
</div>
<div className="asset-estimate__view-button" onClick={() => setExpandedAssetId(null)}>
<EyeIcon isClosed={false} />
<div className="asset-estimate__view-text">View in Scene</div>
</div>
</div>
) : (
<div className="asset-contents">
<div className="asset-wrapper">
<div className="key-wrapper">
<div className="icon"><RightHalfFillCircleIcon /></div>
<div className="key">Usage rate</div>
</div>
<div className="progress-wrapper">
<div className="progress-bar">
<div
className="filled-value"
style={{ width: `${asset.usageRate}%` }}
></div>
</div>
<div className="usage-value">{asset.usageRate}%</div>
</div>
</div>
<div className="asset-wrapper">
<div className="key-wrapper">
<div className="icon"><LocationPinIcon /></div>
<div className="key">{asset.level}</div>
</div>
<div
className="viewMore"
onClick={() =>
setExpandedAssetId(expandedAssetId === asset.id ? null : asset.id)
}
>
<div className="value">{expandedAssetId === asset.id ? "View Less" : "View More"}</div>
<div className="icon"><KebabIcon /></div>
</div>
</div>
</div>
)}
</div>
))}
</div >
</>
)
}
export default AssetManagement