Changes done in ui screens
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import AlarmRulesPortal from "@/components/dashboard/iotapplication/alarmsRules";
|
import AlarmRulesPortal from "@/components/dashboard/iotapplication/alarmsRules";
|
||||||
import DeviceFleetPortal from "@/components/dashboard/iotapplication/deviceFleet";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ type TableProps = {
|
|||||||
|
|
||||||
export default function Table({ headers, rows }: TableProps) {
|
export default function Table({ headers, rows }: TableProps) {
|
||||||
return (
|
return (
|
||||||
<div className="w-full overflow-hidden rounded-2xl border
|
<div className="w-full overflow-hidden border
|
||||||
border-slate-800 bg-[#0B1727] shadow-xl">
|
border-slate-800 bg-[#0B1727] shadow-xl">
|
||||||
<div className="overflow-x-auto">
|
<div className="overflow-x-auto">
|
||||||
<table className="w-full border-collapse text-[12px]">
|
<table className="w-full border-collapse text-[12px]">
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ export default function AuditSurveyPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest uppercase font-mono">
|
||||||
<span className="text-teal-400">Apple One — HQ Tower</span>
|
<span className="text-teal-400">Apple One — HQ Tower</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">COMPLIANCE</span>
|
<span className="text-slate-400">COMPLIANCE</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">AUDIT & SURVEY</span>
|
<span className="text-slate-400">AUDIT & SURVEY</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
Audit & survey management
|
Audit & survey management
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ export default function ContractsPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-emerald-400 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-emerald-400 uppercase font-mono">
|
||||||
<span>Apple One — HQ Tower</span>
|
<span>Apple One — HQ Tower</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">COMPLIANCE</span>
|
<span className="text-slate-400">COMPLIANCE</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500"> Contracts</span>
|
<span className="text-slate-400"> Contracts</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
Contract management
|
Contract management
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ export default function FireSafetyPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest uppercase font-mono">
|
||||||
<span className="text-teal-400">Apple One — HQ Tower</span>
|
<span className="text-teal-400">Apple One — HQ Tower</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">COMPLIANCE</span>
|
<span className="text-slate-400">COMPLIANCE</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500"> FIRE & SAFETY</span>
|
<span className="text-slate-400"> FIRE & SAFETY</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
Fire & safety management
|
Fire & safety management
|
||||||
@@ -102,7 +102,7 @@ export default function FireSafetyPortal() {
|
|||||||
{/* --- MAIN CONTENT LAYOUT --- */}
|
{/* --- MAIN CONTENT LAYOUT --- */}
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
|
||||||
{/* Left Column: Safety equipment inspection Table */}
|
{/* Left Column: Safety equipment inspection Table */}
|
||||||
<div className="lg:col-span-2 rounded-xl border border-slate-800/80 bg-[#071321]/80 p-5">
|
<div className="lg:col-span-2 rounded-xl border border-slate-800/80 p-5">
|
||||||
<div className="flex items-center justify-between mb-4">
|
<div className="flex items-center justify-between mb-4">
|
||||||
<h2 className="text-base font-bold text-slate-100">
|
<h2 className="text-base font-bold text-slate-100">
|
||||||
Safety equipment inspection
|
Safety equipment inspection
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import {
|
import {
|
||||||
Layers,
|
Layers,
|
||||||
ShieldCheck,
|
ShieldCheck,
|
||||||
@@ -32,12 +32,12 @@ export default function StatutoryCompliancePortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
||||||
<span className="text-teal-400">Apple One — HQ Tower</span>
|
<span className="text-teal-400">Apple One — HQ Tower</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>Compliance</span>
|
<span className="text-gray-400">Compliance</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>Statutory</span>
|
<span className="text-gray-400">Statutory</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-extrabold text-white tracking-tight mt-1.5">
|
<h1 className="text-2xl font-extrabold text-white tracking-tight mt-1.5">
|
||||||
Statutory compliance tracker
|
Statutory compliance tracker
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import {
|
import {
|
||||||
ShieldCheck,
|
|
||||||
Clock,
|
|
||||||
AlertTriangle,
|
AlertTriangle,
|
||||||
Calendar,
|
|
||||||
Layers,
|
|
||||||
Plus,
|
Plus,
|
||||||
GraduationCap,
|
GraduationCap,
|
||||||
Star,
|
Star,
|
||||||
@@ -28,12 +26,12 @@ export default function TrainingPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest uppercase font-mono">
|
||||||
<span className="text-teal-400">Apple One — HQ Tower</span>
|
<span className="text-teal-400">Apple One — HQ Tower</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">COMPLIANCE</span>
|
<span className="text-slate-400">COMPLIANCE</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">TRAINING</span>
|
<span className="text-slate-400">TRAINING</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
Training & onboarding
|
Training & onboarding
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ export default function WasteESGPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest uppercase font-mono">
|
||||||
<span className="text-teal-400">Apple One — HQ Tower</span>
|
<span className="text-teal-400">Apple One — HQ Tower</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">SUSTAINABILITY</span>
|
<span className="text-slate-400">SUSTAINABILITY</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">WASTE</span>
|
<span className="text-slate-400">WASTE</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
Waste management
|
Waste management
|
||||||
@@ -97,7 +97,7 @@ export default function WasteESGPortal() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* --- MAIN CONTENT SECTION BELOW STAT CARDS --- */}
|
{/* --- MAIN CONTENT SECTION BELOW STAT CARDS --- */}
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-5 gap-4 mb-6">
|
<div className="grid grid-cols-1 lg:grid-cols-5 gap-4 mb-4">
|
||||||
{/* Waste by Stream Progress Chart */}
|
{/* Waste by Stream Progress Chart */}
|
||||||
<div className="lg:col-span-3 rounded-xl border border-slate-800/80 bg-[#071321]/80 p-5 flex flex-col justify-between">
|
<div className="lg:col-span-3 rounded-xl border border-slate-800/80 bg-[#071321]/80 p-5 flex flex-col justify-between">
|
||||||
<div className="flex items-center justify-between mb-6">
|
<div className="flex items-center justify-between mb-6">
|
||||||
|
|||||||
@@ -1,25 +1,24 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React, { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Plus, QrCode, Sparkles } from "lucide-react";
|
import { Plus, } from "lucide-react";
|
||||||
|
import Button from "@/components/common/button";
|
||||||
|
import { blocks, floors, zones } from "@/constants/constant";
|
||||||
|
|
||||||
export default function MasterDataPortal() {
|
export default function MasterDataPortal() {
|
||||||
const [activeTab, setActiveTab] = useState("Block / Floor / Zone");
|
const [activeTab, setActiveTab] = useState("Block / Floor / Zone");
|
||||||
|
|
||||||
// Sample data for the hierarchy cards
|
// Sample data for the hierarchy cards
|
||||||
const blocks = ["Block 1", "Block 2", "Tower A"];
|
|
||||||
const floors = ["Ground", "Floor 1", "Floor 2"];
|
|
||||||
const zones = ["Zone N", "Zone Z1", "Zone Z2"];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className=" text-slate-100 font-sans my-15">
|
<div className=" text-slate-100 font-sans my-15">
|
||||||
{/* --- BREADCRUMB --- */}
|
{/* --- BREADCRUMB --- */}
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-emerald-400 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-emerald-400 uppercase font-mono">
|
||||||
<span>APPLE ONE — HQ TOWER</span>
|
<span>APPLE ONE — HQ TOWER</span>
|
||||||
<span className="text-slate-600">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">CONFIGURE</span>
|
<span className="text-slate-400">CONFIGURE</span>
|
||||||
<span className="text-slate-600">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">MASTER DATA</span>
|
<span className="text-slate-400">MASTER DATA</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* --- PAGE HEADER --- */}
|
{/* --- PAGE HEADER --- */}
|
||||||
@@ -40,7 +39,7 @@ export default function MasterDataPortal() {
|
|||||||
<span className="text-[10px] uppercase font-mono tracking-wider text-slate-500 font-bold">
|
<span className="text-[10px] uppercase font-mono tracking-wider text-slate-500 font-bold">
|
||||||
SITE & LOCATION
|
SITE & LOCATION
|
||||||
</span>
|
</span>
|
||||||
<button
|
<Button
|
||||||
onClick={() => setActiveTab("Block / Floor / Zone")}
|
onClick={() => setActiveTab("Block / Floor / Zone")}
|
||||||
className={`px-3 py-1.5 rounded-lg border text-xs font-semibold transition-all ${
|
className={`px-3 py-1.5 rounded-lg border text-xs font-semibold transition-all ${
|
||||||
activeTab === "Block / Floor / Zone"
|
activeTab === "Block / Floor / Zone"
|
||||||
@@ -49,7 +48,7 @@ export default function MasterDataPortal() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Block / Floor / Zone
|
Block / Floor / Zone
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ASSETS */}
|
{/* ASSETS */}
|
||||||
@@ -59,7 +58,7 @@ export default function MasterDataPortal() {
|
|||||||
</span>
|
</span>
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
{["Manufacturer", "Service Provider", "Criticality"].map((item) => (
|
{["Manufacturer", "Service Provider", "Criticality"].map((item) => (
|
||||||
<button
|
<Button
|
||||||
key={item}
|
key={item}
|
||||||
onClick={() => setActiveTab(item)}
|
onClick={() => setActiveTab(item)}
|
||||||
className={`px-3 py-1.5 rounded-lg border text-xs transition-all ${
|
className={`px-3 py-1.5 rounded-lg border text-xs transition-all ${
|
||||||
@@ -69,7 +68,7 @@ export default function MasterDataPortal() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{item}
|
{item}
|
||||||
</button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -81,7 +80,7 @@ export default function MasterDataPortal() {
|
|||||||
</span>
|
</span>
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
{["Service Type", "Unit", "Store", "Partners"].map((item) => (
|
{["Service Type", "Unit", "Store", "Partners"].map((item) => (
|
||||||
<button
|
<Button
|
||||||
key={item}
|
key={item}
|
||||||
onClick={() => setActiveTab(item)}
|
onClick={() => setActiveTab(item)}
|
||||||
className={`px-3 py-1.5 rounded-lg border text-xs transition-all ${
|
className={`px-3 py-1.5 rounded-lg border text-xs transition-all ${
|
||||||
@@ -91,7 +90,7 @@ export default function MasterDataPortal() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{item}
|
{item}
|
||||||
</button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -103,7 +102,7 @@ export default function MasterDataPortal() {
|
|||||||
</span>
|
</span>
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
{["Budget Category", "Budget Type"].map((item) => (
|
{["Budget Category", "Budget Type"].map((item) => (
|
||||||
<button
|
<Button
|
||||||
key={item}
|
key={item}
|
||||||
onClick={() => setActiveTab(item)}
|
onClick={() => setActiveTab(item)}
|
||||||
className={`px-3 py-1.5 rounded-lg border text-xs transition-all ${
|
className={`px-3 py-1.5 rounded-lg border text-xs transition-all ${
|
||||||
@@ -113,7 +112,7 @@ export default function MasterDataPortal() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{item}
|
{item}
|
||||||
</button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -125,7 +124,7 @@ export default function MasterDataPortal() {
|
|||||||
PEOPLE
|
PEOPLE
|
||||||
</span>
|
</span>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<Button
|
||||||
onClick={() => setActiveTab("Course")}
|
onClick={() => setActiveTab("Course")}
|
||||||
className={`px-3 py-1.5 rounded-lg border text-xs font-semibold transition-all ${
|
className={`px-3 py-1.5 rounded-lg border text-xs font-semibold transition-all ${
|
||||||
activeTab === "Course"
|
activeTab === "Course"
|
||||||
@@ -134,7 +133,7 @@ export default function MasterDataPortal() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Course
|
Course
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -200,18 +199,18 @@ export default function MasterDataPortal() {
|
|||||||
<span className="flex items-center gap-1 text-[10px] font-mono font-bold text-emerald-400 uppercase tracking-wider">
|
<span className="flex items-center gap-1 text-[10px] font-mono font-bold text-emerald-400 uppercase tracking-wider">
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400"></span> ACTIVE
|
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400"></span> ACTIVE
|
||||||
</span>
|
</span>
|
||||||
<button className="text-[11px] text-slate-400 border border-slate-800 bg-slate-900/60 hover:bg-slate-800 px-2.5 py-1 rounded-md transition-colors">
|
<Button className="text-[11px] text-slate-400 border border-slate-800 bg-slate-900/60 hover:bg-slate-800 px-2.5 py-1 rounded-md transition-colors">
|
||||||
Remove
|
Remove
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button className="mt-6 flex items-center gap-1.5 text-xs font-bold text-emerald-400 hover:text-emerald-300 transition-colors w-fit">
|
<Button className="mt-6 flex items-center gap-1.5 text-xs font-bold text-emerald-400 hover:text-emerald-300 transition-colors w-fit">
|
||||||
<Plus className="w-3.5 h-3.5 stroke-[3]" />
|
<Plus className="w-3.5 h-3.5 stroke-[3]" />
|
||||||
<span>Add floor</span>
|
<span>Add floor</span>
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Zone Column */}
|
{/* Zone Column */}
|
||||||
@@ -229,22 +228,23 @@ export default function MasterDataPortal() {
|
|||||||
<span className="flex items-center gap-1 text-[10px] font-mono font-bold text-emerald-400 uppercase tracking-wider">
|
<span className="flex items-center gap-1 text-[10px] font-mono font-bold text-emerald-400 uppercase tracking-wider">
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400"></span> ACTIVE
|
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400"></span> ACTIVE
|
||||||
</span>
|
</span>
|
||||||
<button className="text-[11px] text-slate-400 border border-slate-800 bg-slate-900/60 hover:bg-slate-800 px-2.5 py-1 rounded-md transition-colors">
|
<Button className="text-[11px] text-slate-400 border border-slate-800 bg-slate-900/60 hover:bg-slate-800 px-2.5 py-1 rounded-md transition-colors">
|
||||||
Remove
|
Remove
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button className="mt-6 flex items-center gap-1.5 text-xs font-bold text-emerald-400 hover:text-emerald-300 transition-colors w-fit">
|
<Button className="mt-6 flex items-center gap-1.5 text-xs font-bold text-emerald-400 hover:text-emerald-300 transition-colors w-fit">
|
||||||
<Plus className="w-3.5 h-3.5 stroke-[3]" />
|
<Plus className="w-3.5 h-3.5 stroke-[3]" />
|
||||||
<span>Add zone</span>
|
<span>Add zone</span>
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -3,61 +3,9 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Check } from "lucide-react";
|
import { Check } from "lucide-react";
|
||||||
import Button from "@/components/common/button";
|
import Button from "@/components/common/button";
|
||||||
|
import { initialPermissions, rolesList } from "@/constants/constant";
|
||||||
|
|
||||||
// Initial roles state
|
|
||||||
const rolesList = [
|
|
||||||
{ id: "admin", label: "Admin", badge: "all" },
|
|
||||||
{ id: "helpdesk", label: "Helpdesk", badge: "scoped" },
|
|
||||||
{ id: "mne_supervisor", label: "M&E Supervisor", badge: "scoped" },
|
|
||||||
{ id: "technician", label: "Technician", badge: "scoped" },
|
|
||||||
{ id: "tenant", label: "Tenant", badge: "scoped" },
|
|
||||||
];
|
|
||||||
|
|
||||||
// Initial permissions table data
|
|
||||||
const initialPermissions = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
module: "Help Desk",
|
|
||||||
menu: "Daily Location Checklist",
|
|
||||||
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
module: "Equipment",
|
|
||||||
menu: "Site-Wise Equipment",
|
|
||||||
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
module: "Equipment",
|
|
||||||
menu: "AMC Schedule",
|
|
||||||
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
module: "Request",
|
|
||||||
menu: "TFM Request",
|
|
||||||
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
module: "Energy",
|
|
||||||
menu: "Meter Reading",
|
|
||||||
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
module: "Master",
|
|
||||||
menu: "Request Location",
|
|
||||||
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 7,
|
|
||||||
module: "Security",
|
|
||||||
menu: "Users",
|
|
||||||
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function RolesAccessPortal() {
|
export default function RolesAccessPortal() {
|
||||||
const [activeTopTab, setActiveTopTab] = useState("Roles & Permissions");
|
const [activeTopTab, setActiveTopTab] = useState("Roles & Permissions");
|
||||||
@@ -68,16 +16,16 @@ export default function RolesAccessPortal() {
|
|||||||
return (
|
return (
|
||||||
<div className="my-15 text-slate-100 font-sans">
|
<div className="my-15 text-slate-100 font-sans">
|
||||||
{/* --- BREADCRUMB --- */}
|
{/* --- BREADCRUMB --- */}
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-emerald-400 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-emerald-400 uppercase font-mono">
|
||||||
<span>APPLE ONE — HQ TOWER</span>
|
<span>APPLE ONE — HQ TOWER</span>
|
||||||
<span className="text-slate-600">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">CONFIGURE</span>
|
<span className="text-slate-400">CONFIGURE</span>
|
||||||
<span className="text-slate-600">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">ROLES & ACCESS</span>
|
<span className="text-slate-400">ROLES & ACCESS</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* --- PAGE HEADER --- */}
|
{/* --- PAGE HEADER --- */}
|
||||||
<h1 className="text-3xl font-bold text-white tracking-tight mt-1">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-1">
|
||||||
Roles & access
|
Roles & access
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-sm font-medium text-slate-400 mt-2 max-w-2xl leading-relaxed">
|
<p className="text-sm font-medium text-slate-400 mt-2 max-w-2xl leading-relaxed">
|
||||||
@@ -88,7 +36,7 @@ export default function RolesAccessPortal() {
|
|||||||
{/* --- MAIN TABS --- */}
|
{/* --- MAIN TABS --- */}
|
||||||
<div className="flex items-center gap-8 border-b border-slate-800/80 mt-8 text-sm font-semibold">
|
<div className="flex items-center gap-8 border-b border-slate-800/80 mt-8 text-sm font-semibold">
|
||||||
{["Roles & Permissions", "Tenant Access", "Escalation Matrix"].map((tab) => (
|
{["Roles & Permissions", "Tenant Access", "Escalation Matrix"].map((tab) => (
|
||||||
<button
|
<Button
|
||||||
key={tab}
|
key={tab}
|
||||||
onClick={() => setActiveTopTab(tab)}
|
onClick={() => setActiveTopTab(tab)}
|
||||||
className={`pb-3 relative transition-colors ${
|
className={`pb-3 relative transition-colors ${
|
||||||
@@ -101,7 +49,7 @@ export default function RolesAccessPortal() {
|
|||||||
{activeTopTab === tab && (
|
{activeTopTab === tab && (
|
||||||
<span className="absolute bottom-0 left-0 right-0 h-0.5 bg-emerald-400 rounded-full" />
|
<span className="absolute bottom-0 left-0 right-0 h-0.5 bg-emerald-400 rounded-full" />
|
||||||
)}
|
)}
|
||||||
</button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -112,7 +60,7 @@ export default function RolesAccessPortal() {
|
|||||||
{rolesList.map((role) => {
|
{rolesList.map((role) => {
|
||||||
const isSelected = selectedRole === role.id;
|
const isSelected = selectedRole === role.id;
|
||||||
return (
|
return (
|
||||||
<button
|
<Button
|
||||||
key={role.id}
|
key={role.id}
|
||||||
onClick={() => setSelectedRole(role.id)}
|
onClick={() => setSelectedRole(role.id)}
|
||||||
className={`w-full flex items-center justify-between px-5 py-4 text-left transition-all relative ${
|
className={`w-full flex items-center justify-between px-5 py-4 text-left transition-all relative ${
|
||||||
@@ -136,7 +84,7 @@ export default function RolesAccessPortal() {
|
|||||||
>
|
>
|
||||||
{role.badge}
|
{role.badge}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</Button>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@@ -176,8 +124,8 @@ export default function RolesAccessPortal() {
|
|||||||
const isChecked = row.permissions[permKey];
|
const isChecked = row.permissions[permKey];
|
||||||
return (
|
return (
|
||||||
<td key={permKey} className="py-4 px-4 text-center">
|
<td key={permKey} className="py-4 px-4 text-center">
|
||||||
<button
|
<Button
|
||||||
type="button"
|
|
||||||
|
|
||||||
className={`w-5 h-5 rounded flex items-center justify-center transition-all border mx-auto ${
|
className={`w-5 h-5 rounded flex items-center justify-center transition-all border mx-auto ${
|
||||||
isChecked
|
isChecked
|
||||||
@@ -186,7 +134,7 @@ export default function RolesAccessPortal() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{isChecked && <Check className="w-3.5 h-3.5 stroke-[3]" />}
|
{isChecked && <Check className="w-3.5 h-3.5 stroke-[3]" />}
|
||||||
</button>
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,29 +26,23 @@ export default function SettingsPortal() {
|
|||||||
return (
|
return (
|
||||||
<div className="my-15 text-slate-200 font-sans">
|
<div className="my-15 text-slate-200 font-sans">
|
||||||
{/* Top Header & Breadcrumb */}
|
{/* Top Header & Breadcrumb */}
|
||||||
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4 mb-6">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-emerald-400 uppercase font-mono">
|
||||||
<div>
|
<span>APPLE ONE — HQ TOWER</span>
|
||||||
<div className="text-xs uppercase tracking-wider text-slate-400 mb-2 font-medium">
|
<span className="text-slate-600">•</span>
|
||||||
<span className="hover:text-slate-200 cursor-pointer">
|
<span className="text-slate-400">CONFIGURE</span>
|
||||||
APPLE ONE — HQ TOWER
|
<span className="text-slate-600">•</span>
|
||||||
</span>{" "}
|
<span className="text-slate-400">SETTINGS</span>
|
||||||
• <span className="hover:text-slate-200 cursor-pointer">CONFIGURE</span>{" "}
|
|
||||||
• <span className="text-slate-300">SETTINGS</span>
|
|
||||||
</div>
|
|
||||||
<h1 className="text-2xl font-bold text-white mb-1">Settings</h1>
|
|
||||||
<p className="text-slate-400 text-sm">
|
|
||||||
Personal and notification preferences for this tenant workspace.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Save Changes Button */}
|
|
||||||
<div>
|
|
||||||
<button className="bg-[#2DD4BF] hover:bg-[#26b8a5] text-[#070D19] font-semibold text-sm px-5 py-2.5 rounded-lg transition-colors shadow-sm">
|
|
||||||
Save changes
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* --- PAGE HEADER --- */}
|
||||||
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-1">
|
||||||
|
Settings
|
||||||
|
</h1>
|
||||||
|
<p className="text-sm font-medium text-slate-400 mt-2 max-w-2xl leading-relaxed">
|
||||||
|
Personal and notification preferences for this tenant workspace.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
{/* Main Grid Layout */}
|
{/* Main Grid Layout */}
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6">
|
||||||
{/* Left Column: App Settings */}
|
{/* Left Column: App Settings */}
|
||||||
@@ -66,7 +60,7 @@ export default function SettingsPortal() {
|
|||||||
<p className="text-xs text-slate-400">Workspace loaded on sign-in</p>
|
<p className="text-xs text-slate-400">Workspace loaded on sign-in</p>
|
||||||
</div>
|
</div>
|
||||||
<select
|
<select
|
||||||
value={appSettings.defaultTenant}
|
|
||||||
|
|
||||||
className="bg-[#080E21] border border-slate-700/80 text-slate-200 text-xs rounded-lg px-3 py-2 w-full sm:w-48 focus:outline-none focus:border-[#2DD4BF] cursor-pointer"
|
className="bg-[#080E21] border border-slate-700/80 text-slate-200 text-xs rounded-lg px-3 py-2 w-full sm:w-48 focus:outline-none focus:border-[#2DD4BF] cursor-pointer"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,71 +1,38 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import Button from "@/components/common/button";
|
||||||
|
import { userData } from "@/constants/constant";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
// Mock user location data matching the screenshot
|
|
||||||
const userData = [
|
|
||||||
{
|
|
||||||
name: "Dhananjay T.",
|
|
||||||
email: "dhananjay@kafm.io",
|
|
||||||
mobile: "7489477369",
|
|
||||||
latitude: "18.5450",
|
|
||||||
longitude: "73.7935",
|
|
||||||
site: "Apple One",
|
|
||||||
// Relative coordinates for the map visual dots (X%, Y%)
|
|
||||||
x: "19%",
|
|
||||||
y: "38%",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "ME Local",
|
|
||||||
email: "me.local@kafm.io",
|
|
||||||
mobile: "9876543210",
|
|
||||||
latitude: "18.5469",
|
|
||||||
longitude: "73.7945",
|
|
||||||
site: "Apple One",
|
|
||||||
x: "44%",
|
|
||||||
y: "43%",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "TECH Local",
|
|
||||||
email: "tech.local@kafm.io",
|
|
||||||
mobile: "9123456780",
|
|
||||||
latitude: "18.5441",
|
|
||||||
longitude: "73.7951",
|
|
||||||
site: "Apple One",
|
|
||||||
x: "69%",
|
|
||||||
y: "48%",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function UserLocationPortal() {
|
export default function UserLocationPortal() {
|
||||||
const [viewMode, setViewMode] = useState<"map" | "table">("table");
|
const [viewMode, setViewMode] = useState<"map" | "table">("table");
|
||||||
const [mapType, setMapType] = useState<"MAP" | "SATELLITE">("MAP");
|
const [mapType, setMapType] = useState<"MAP" | "SATELLITE">("MAP");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="my-15 text-slate-200 font-sans">
|
<div className="my-15 min-h-screen h-full text-slate-200 font-sans">
|
||||||
{/* Top Breadcrumb & Header */}
|
{/* Top Breadcrumb & Header */}
|
||||||
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
{/* Breadcrumb */}
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest uppercase font-mono">
|
||||||
<div className="text-xs uppercase tracking-wider text-slate-400 mb-2 font-medium">
|
<span className="text-teal-400">APPLE ONE — HQ TOWER</span>
|
||||||
<span className="hover:text-slate-200 cursor-pointer">
|
<span className="text-slate-600">•</span>
|
||||||
APPLE ONE — HQ TOWER
|
<span className="text-slate-400">CONFIGURE</span>
|
||||||
</span>{" "}
|
<span className="text-slate-600">•</span>
|
||||||
• <span className="hover:text-slate-200 cursor-pointer">CONFIGURE</span>{" "}
|
<span className="text-slate-400">USER LOCATION</span>
|
||||||
• <span className="text-slate-300">USER LOCATION</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
{/* Main Title */}
|
User location
|
||||||
<h1 className="text-3xl font-bold text-white mb-2">User location</h1>
|
</h1>
|
||||||
<p className="text-slate-400 text-sm max-w-2xl leading-relaxed">
|
<p className="text-sm font-medium text-slate-400 mt-2 max-w-xl leading-relaxed">
|
||||||
Live position of active technicians, captured from the mobile app. Map
|
Live position of active technicians, captured from the mobile app. Map and table views.
|
||||||
and table views.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* View Switcher Buttons */}
|
{/* View Switcher Buttons */}
|
||||||
<div className="flex bg-[#0F172A] p-1 rounded-lg border border-slate-800 self-start md:self-auto">
|
<div className="flex bg-[#0F172A] p-1 rounded-lg border border-slate-800 self-start md:self-auto">
|
||||||
<button
|
<Button
|
||||||
onClick={() => setViewMode("map")}
|
onClick={() => setViewMode("map")}
|
||||||
className={`px-4 py-2 rounded-md text-sm font-medium transition-all ${
|
className={`px-4 py-2 rounded-md text-sm font-medium transition-all ${
|
||||||
viewMode === "map"
|
viewMode === "map"
|
||||||
@@ -74,8 +41,8 @@ export default function UserLocationPortal() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Map view
|
Map view
|
||||||
</button>
|
</Button>
|
||||||
<button
|
<Button
|
||||||
onClick={() => setViewMode("table")}
|
onClick={() => setViewMode("table")}
|
||||||
className={`px-4 py-2 rounded-md text-sm font-medium transition-all ${
|
className={`px-4 py-2 rounded-md text-sm font-medium transition-all ${
|
||||||
viewMode === "table"
|
viewMode === "table"
|
||||||
@@ -84,7 +51,7 @@ export default function UserLocationPortal() {
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Table view
|
Table view
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -139,23 +106,23 @@ export default function UserLocationPortal() {
|
|||||||
|
|
||||||
{/* Map Type Toggle (Bottom Right of Map Area) */}
|
{/* Map Type Toggle (Bottom Right of Map Area) */}
|
||||||
<div className="absolute bottom-2 right-4 flex items-center space-x-2 text-[10px] font-mono tracking-wider text-slate-500">
|
<div className="absolute bottom-2 right-4 flex items-center space-x-2 text-[10px] font-mono tracking-wider text-slate-500">
|
||||||
<button
|
<Button
|
||||||
onClick={() => setMapType("MAP")}
|
onClick={() => setMapType("MAP")}
|
||||||
className={`hover:text-slate-300 transition-colors ${
|
className={`hover:text-slate-300 transition-colors ${
|
||||||
mapType === "MAP" ? "text-slate-300 font-bold" : ""
|
mapType === "MAP" ? "text-slate-300 font-bold" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
MAP
|
MAP
|
||||||
</button>
|
</Button>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<button
|
<Button
|
||||||
onClick={() => setMapType("SATELLITE")}
|
onClick={() => setMapType("SATELLITE")}
|
||||||
className={`hover:text-slate-300 transition-colors ${
|
className={`hover:text-slate-300 transition-colors ${
|
||||||
mapType === "SATELLITE" ? "text-slate-300 font-bold" : ""
|
mapType === "SATELLITE" ? "text-slate-300 font-bold" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
SATELLITE
|
SATELLITE
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ export default function WorkFlowAutomationPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest uppercase font-mono">
|
||||||
<span className="text-teal-400">APPLE ONE — HQ TOWER</span>
|
<span className="text-teal-400">APPLE ONE — HQ TOWER</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">CONFIGURE</span>
|
<span className="text-slate-400">CONFIGURE</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">AUTOMATION</span>
|
<span className="text-slate-400">AUTOMATION</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
Workflow automation
|
Workflow automation
|
||||||
@@ -113,9 +113,9 @@ export default function WorkFlowAutomationPortal() {
|
|||||||
<span className="text-[10px] font-mono tracking-widest text-slate-400 uppercase">
|
<span className="text-[10px] font-mono tracking-widest text-slate-400 uppercase">
|
||||||
WHEN
|
WHEN
|
||||||
</span>
|
</span>
|
||||||
<button className="px-3.5 py-1.5 rounded-lg border border-[#2DD4BF]/40 text-[#2DD4BF] text-xs font-mono font-medium transition-colors">
|
<Button className="px-3.5 py-1.5 rounded-lg border border-[#2DD4BF]/40 text-[#2DD4BF] text-xs font-mono font-medium transition-colors">
|
||||||
Trigger event
|
Trigger event
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* IF Step */}
|
{/* IF Step */}
|
||||||
@@ -123,9 +123,9 @@ export default function WorkFlowAutomationPortal() {
|
|||||||
<span className="text-[10px] font-mono tracking-widest text-slate-400 uppercase">
|
<span className="text-[10px] font-mono tracking-widest text-slate-400 uppercase">
|
||||||
IF
|
IF
|
||||||
</span>
|
</span>
|
||||||
<button className="px-3.5 py-1.5 rounded-lg border border-slate-700 text-slate-300 text-xs font-mono font-medium transition-colors">
|
<Button className="px-3.5 py-1.5 rounded-lg border border-slate-700 text-slate-300 text-xs font-mono font-medium transition-colors">
|
||||||
Condition
|
Condition
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* THEN Step */}
|
{/* THEN Step */}
|
||||||
@@ -133,9 +133,9 @@ export default function WorkFlowAutomationPortal() {
|
|||||||
<span className="text-[10px] font-mono tracking-widest text-slate-400 uppercase">
|
<span className="text-[10px] font-mono tracking-widest text-slate-400 uppercase">
|
||||||
THEN
|
THEN
|
||||||
</span>
|
</span>
|
||||||
<button className="px-3.5 py-1.5 rounded-lg border border-[#2DD4BF]/30 text-[#2DD4BF] text-xs font-mono font-medium transition-colors">
|
<Button className="px-3.5 py-1.5 rounded-lg border border-[#2DD4BF]/30 text-[#2DD4BF] text-xs font-mono font-medium transition-colors">
|
||||||
Action
|
Action
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import StatCard from "@/components/common/dashStatCard";
|
|||||||
import { Card } from '@/components/common/cardWrapper';
|
import { Card } from '@/components/common/cardWrapper';
|
||||||
import { CardHeader } from '@/components/common/cardHeader';
|
import { CardHeader } from '@/components/common/cardHeader';
|
||||||
import { approvalQueueData, categoryData } from "@/constants/constant";
|
import { approvalQueueData, categoryData } from "@/constants/constant";
|
||||||
|
import Table from "@/components/common/dataTable";
|
||||||
|
import { budgetPerformanceRows } from "@/constants/tabledata";
|
||||||
|
import { budgetPerformanceHeaders } from "@/constants/tabledata";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -21,12 +24,12 @@ export default function BudgetPortal() {
|
|||||||
{/* --- HEADER SECTION WITH BUTTONS --- */}
|
{/* --- HEADER SECTION WITH BUTTONS --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
||||||
<span className="text-teal-400">Apple One — HQ Tower</span>
|
<span className="text-teal-400">Apple One — HQ Tower</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>FINANCE</span>
|
<span className="text-gray-400">FINANCE</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>O&M BUDGET</span>
|
<span className="text-gray-400">O&M BUDGET</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
@@ -99,63 +102,23 @@ export default function BudgetPortal() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* --- BUDGET DETAILS & APPROVAL QUEUE SECTION --- */}
|
{/* --- BUDGET DETAILS & APPROVAL QUEUE SECTION --- */}
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
|
<div className="grid grid-cols-2 gap-3 mb-8">
|
||||||
{/* Planned vs Actual Table (Left 2 Columns) */}
|
{/* Planned vs Actual Table (Left 2 Columns) */}
|
||||||
<Card className="lg:col-span-2 justify-start">
|
<div className=" border border-slate-800/80 rounded-lg ">
|
||||||
<CardHeader
|
<div className="flex items-center justify-between
|
||||||
title="Planned vs actual · by category"
|
px-4 py-4 border-b border-slate-800/80">
|
||||||
subtitle="CAPEX ₹35.0 L • OPEX ₹1.56 Cr"
|
<h2 className="text-base font-semibold text-white">
|
||||||
/>
|
Planned vs actual·by category</h2>
|
||||||
|
|
||||||
<div className="overflow-x-auto mt-2">
|
</div>
|
||||||
<table className="w-full text-left border-collapse">
|
|
||||||
<thead>
|
{/* Corrected column layout and removed horizontal scrollbar to align with the right UI. */}
|
||||||
<tr className="border-b border-[#162942]/60 text-[11px] font-mono font-bold text-slate-500 uppercase tracking-wider">
|
<Table headers={budgetPerformanceHeaders} rows={budgetPerformanceRows} />
|
||||||
<th className="py-2.5 px-2">Category</th>
|
</div>
|
||||||
<th className="py-2.5 px-2">Type</th>
|
|
||||||
<th className="py-2.5 px-2 font-mono">Planned</th>
|
|
||||||
<th className="py-2.5 px-2 font-mono">Actual</th>
|
|
||||||
<th className="py-2.5 px-2 font-mono">Variance</th>
|
|
||||||
<th className="py-2.5 px-2 font-mono min-w-[120px]">Utilization</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody className="divide-y divide-[#162942]/40 text-xs">
|
|
||||||
{categoryData.map((row, idx) => (
|
|
||||||
<tr key={idx} className="hover:bg-slate-900/30 transition-colors">
|
|
||||||
<td className="py-3 px-2 font-semibold text-slate-100">
|
|
||||||
{row.category}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-2">
|
|
||||||
<span className="bg-[#12233a] border border-[#1d3554] text-slate-300 font-mono text-[10px] px-2 py-0.5 rounded">
|
|
||||||
{row.type}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-2 font-mono text-slate-300">
|
|
||||||
{row.planned}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-2 font-mono text-slate-300">
|
|
||||||
{row.actual}
|
|
||||||
</td>
|
|
||||||
<td className={`py-3 px-2 font-mono font-semibold ${row.varianceColor}`}>
|
|
||||||
{row.variance}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-2">
|
|
||||||
<div className="w-full bg-[#12233a] h-1.5 rounded-full overflow-hidden mb-1">
|
|
||||||
<div
|
|
||||||
className={`h-full ${row.barColor}`}
|
|
||||||
style={{ width: `${Math.min(row.utilization, 100)}%` }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<span className="text-[10px] font-mono text-slate-400">
|
|
||||||
{row.utilization}%
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{/* Approval Queue Panel (Right 1 Column) */}
|
{/* Approval Queue Panel (Right 1 Column) */}
|
||||||
<Card className="justify-start">
|
<Card className="justify-start">
|
||||||
@@ -174,9 +137,9 @@ export default function BudgetPortal() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{item.status === "pending" ? (
|
{item.status === "pending" ? (
|
||||||
<button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-200 text-xs font-semibold px-3 py-1 rounded transition-colors whitespace-nowrap">
|
<Button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-200 text-xs font-semibold px-3 py-1 rounded transition-colors whitespace-nowrap">
|
||||||
Approve
|
Approve
|
||||||
</button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<span className="flex items-center gap-1.5 bg-emerald-950/40 border border-emerald-800/30 text-emerald-400 text-[10px] font-mono font-bold px-2.5 py-1 rounded-full whitespace-nowrap">
|
<span className="flex items-center gap-1.5 bg-emerald-950/40 border border-emerald-800/30 text-emerald-400 text-[10px] font-mono font-bold px-2.5 py-1 rounded-full whitespace-nowrap">
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400" />
|
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400" />
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ export default function CostInvoicePortal() {
|
|||||||
{/* --- HEADER SECTION WITH BUTTONS --- */}
|
{/* --- HEADER SECTION WITH BUTTONS --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
||||||
<span className="text-teal-400">Apple One — HQ Tower</span>
|
<span className="text-teal-400">Apple One — HQ Tower</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>FINANCE</span>
|
<span className="text-gray-400">FINANCE</span>
|
||||||
<span>•</span>
|
<span className="text-gray-400">•</span>
|
||||||
<span>COSTING & INVOICING</span>
|
<span className="text-gray-400">COSTING & INVOICING</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Plus, Download } from 'lucide-react';
|
|
||||||
import Button from "@/components/common/button";
|
import Button from "@/components/common/button";
|
||||||
import NavigationTabs from '@/components/common/tabs';
|
import NavigationTabs from '@/components/common/tabs';
|
||||||
import { reportFilters, reporttabs, Reqeusttabs, statusFilters } from '@/constants/constant';
|
import { reportFilters, reporttabs, Reqeusttabs, statusFilters } from '@/constants/constant';
|
||||||
@@ -22,12 +22,12 @@ export default function ReportPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
||||||
<span className="text-teal-400">Apple One — HQ Tower</span>
|
<span className="text-teal-400">Apple One — HQ Tower</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>INSIGHT</span>
|
<span className="text-gray-400">INSIGHT</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>REPORTS</span>
|
<span className="text-gray-400">REPORTS</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
Reports & MMR
|
Reports & MMR
|
||||||
@@ -59,11 +59,11 @@ export default function ReportPortal() {
|
|||||||
onChange={setActiveFilter}
|
onChange={setActiveFilter}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button
|
<Button
|
||||||
className="inline-flex items-center gap-2 rounded-xl bg-teal-400 px-5 py-2.5 text-sm font-semibold text-slate-950 hover:bg-teal-300 transition-colors focus:outline-none focus:ring-2 focus:ring-teal-400/50 shrink-0"
|
className="inline-flex items-center gap-2 rounded-xl bg-teal-400 px-5 py-2.5 text-sm font-semibold text-slate-950 hover:bg-teal-300 transition-colors focus:outline-none focus:ring-2 focus:ring-teal-400/50 shrink-0"
|
||||||
>
|
>
|
||||||
Download
|
Download
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='mt-5'>
|
<div className='mt-5'>
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ export default function AlarmRulesPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-emerald-400 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-emerald-400 uppercase font-mono">
|
||||||
<span>APPLE ONE — HQ TOWER</span>
|
<span>APPLE ONE — HQ TOWER</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">IOT</span>
|
<span className="text-slate-400">IOT</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-slate-600">•</span>
|
||||||
<span className="text-slate-500">ALARMS & RULES</span>
|
<span className="text-slate-400">ALARMS & RULES</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-1">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-1">
|
||||||
Alarms & automation rules
|
Alarms & automation rules
|
||||||
@@ -237,8 +237,8 @@ export default function AlarmRulesPortal() {
|
|||||||
Raises a Help Desk request with the asset and fault pre-filled
|
Raises a Help Desk request with the asset and fault pre-filled
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<Button
|
||||||
type="button"
|
|
||||||
onClick={() => setAutoWorkOrder(!autoWorkOrder)}
|
onClick={() => setAutoWorkOrder(!autoWorkOrder)}
|
||||||
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
||||||
autoWorkOrder ? 'bg-[#2dd4bf]' : 'bg-slate-700'
|
autoWorkOrder ? 'bg-[#2dd4bf]' : 'bg-slate-700'
|
||||||
@@ -249,7 +249,7 @@ export default function AlarmRulesPortal() {
|
|||||||
autoWorkOrder ? 'translate-x-5' : 'translate-x-0'
|
autoWorkOrder ? 'translate-x-5' : 'translate-x-0'
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Rule 2 */}
|
{/* Rule 2 */}
|
||||||
@@ -262,8 +262,8 @@ export default function AlarmRulesPortal() {
|
|||||||
Notifies the escalation matrix after 15 minutes
|
Notifies the escalation matrix after 15 minutes
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<Button
|
||||||
type="button"
|
|
||||||
onClick={() => setEscalateCriticals(!escalateCriticals)}
|
onClick={() => setEscalateCriticals(!escalateCriticals)}
|
||||||
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
||||||
escalateCriticals ? 'bg-[#2dd4bf]' : 'bg-slate-700'
|
escalateCriticals ? 'bg-[#2dd4bf]' : 'bg-slate-700'
|
||||||
@@ -274,7 +274,7 @@ export default function AlarmRulesPortal() {
|
|||||||
escalateCriticals ? 'translate-x-5' : 'translate-x-0'
|
escalateCriticals ? 'translate-x-5' : 'translate-x-0'
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Rule 3 */}
|
{/* Rule 3 */}
|
||||||
@@ -287,8 +287,8 @@ export default function AlarmRulesPortal() {
|
|||||||
Widens comfort bands 22:00–06:00 to save energy
|
Widens comfort bands 22:00–06:00 to save energy
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<Button
|
||||||
type="button"
|
|
||||||
onClick={() => setOffHoursSetpoint(!offHoursSetpoint)}
|
onClick={() => setOffHoursSetpoint(!offHoursSetpoint)}
|
||||||
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
||||||
offHoursSetpoint ? 'bg-[#2dd4bf]' : 'bg-slate-700'
|
offHoursSetpoint ? 'bg-[#2dd4bf]' : 'bg-slate-700'
|
||||||
@@ -299,7 +299,7 @@ export default function AlarmRulesPortal() {
|
|||||||
offHoursSetpoint ? 'translate-x-5' : 'translate-x-0'
|
offHoursSetpoint ? 'translate-x-5' : 'translate-x-0'
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Rule 4 */}
|
{/* Rule 4 */}
|
||||||
@@ -312,8 +312,8 @@ export default function AlarmRulesPortal() {
|
|||||||
Adds a filter change to the next PPM visit automatically
|
Adds a filter change to the next PPM visit automatically
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<Button
|
||||||
type="button"
|
|
||||||
onClick={() => setFilterPpmTask(!filterPpmTask)}
|
onClick={() => setFilterPpmTask(!filterPpmTask)}
|
||||||
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
|
||||||
filterPpmTask ? 'bg-[#2dd4bf]' : 'bg-slate-800'
|
filterPpmTask ? 'bg-[#2dd4bf]' : 'bg-slate-800'
|
||||||
@@ -324,7 +324,7 @@ export default function AlarmRulesPortal() {
|
|||||||
filterPpmTask ? 'translate-x-5 bg-slate-950' : 'translate-x-0'
|
filterPpmTask ? 'translate-x-5 bg-slate-950' : 'translate-x-0'
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ export default function CommandCenterPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[11px] font-semibold tracking-widest text-[#4e6178] uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-semibold tracking-widest text-[#4e6178] uppercase font-mono">
|
||||||
<span className="text-emerald-400 font-bold">APPLE ONE — HQ TOWER</span>
|
<span className="text-emerald-400 font-bold">APPLE ONE — HQ TOWER</span>
|
||||||
<span>•</span>
|
<span className='text-gray-600'>•</span>
|
||||||
<span>IOT</span>
|
<span className='text-gray-400'>IOT</span>
|
||||||
<span>•</span>
|
<span className='text-gray-600'>•</span>
|
||||||
<span>COMMAND CENTER</span>
|
<span className='text-gray-400'>COMMAND CENTER</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-3xl font-bold text-white tracking-tight mt-1">
|
<h1 className="text-3xl font-bold text-white tracking-tight mt-1">
|
||||||
IoT command center
|
IoT command center
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-sm text-[#7f93ac] mt-2 max-w-xl leading-relaxed">
|
<p className="text-sm text-[#7f93ac] font-medium mt-2 max-w-xl leading-relaxed">
|
||||||
Every gateway, controller and sensor across the portfolio on one live board — scoped to Apple One.
|
Every gateway, controller and sensor across the portfolio on one live board — scoped to Apple One.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -192,9 +192,9 @@ export default function CommandCenterPortal() {
|
|||||||
<div>
|
<div>
|
||||||
<div className="flex justify-between items-center mb-1">
|
<div className="flex justify-between items-center mb-1">
|
||||||
<h3 className="font-semibold text-white text-base">Live alarm feed</h3>
|
<h3 className="font-semibold text-white text-base">Live alarm feed</h3>
|
||||||
<button className="text-xs text-[#10b981] font-semibold hover:underline">
|
<Button className="text-xs text-[#10b981] font-semibold hover:underline">
|
||||||
All alarms
|
All alarms
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-[11px] text-[#4e6178] font-mono mb-4">streaming</p>
|
<p className="text-[11px] text-[#4e6178] font-mono mb-4">streaming</p>
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import {
|
import {
|
||||||
Grid2X2,
|
Grid2X2,
|
||||||
AlertTriangle,
|
AlertTriangle,
|
||||||
Sun,
|
Sun,
|
||||||
Disc,
|
Disc,
|
||||||
Smartphone,
|
Smartphone,
|
||||||
FileText
|
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import Button from "@/components/common/button";
|
import Button from "@/components/common/button";
|
||||||
import StatCard from "@/components/common/dashStatCard";
|
import StatCard from "@/components/common/dashStatCard";
|
||||||
import InfoBanner from "@/components/common/infoBanner";
|
import InfoBanner from "@/components/common/infoBanner";
|
||||||
import Table from '@/components/common/dataTable';
|
import Table from '@/components/common/dataTable';
|
||||||
import { contractheaders, contractrows, devicefleetheaders, devicefleetrows } from '@/constants/tabledata';
|
import { devicefleetheaders, devicefleetrows } from '@/constants/tabledata';
|
||||||
|
|
||||||
export default function DeviceFleetPortal() {
|
export default function DeviceFleetPortal() {
|
||||||
return (
|
return (
|
||||||
@@ -19,12 +19,12 @@ export default function DeviceFleetPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-emerald-400 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-emerald-400 uppercase font-mono">
|
||||||
<span>APPLE ONE — HQ TOWER</span>
|
<span>APPLE ONE — HQ TOWER</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span className="text-slate-500">IOT</span>
|
<span className="text-gray-400">IOT</span>
|
||||||
<span className="text-slate-500">•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span className="text-slate-500">DEVICE FLEET</span>
|
<span className="text-gray-400">DEVICE FLEET</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-1">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-1">
|
||||||
Gateways, controllers & sensors
|
Gateways, controllers & sensors
|
||||||
|
|||||||
@@ -13,17 +13,17 @@ export default function EnergyUtilityPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[11px] font-semibold tracking-widest text-[#4e6178] uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-semibold tracking-widest text-[#4e6178] uppercase font-mono">
|
||||||
<span className="text-emerald-400 font-bold">APPLE ONE — HQ TOWER</span>
|
<span className="text-emerald-400 font-bold">APPLE ONE — HQ TOWER</span>
|
||||||
<span>•</span>
|
<span className='text-gray-600'>•</span>
|
||||||
<span>IOT</span>
|
<span className='text-gray-400'>IOT</span>
|
||||||
<span>•</span>
|
<span className='text-gray-600'>•</span>
|
||||||
<span>ENERGY & UTILITIES</span>
|
<span className='text-gray-400'>ENERGY & UTILITIES</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-1">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-1">
|
||||||
Energy & utilities telemetry
|
Energy & utilities telemetry
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-sm text-[#7f93ac] mt-2 max-w-xl leading-relaxed">
|
<p className="text-sm text-[#7f93ac] font-medium mt-2 max-w-xl leading-relaxed">
|
||||||
Live smart-meter streams for power, water and gas — the same spine that feeds the Energy module and ESG reporting.
|
Live smart-meter streams for power, water and gas — the same spine that feeds the Energy module and ESG reporting.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,22 +4,9 @@ import Button from "@/components/common/button";
|
|||||||
import { Card } from '@/components/common/cardWrapper';
|
import { Card } from '@/components/common/cardWrapper';
|
||||||
|
|
||||||
import BarChart from "@/components/charts/barchart"; // Replace path with your actual BarChart component import path
|
import BarChart from "@/components/charts/barchart"; // Replace path with your actual BarChart component import path
|
||||||
|
import { plantLoadData } from '@/constants/constant';
|
||||||
|
|
||||||
const plantLoadData = [
|
|
||||||
{ month: '08', height: 'h-[35%]' },
|
|
||||||
{ month: '09', height: 'h-[38%]' },
|
|
||||||
{ month: '10', height: 'h-[32%]' },
|
|
||||||
{ month: '11', height: 'h-[40%]' },
|
|
||||||
{ month: '12', height: 'h-[52%]' },
|
|
||||||
{ month: '13', height: 'h-[68%]' },
|
|
||||||
{ month: '14', height: 'h-[78%]' },
|
|
||||||
{ month: '15', height: 'h-[78%]' },
|
|
||||||
{ month: '16', height: 'h-[78%]' },
|
|
||||||
{ month: '17', height: 'h-[78%]' },
|
|
||||||
{ month: '18', height: 'h-[78%]' },
|
|
||||||
{ month: '19', height: 'h-[78%]' }
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function HVACPlantPortal() {
|
export default function HVACPlantPortal() {
|
||||||
return (
|
return (
|
||||||
<div className="my-15 text-slate-100 font-sans">
|
<div className="my-15 text-slate-100 font-sans">
|
||||||
@@ -27,17 +14,17 @@ export default function HVACPlantPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[11px] font-semibold tracking-widest text-[#4e6178] uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-semibold tracking-widest text-[#4e6178] uppercase font-mono">
|
||||||
<span className="text-emerald-400 font-bold">APPLE ONE — HQ TOWER</span>
|
<span className="text-emerald-400 font-bold">APPLE ONE — HQ TOWER</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>IOT</span>
|
<span className="text-gray-400">IOT</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>HVAC PLANT</span>
|
<span className="text-gray-400">HVAC PLANT</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-3xl font-bold text-white tracking-tight mt-1">
|
<h1 className="text-3xl font-bold text-white tracking-tight mt-1">
|
||||||
Chiller plant & air side
|
Chiller plant & air side
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-sm text-[#7f93ac] mt-2 max-w-xl leading-relaxed">
|
<p className="text-sm text-[#7f93ac] font-medium mt-2 max-w-xl leading-relaxed">
|
||||||
Live chiller, AHU and plant telemetry with start/stop control — commands are audit-logged.
|
Live chiller, AHU and plant telemetry with start/stop control — commands are audit-logged.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -221,9 +208,9 @@ export default function HVACPlantPortal() {
|
|||||||
<td className="py-3.5 text-slate-500">— / —</td>
|
<td className="py-3.5 text-slate-500">— / —</td>
|
||||||
<td className="py-3.5 text-slate-400">0</td>
|
<td className="py-3.5 text-slate-400">0</td>
|
||||||
<td className="py-3.5 text-right">
|
<td className="py-3.5 text-right">
|
||||||
<button className="px-3 py-1 rounded border border-[#162942] text-slate-300 bg-[#0e1c2e] hover:bg-slate-800 text-[11px] font-semibold transition-colors">
|
<Button className="px-3 py-1 rounded border border-[#162942] text-slate-300 bg-[#0e1c2e] hover:bg-slate-800 text-[11px] font-semibold transition-colors">
|
||||||
Start
|
Start
|
||||||
</button>
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@@ -42,17 +42,35 @@ export default function EnergyPortal() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 xl:grid-cols-2 gap-6 items-start">
|
||||||
{/* --- TABLES GRID (SIDE-BY-SIDE) --- */}
|
|
||||||
<div className="grid grid-cols-1 xl:grid-cols-2 gap-2 items-start">
|
|
||||||
|
|
||||||
{/* LEFT TABLE: METER MASTER */}
|
{/* LEFT TABLE: STOCK MASTER */}
|
||||||
<Table headers={meterHeaders} rows={meterRows}/>
|
<div className=" border border-slate-800/80 rounded-lg ">
|
||||||
{/* Right table */}
|
<div className="flex items-center justify-between px-4
|
||||||
<Table headers={readingHeaders} rows={readingRows}/>
|
py-4 border-b border-slate-800/80">
|
||||||
</div>
|
<h2 className="text-base font-semibold text-white">Meter Master</h2>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Corrected column layout and removed horizontal scrollbar to align with the right UI. */}
|
||||||
|
<Table headers={meterHeaders} rows={meterRows}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* RIGHT TABLE: CONSUMPTION LEDGER */}
|
||||||
|
<div className=" w-full border
|
||||||
|
border-slate-800/80 rounded-lg overflow-hidden">
|
||||||
|
<div className="flex items-center justify-between px-6 py-4 border-b border-slate-800/80">
|
||||||
|
<h2 className="text-base font-semibold text-white">Latest Readings</h2>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Table headers={readingHeaders} rows={readingRows}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -9,7 +9,8 @@ import {
|
|||||||
import Button from "@/components/common/button";
|
import Button from "@/components/common/button";
|
||||||
import StatCard from "@/components/common/dashStatCard";
|
import StatCard from "@/components/common/dashStatCard";
|
||||||
import InfoBanner from "@/components/common/infoBanner";
|
import InfoBanner from "@/components/common/infoBanner";
|
||||||
import { consumptionLedger, stockItems } from "@/constants/constant";
|
import Table from "@/components/common/dataTable";
|
||||||
|
import { consumptionHeaders, consumptionRows, inventoryHeaders, inventoryRows, } from "@/constants/tabledata";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -104,87 +105,19 @@ export default function InventoryPortal() {
|
|||||||
<div className="grid grid-cols-1 xl:grid-cols-2 gap-6 items-start">
|
<div className="grid grid-cols-1 xl:grid-cols-2 gap-6 items-start">
|
||||||
|
|
||||||
{/* LEFT TABLE: STOCK MASTER */}
|
{/* LEFT TABLE: STOCK MASTER */}
|
||||||
<div className="bg-[#0b1329] border border-slate-800/80 rounded-lg overflow-hidden">
|
<div className=" border border-slate-800/80 rounded-lg ">
|
||||||
<div className="flex items-center justify-between px-6 py-4 border-b border-slate-800/80">
|
<div className="flex items-center justify-between px-4
|
||||||
|
py-4 border-b border-slate-800/80">
|
||||||
<h2 className="text-base font-semibold text-white">Stock master</h2>
|
<h2 className="text-base font-semibold text-white">Stock master</h2>
|
||||||
<span className="text-xs font-mono text-slate-500">7 items</span>
|
<span className="text-xs font-mono text-slate-500">7 items</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Corrected column layout and removed horizontal scrollbar to align with the right UI. */}
|
{/* Corrected column layout and removed horizontal scrollbar to align with the right UI. */}
|
||||||
<div className="">
|
<Table headers={inventoryHeaders} rows={inventoryRows} />
|
||||||
<table className="w-full h-full text-left text-sm">
|
|
||||||
<thead>
|
|
||||||
<tr className="border-b border-slate-800/60 text-[11px] font-bold uppercase tracking-wider text-slate-400">
|
|
||||||
<th className="py-3 px-4">Item</th>
|
|
||||||
<th className="py-3 px-4">Group</th>
|
|
||||||
<th className="py-3 px-4">Store</th>
|
|
||||||
<th className="py-3 px-4">Min</th>
|
|
||||||
<th className="py-3 px-4">Present</th>
|
|
||||||
<th className="py-3 px-4">Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody className="divide-y divide-slate-800/40">
|
|
||||||
{stockItems.map((row, index) => {
|
|
||||||
const isOverdue = row.status === "OVERDUE";
|
|
||||||
return (
|
|
||||||
<tr
|
|
||||||
key={index}
|
|
||||||
className={`transition-colors relative ${
|
|
||||||
row.isHighlighted
|
|
||||||
? "bg-[#0e2238]"
|
|
||||||
: "hover:bg-slate-800/30"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<td className="py-3 px-4 font-semibold text-slate-100 relative">
|
|
||||||
{row.isHighlighted && (
|
|
||||||
<div className="absolute left-0 top-0 bottom-0 w-[3px] bg-teal-400" />
|
|
||||||
)}
|
|
||||||
{row.item}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-4 text-slate-300 font-medium whitespace-nowrap">
|
|
||||||
{row.group}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-4 text-slate-300 font-medium whitespace-nowrap">
|
|
||||||
{row.store}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-4 text-slate-300 font-medium whitespace-nowrap">
|
|
||||||
{row.min}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-4 font-semibold whitespace-nowrap">
|
|
||||||
<span className={isOverdue ? "text-rose-400" : "text-white"}>
|
|
||||||
{row.presentValue}{" "}
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
className={`font-mono text-xs ${
|
|
||||||
isOverdue ? "text-rose-400" : "text-slate-300"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{row.unit}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-4">
|
|
||||||
{row.status === "COMPLETED" ? (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[10px] font-bold tracking-wider bg-emerald-950/60 text-emerald-400 border border-emerald-800/30">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400"></span>
|
|
||||||
COMPLETED
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[10px] font-bold tracking-wider bg-rose-950/40 text-rose-400 border border-rose-900/30">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-rose-400"></span>
|
|
||||||
OVERDUE
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* RIGHT TABLE: CONSUMPTION LEDGER */}
|
{/* RIGHT TABLE: CONSUMPTION LEDGER */}
|
||||||
<div className="bg-[#0b1329] border border-slate-800/80 rounded-lg overflow-hidden">
|
<div className="h-full w-full border border-slate-800/80 rounded-lg overflow-hidden">
|
||||||
<div className="flex items-center justify-between px-6 py-4 border-b border-slate-800/80">
|
<div className="flex items-center justify-between px-6 py-4 border-b border-slate-800/80">
|
||||||
<h2 className="text-base font-semibold text-white">Consumption ledger</h2>
|
<h2 className="text-base font-semibold text-white">Consumption ledger</h2>
|
||||||
<span className="text-xs font-mono text-slate-500 lowercase">
|
<span className="text-xs font-mono text-slate-500 lowercase">
|
||||||
@@ -192,54 +125,7 @@ export default function InventoryPortal() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<Table headers={consumptionHeaders} rows={consumptionRows} />
|
||||||
<table className="w-full h-full text-left text-sm">
|
|
||||||
<thead>
|
|
||||||
<tr className="border-b border-slate-800/60 text-[11px] font-bold uppercase tracking-wider text-slate-400">
|
|
||||||
<th className="py-3 px-4">Txn</th>
|
|
||||||
<th className="py-3 px-4">Item</th>
|
|
||||||
<th className="py-3 px-4">Type</th>
|
|
||||||
<th className="py-3 px-4">Qty</th>
|
|
||||||
<th className="py-3 px-4">Job Card</th>
|
|
||||||
<th className="py-3 px-4">Date</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody className="divide-y divide-slate-800/40">
|
|
||||||
{consumptionLedger.map((row, index) => (
|
|
||||||
<tr key={index} className="hover:bg-slate-800/30 transition-colors">
|
|
||||||
<td className="py-3 px-4 font-mono text-teal-400 font-medium text-xs whitespace-nowrap">
|
|
||||||
{row.txn}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-4 font-semibold text-slate-100 max-w-[140px]">
|
|
||||||
{row.item}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-4 whitespace-nowrap">
|
|
||||||
{row.type === "Consume" ? (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium bg-amber-950/40 text-amber-300 border border-amber-800/30">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-amber-400"></span>
|
|
||||||
Consume
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-950/40 text-blue-300 border border-blue-800/30">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-blue-400"></span>
|
|
||||||
Receipt
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-4 font-medium text-slate-200 whitespace-nowrap">
|
|
||||||
{row.qty}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-4 font-mono text-teal-400 text-xs whitespace-nowrap">
|
|
||||||
{row.jobCard}
|
|
||||||
</td>
|
|
||||||
<td className="py-3 px-4 text-slate-300 text-xs font-medium whitespace-nowrap">
|
|
||||||
{row.date}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import {
|
import {
|
||||||
Star,
|
Star,
|
||||||
ShieldCheck,
|
ShieldCheck,
|
||||||
Activity,
|
Activity,
|
||||||
Clock,
|
Clock,
|
||||||
BarChart2,
|
BarChart2,
|
||||||
Plus
|
Plus,
|
||||||
|
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import Button from "@/components/common/button";
|
import Button from "@/components/common/button";
|
||||||
import StatCard from "@/components/common/dashStatCard";
|
import StatCard from "@/components/common/dashStatCard";
|
||||||
import InfoBanner from "@/components/common/infoBanner";
|
import InfoBanner from "@/components/common/infoBanner";
|
||||||
import { fieldCrewData, vendorData } from '@/constants/constant';
|
import Table from "@/components/common/dataTable";
|
||||||
|
import { teamStatusRows, teamStatusHeaders, vendorPerformanceHeaders, vendorPerformanceRows } from "@/constants/tabledata";
|
||||||
|
|
||||||
export default function VendorServicePortal() {
|
export default function VendorServicePortal() {
|
||||||
|
|
||||||
@@ -99,111 +101,23 @@ export default function VendorServicePortal() {
|
|||||||
<div className="grid grid-cols-1 xl:grid-cols-3 gap-6 items-start">
|
<div className="grid grid-cols-1 xl:grid-cols-3 gap-6 items-start">
|
||||||
|
|
||||||
{/* LEFT TABLE: VENDOR SCORECARD */}
|
{/* LEFT TABLE: VENDOR SCORECARD */}
|
||||||
<div className="xl:col-span-2 bg-[#0b1329] border border-slate-800/80 rounded-lg overflow-hidden">
|
<div className="xl:col-span-2 border border-slate-800/80 rounded-lg overflow-hidden">
|
||||||
<div className="flex items-center justify-between px-6 py-4 border-b border-slate-800/80">
|
<div className="flex items-center justify-between px-6 py-4 border-b border-slate-800/80">
|
||||||
<h2 className="text-base font-semibold text-white">Vendor scorecard</h2>
|
<h2 className="text-base font-semibold text-white">Vendor scorecard</h2>
|
||||||
<span className="text-xs font-mono text-slate-500 lowercase">
|
|
||||||
SLA • rating • jobs
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="overflow-x-auto">
|
<Table headers={vendorPerformanceHeaders} rows={vendorPerformanceRows} />
|
||||||
<table className="w-full text-left text-sm">
|
|
||||||
<thead>
|
|
||||||
<tr className="border-b border-slate-800/60 text-[11px] font-bold uppercase tracking-wider text-slate-400">
|
|
||||||
<th className="py-3 px-6">Vendor</th>
|
|
||||||
<th className="py-3 px-4">Scope</th>
|
|
||||||
<th className="py-3 px-4">Rating</th>
|
|
||||||
<th className="py-3 px-4">SLA</th>
|
|
||||||
<th className="py-3 px-4">Response</th>
|
|
||||||
<th className="py-3 px-6">Open</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody className="divide-y divide-slate-800/40">
|
|
||||||
{vendorData.map((row, index) => (
|
|
||||||
<tr key={index} className="hover:bg-slate-800/30 transition-colors">
|
|
||||||
<td className="py-4 px-6">
|
|
||||||
<div className="font-semibold text-slate-100">{row.name}</div>
|
|
||||||
<div className="text-xs font-mono text-slate-500 mt-0.5">{row.id}</div>
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-4 text-slate-300 font-medium whitespace-nowrap">
|
|
||||||
{row.scope}
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-4 font-medium text-slate-200 whitespace-nowrap">
|
|
||||||
<div className="flex items-center gap-1">
|
|
||||||
<span>{row.rating}</span>
|
|
||||||
<Star className="w-3.5 h-3.5 fill-amber-400 text-amber-400" />
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className={`py-4 px-4 font-semibold whitespace-nowrap ${row.slaColor}`}>
|
|
||||||
{row.sla}
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-4 text-slate-300 font-medium whitespace-nowrap">
|
|
||||||
{row.response}
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-6 font-semibold text-blue-400 whitespace-nowrap">
|
|
||||||
{row.openJobs}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* RIGHT TABLE: FIELD CREW • LIVE */}
|
{/* RIGHT TABLE: FIELD CREW • LIVE */}
|
||||||
<div className="bg-[#0b1329] border border-slate-800/80 rounded-lg overflow-hidden">
|
<div className=" border border-slate-800/80 rounded-lg overflow-hidden">
|
||||||
<div className="flex items-center justify-between px-6 py-4 border-b border-slate-800/80">
|
<div className="flex items-center justify-between px-6 py-4 border-b border-slate-800/80">
|
||||||
<h2 className="text-base font-semibold text-white">Field crew • live</h2>
|
<h2 className="text-base font-semibold text-white">Field crew • live</h2>
|
||||||
<span className="text-xs font-mono text-slate-500 lowercase">
|
|
||||||
4 on site
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-4 space-y-3">
|
<Table headers={teamStatusHeaders} rows={teamStatusRows} />
|
||||||
{fieldCrewData.map((crew, index) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="flex items-center justify-between p-3 rounded-lg bg-[#0d1835]/50 hover:bg-slate-800/30 transition-colors border border-slate-800/40"
|
|
||||||
>
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div className="w-9 h-9 rounded-lg bg-teal-950/60 border border-teal-800/30 text-teal-400 text-xs font-bold flex items-center justify-center shrink-0">
|
|
||||||
{crew.initials}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="font-semibold text-slate-100 text-sm">{crew.name}</div>
|
|
||||||
<div className="text-xs text-slate-400 mt-0.5">{crew.role}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="text-right shrink-0">
|
|
||||||
{crew.statusType === "onsite" && (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-bold tracking-wider bg-emerald-950/60 text-emerald-400 border border-emerald-800/30">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400"></span>
|
|
||||||
{crew.status}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{crew.statusType === "enroute" && (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-bold tracking-wider bg-amber-950/60 text-amber-400 border border-amber-800/30">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-amber-400"></span>
|
|
||||||
{crew.status}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{crew.statusType === "offsite" && (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-bold tracking-wider bg-slate-800/80 text-slate-400 border border-slate-700/50">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-slate-500"></span>
|
|
||||||
{crew.status}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
<div className="text-[11px] font-mono text-slate-500 mt-1">
|
|
||||||
{crew.time}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import { permitsData, workPermitFilters } from '@/constants/constant';
|
|||||||
import FilterTabs from '@/components/common/roundedFilters';
|
import FilterTabs from '@/components/common/roundedFilters';
|
||||||
import StatCard from '@/components/common/dashStatCard';
|
import StatCard from '@/components/common/dashStatCard';
|
||||||
import InfoBanner from '@/components/common/infoBanner';
|
import InfoBanner from '@/components/common/infoBanner';
|
||||||
|
import Table from '@/components/common/dataTable';
|
||||||
|
import { workPermitHeaders, workPermitRows } from '@/constants/tabledata';
|
||||||
|
|
||||||
export default function WorkPermitPortal() {
|
export default function WorkPermitPortal() {
|
||||||
|
|
||||||
@@ -13,61 +15,7 @@ export default function WorkPermitPortal() {
|
|||||||
// Permit Data matching the UI
|
// Permit Data matching the UI
|
||||||
|
|
||||||
|
|
||||||
const renderStatusBadge = (status: string) => {
|
|
||||||
switch (status) {
|
|
||||||
case "ACTIVE":
|
|
||||||
return (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-bold tracking-wider bg-emerald-950/60 text-emerald-400 border border-emerald-800/40">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400"></span>
|
|
||||||
ACTIVE
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
case "SUBMITTED":
|
|
||||||
return (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-bold tracking-wider bg-amber-950/50 text-amber-300 border border-amber-800/40">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-amber-400"></span>
|
|
||||||
SUBMITTED
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
case "APPROVED":
|
|
||||||
return (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-bold tracking-wider bg-blue-950/60 text-blue-400 border border-blue-800/40">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-blue-400"></span>
|
|
||||||
APPROVED
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
case "EXPIRED":
|
|
||||||
return (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-bold tracking-wider bg-rose-950/40 text-rose-400 border border-rose-900/30">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-rose-400"></span>
|
|
||||||
EXPIRED
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
case "CLOSED":
|
|
||||||
return (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-bold tracking-wider bg-slate-800/80 text-slate-400 border border-slate-700/50">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-slate-400"></span>
|
|
||||||
CLOSED
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
case "REJECTED":
|
|
||||||
return (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-bold tracking-wider bg-rose-950/40 text-rose-400 border border-rose-900/30">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-rose-400"></span>
|
|
||||||
REJECTED
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
case "DRAFT":
|
|
||||||
return (
|
|
||||||
<span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-bold tracking-wider bg-slate-800/80 text-slate-400 border border-slate-700/50">
|
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-slate-400"></span>
|
|
||||||
DRAFT
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="my-15 text-slate-100 font-sans">
|
<div className="my-15 text-slate-100 font-sans">
|
||||||
@@ -103,10 +51,7 @@ export default function WorkPermitPortal() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* --- NAVIGATION TABS & TOP ACTION BUTTONS --- */}
|
|
||||||
<div className="flex flex-col md:flex-row md:items-center justify-between border-b border-slate-800/80 mb-6 gap-4">
|
|
||||||
{/* Navigation tabs component if needed */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* --- STAT CARDS --- */}
|
{/* --- STAT CARDS --- */}
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
|
||||||
@@ -166,94 +111,7 @@ export default function WorkPermitPortal() {
|
|||||||
|
|
||||||
{/* --- PERMIT TABLE SECTION --- */}
|
{/* --- PERMIT TABLE SECTION --- */}
|
||||||
<div className="bg-[#0b1329] border border-slate-800/80 rounded-lg overflow-x-auto">
|
<div className="bg-[#0b1329] border border-slate-800/80 rounded-lg overflow-x-auto">
|
||||||
<table className="w-full text-left text-sm">
|
<Table headers={workPermitHeaders} rows={workPermitRows}/>
|
||||||
<thead>
|
|
||||||
<tr className="border-b border-slate-800/80 text-[11px] font-bold uppercase tracking-wider text-slate-400">
|
|
||||||
<th className="py-3 px-4">Permit</th>
|
|
||||||
<th className="py-3 px-4">Working Type</th>
|
|
||||||
<th className="py-3 px-4">Location</th>
|
|
||||||
<th className="py-3 px-4">Contractor</th>
|
|
||||||
<th className="py-3 px-4">Validity</th>
|
|
||||||
<th className="py-3 px-4">Crew</th>
|
|
||||||
<th className="py-3 px-4">Status</th>
|
|
||||||
<th className="py-3 px-4 text-right"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody className="divide-y divide-slate-800/40">
|
|
||||||
{permitsData.map((row, index) => (
|
|
||||||
<tr
|
|
||||||
key={index}
|
|
||||||
className={`transition-colors relative ${
|
|
||||||
row.isHighlighted ? "bg-[#0e2238]" : "hover:bg-slate-800/30"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{/* Permit ID */}
|
|
||||||
<td className="py-4 px-4 font-mono text-teal-400 font-medium text-xs whitespace-nowrap relative">
|
|
||||||
{row.isHighlighted && (
|
|
||||||
<div className="absolute left-0 top-0 bottom-0 w-[3px] bg-teal-400" />
|
|
||||||
)}
|
|
||||||
{row.permit}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{/* Working Type */}
|
|
||||||
<td className="py-4 px-4 font-semibold text-slate-100 whitespace-nowrap">
|
|
||||||
{row.workingType}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{/* Location */}
|
|
||||||
<td className="py-4 px-4 text-slate-300 font-medium whitespace-nowrap">
|
|
||||||
{row.location}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{/* Contractor */}
|
|
||||||
<td className="py-4 px-4 text-slate-300 font-medium whitespace-nowrap">
|
|
||||||
{row.contractor}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{/* Validity */}
|
|
||||||
<td className="py-4 px-4 whitespace-nowrap">
|
|
||||||
<div className="text-xs text-slate-300 font-medium">{row.validityDate}</div>
|
|
||||||
<div className="text-[11px] font-mono text-slate-500">{row.validityTime}</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{/* Crew */}
|
|
||||||
<td className="py-4 px-4 text-slate-300 font-medium whitespace-nowrap">
|
|
||||||
{row.crew}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{/* Status Badge */}
|
|
||||||
<td className="py-4 px-4 whitespace-nowrap">
|
|
||||||
{renderStatusBadge(row.status)}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{/* Actions */}
|
|
||||||
<td className="py-4 px-4 text-right whitespace-nowrap">
|
|
||||||
<div className="flex items-center justify-end gap-2">
|
|
||||||
{row.hasViewIconOnly ? (
|
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<button className="p-1.5 text-slate-400 hover:text-white bg-slate-800/40 hover:bg-slate-800 rounded border border-slate-700/50 transition-colors">
|
|
||||||
<FileText size={14} />
|
|
||||||
</button>
|
|
||||||
<button className="p-1.5 text-slate-400 hover:text-white bg-slate-800/40 hover:bg-slate-800 rounded border border-slate-700/50 transition-colors">
|
|
||||||
<Eye size={14} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="flex flex-col items-center gap-1">
|
|
||||||
<button className="p-1.5 text-slate-400 hover:text-white bg-slate-800/40 hover:bg-slate-800 rounded border border-slate-700/50 transition-colors">
|
|
||||||
<FileText size={14} />
|
|
||||||
</button>
|
|
||||||
<button className="text-teal-400 hover:text-teal-300 text-xs font-semibold hover:underline">
|
|
||||||
{row.actionText}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-10 mt-10">
|
<div className="mb-10 mt-10">
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ import { Check } from 'lucide-react';
|
|||||||
import BarChart from "@/components/charts/barchart";
|
import BarChart from "@/components/charts/barchart";
|
||||||
import StatCard from "@/components/common/dashStatCard";
|
import StatCard from "@/components/common/dashStatCard";
|
||||||
import ActivityFeed from "@/components/dashboard/overview/activityFeed";
|
import ActivityFeed from "@/components/dashboard/overview/activityFeed";
|
||||||
import {activities, chartData, schedulePerformanceHeaders, schedulePerformanceRows} from "@/constants/constant"
|
import {activities, chartData} from "@/constants/constant"
|
||||||
import { Card } from '@/components/common/cardWrapper';
|
import { Card } from '@/components/common/cardWrapper';
|
||||||
import {CardHeader} from '@/components/common/cardHeader';
|
import {CardHeader} from '@/components/common/cardHeader';
|
||||||
import {ProgressBarRow }from '@/components/charts/progressBarRow';
|
import {ProgressBarRow }from '@/components/charts/progressBarRow';
|
||||||
import {StatusProgressRow} from '@/components/charts/statusProgressRow';
|
import {StatusProgressRow} from '@/components/charts/statusProgressRow';
|
||||||
import Table from '@/components/common/dataTable';
|
import Table from '@/components/common/dataTable';
|
||||||
|
import { schedulePerformanceHeaders, schedulePerformanceRows } from '@/constants/tabledata';
|
||||||
|
|
||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ export default function MeetingRoomPortal() {
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
||||||
<span className="text-teal-400">Apple One — HQ Tower</span>
|
<span className="text-teal-400">Apple One — HQ Tower</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>WORKPLACE</span>
|
<span className="text-gray-400">WORKPLACE</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>MEETING ROOMS</span>
|
<span className="text-gray-400">MEETING ROOMS</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-1">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-1">
|
||||||
Meeting room booking
|
Meeting room booking
|
||||||
@@ -136,15 +136,15 @@ export default function MeetingRoomPortal() {
|
|||||||
<div className="flex items-center justify-between border-t border-[#162942]/60 pt-3 mt-2">
|
<div className="flex items-center justify-between border-t border-[#162942]/60 pt-3 mt-2">
|
||||||
<span className="text-xs text-slate-400">{room.subtitle}</span>
|
<span className="text-xs text-slate-400">{room.subtitle}</span>
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-200 text-xs font-semibold px-3 py-1.5 rounded transition-colors">
|
<Button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-200 text-xs font-semibold px-3 py-1.5 rounded transition-colors">
|
||||||
{room.actionType === "book" ? "Book" : "View"}
|
{room.actionType === "book" ? "Book" : "View"}
|
||||||
</button>
|
</Button>
|
||||||
<button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-400 hover:text-slate-200 p-1.5 rounded transition-colors">
|
<Button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-400 hover:text-slate-200 p-1.5 rounded transition-colors">
|
||||||
<Pencil className="w-3.5 h-3.5" />
|
<Pencil className="w-3.5 h-3.5" />
|
||||||
</button>
|
</Button>
|
||||||
<button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-400 hover:text-rose-400 p-1.5 rounded transition-colors">
|
<Button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-400 hover:text-rose-400 p-1.5 rounded transition-colors">
|
||||||
<Trash2 className="w-3.5 h-3.5" />
|
<Trash2 className="w-3.5 h-3.5" />
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ const [activeFilter, setActiveFilter] = useState<string>('All');
|
|||||||
{/* --- HEADER SECTION --- */}
|
{/* --- HEADER SECTION --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
||||||
<span className="text-teal-400">Apple One — HQ Tower</span>
|
<span className="text-teal-400">Apple One — HQ Tower</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>Workplace</span>
|
<span className="text-gray-400">Workplace</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>Visitors</span>
|
<span className="text-gray-400">Visitors</span>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
Visitor management
|
Visitor management
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ import { CardHeader } from '@/components/common/cardHeader';
|
|||||||
export default function WorkSpacePortal() {
|
export default function WorkSpacePortal() {
|
||||||
const [activeTab, setActiveTab] = useState<string>("Desk Booking");
|
const [activeTab, setActiveTab] = useState<string>("Desk Booking");
|
||||||
|
|
||||||
// Grid state matching the UI: 4 rows x 12 columns (48 seats)
|
|
||||||
// Types: 'occupied' (red/purple outline), 'free' (teal), 'reserved' (amber)
|
|
||||||
const deskGrid = Array.from({ length: 48 }).map((_, index) => {
|
const deskGrid = Array.from({ length: 48 }).map((_, index) => {
|
||||||
if (index === 42) return "reserved"; // 1 Reserved desk
|
if (index === 42) return "reserved"; // 1 Reserved desk
|
||||||
if (index >= 36) return "free"; // Free desks on the bottom row
|
if (index >= 36) return "free"; // Free desks on the bottom row
|
||||||
@@ -35,12 +34,12 @@ export default function WorkSpacePortal() {
|
|||||||
{/* --- HEADER SECTION WITH BUTTONS --- */}
|
{/* --- HEADER SECTION WITH BUTTONS --- */}
|
||||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
<div className="flex items-center gap-2 text-[12px] font-bold tracking-widest text-slate-500 uppercase font-mono">
|
||||||
<span className="text-teal-400">Apple One — HQ Tower</span>
|
<span className="text-teal-400">Apple One — HQ Tower</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>WORKPLACE</span>
|
<span className="text-gray-400">WORKPLACE</span>
|
||||||
<span>•</span>
|
<span className="text-gray-600">•</span>
|
||||||
<span>WORKSPACE</span>
|
<span className="text-gray-400">WORKSPACE</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
|
||||||
@@ -192,12 +191,12 @@ export default function WorkSpacePortal() {
|
|||||||
{/* Value & Actions */}
|
{/* Value & Actions */}
|
||||||
<div className="flex items-center gap-2 font-mono text-xs text-slate-200">
|
<div className="flex items-center gap-2 font-mono text-xs text-slate-200">
|
||||||
<span className="font-bold">{zone.current}/{zone.max}</span>
|
<span className="font-bold">{zone.current}/{zone.max}</span>
|
||||||
<button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-400 hover:text-slate-200 p-1 rounded transition-colors">
|
<Button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-400 hover:text-slate-200 p-1 rounded transition-colors">
|
||||||
<Pencil className="w-3 h-3" />
|
<Pencil className="w-3 h-3" />
|
||||||
</button>
|
</Button>
|
||||||
<button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-400 hover:text-rose-400 p-1 rounded transition-colors">
|
<Button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-400 hover:text-rose-400 p-1 rounded transition-colors">
|
||||||
<Trash2 className="w-3 h-3" />
|
<Trash2 className="w-3 h-3" />
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { OPERATIONS_SIDEBAR_ITEMS, ADMIN_SIDEBAR_ITEMS } from "@/constants/constant";
|
import { OPERATIONS_SIDEBAR_ITEMS, ADMIN_SIDEBAR_ITEMS } from "@/constants/sidebarConstant";
|
||||||
import SidebarItem from "./sideBarItem";
|
import SidebarItem from "./sideBarItem";
|
||||||
import { ShieldCheck, Activity, ChevronDown, ChevronsLeft } from "lucide-react";
|
import { ShieldCheck, Activity, ChevronDown, ChevronsLeft } from "lucide-react";
|
||||||
import { useSession, signOut } from "next-auth/react";
|
import { useSession, signOut } from "next-auth/react";
|
||||||
|
|||||||
@@ -1,178 +1,6 @@
|
|||||||
|
|
||||||
import {
|
|
||||||
LayoutGrid,
|
|
||||||
Smile,
|
|
||||||
Building2,
|
|
||||||
User,
|
|
||||||
Target,
|
|
||||||
CheckSquare,
|
|
||||||
FileText,
|
|
||||||
Box,
|
|
||||||
Zap,
|
|
||||||
ClipboardList,
|
|
||||||
Star,
|
|
||||||
Monitor,
|
|
||||||
UserCheck,
|
|
||||||
Calendar,
|
|
||||||
Layers,
|
|
||||||
Coins,
|
|
||||||
Receipt,
|
|
||||||
ShieldCheck,
|
|
||||||
Flame,
|
|
||||||
Recycle,
|
|
||||||
GraduationCap,
|
|
||||||
Brain,
|
|
||||||
Activity,
|
|
||||||
Bot,
|
|
||||||
Gauge,
|
|
||||||
Snowflake,
|
|
||||||
Leaf,
|
|
||||||
MapPin,
|
|
||||||
BarChart3,
|
|
||||||
Sun,
|
|
||||||
Shield,
|
|
||||||
Settings,
|
|
||||||
Wallet,
|
|
||||||
Radar,
|
|
||||||
Cog,
|
|
||||||
Smartphone,
|
|
||||||
Users,
|
|
||||||
Database,
|
|
||||||
Globe,
|
|
||||||
LayoutDashboard,
|
|
||||||
} from "lucide-react";
|
|
||||||
|
|
||||||
//Side bar Drop Down menu
|
|
||||||
|
|
||||||
export const OPERATIONS_SIDEBAR_ITEMS = [
|
|
||||||
{
|
|
||||||
title: "Overview",
|
|
||||||
icon: LayoutGrid,
|
|
||||||
children: [
|
|
||||||
{ title: "Dashboard", href: "/dashboard/overview/dashboard", icon: LayoutGrid },
|
|
||||||
{ title: "Engagement", href: "/dashboard/overview/engagement", icon: Smile },
|
|
||||||
{ title: "Building Owner", href: "/dashboard/overview/buildingOwner", icon: Building2 },
|
|
||||||
{ title: "Property Manager", href: "/dashboard/overview/propertyManager", icon: User },
|
|
||||||
{ title: "Service Engineer", href: "/dashboard/overview/serviceEngineer", icon: Target },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Operations",
|
|
||||||
icon: Settings,
|
|
||||||
children: [
|
|
||||||
{ title: "Help Desk", href: "/dashboard/operations/helpDesk", icon: CheckSquare, badge: 6, badgeColor: "bg-amber-500 text-black" },
|
|
||||||
{ title: "Equipment", href: "/dashboard/operations/equipment", icon: Target },
|
|
||||||
{ title: "Requests", href: "/dashboard/operations/request", icon: FileText, badge: 15, badgeColor: "bg-amber-400 text-black" },
|
|
||||||
{ title: "Inventory", href: "/dashboard/operations/inventory", icon: Box },
|
|
||||||
{ title: "Energy", href: "/dashboard/operations/energy", icon: Zap },
|
|
||||||
{ title: "Work Permit", href: "/dashboard/operations/workPermit", icon: ClipboardList, badge: 3, badgeColor: "bg-amber-500 text-black" },
|
|
||||||
{ title: "Vendor & Field Service", href: "/dashboard/operations/vendorFieldService", icon: Star, badge: 12, badgeColor: "bg-sky-400 text-black" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Workplace",
|
|
||||||
icon: Monitor,
|
|
||||||
children: [
|
|
||||||
{ title: "Visitor Management", href: "/dashboard/workplace/visitorManagement", icon: UserCheck },
|
|
||||||
{ title: "Meeting Rooms", href: "/dashboard/workplace/meetingRoom", icon: Calendar },
|
|
||||||
{ title: "Workspace", href: "/dashboard/workplace/workspace", icon: Layers },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Finance",
|
|
||||||
icon: Wallet,
|
|
||||||
children: [
|
|
||||||
{ title: "O&M Budget", href: "/dashboard/finance/budget", icon: Coins },
|
|
||||||
{ title: "Costing & Invoicing", href: "/dashboard/finance/costinvoice", icon: Receipt },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Compliance & Safety",
|
|
||||||
icon: ShieldCheck,
|
|
||||||
children: [
|
|
||||||
{ title: "Statutory Compliance", href: "/dashboard/compliance-safety/statutoryCompliance", icon: ShieldCheck },
|
|
||||||
{ title: "Contracts & SLA", href: "/dashboard/compliance-safety/contracts", icon: FileText },
|
|
||||||
{ title: "Fire & Safety", href: "/dashboard/compliance-safety/fireAndSafety", icon: Flame },
|
|
||||||
{ title: "Waste & ESG", href: "/dashboard/compliance-safety/wasteAndEsg", icon: Recycle },
|
|
||||||
{ title: "Training", href: "/dashboard/compliance-safety/training", icon: GraduationCap },
|
|
||||||
{ title: "Audit & Survey", href: "/dashboard/compliance-safety/auditAndSurvey", icon: GraduationCap },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Intelligence",
|
|
||||||
icon: Brain,
|
|
||||||
children: [{ title: "AI & Predictive", href: "/dashboard/intelligence/aiPredictive", icon: Brain },
|
|
||||||
{ title: "Asset Health", href: "/dashboard/intelligence/assetHealth", icon: ShieldCheck },
|
|
||||||
{ title: "Energy Benchmarking", href: "/dashboard/intelligence/energyBenchmarking", icon: Activity },
|
|
||||||
{ title: "AI Helpdesk", href: "/dashboard/intelligence/aiHelpdesk", icon: Bot },
|
|
||||||
{ title: "Connected Ops", href: "/dashboard/intelligence/connectedOps", icon: Gauge },
|
|
||||||
{ title: "Connected Assets", href: "/dashboard/intelligence/connectedAsset", icon: Snowflake },
|
|
||||||
{ title: "Sustainability", href: "/dashboard/intelligence/sustainability", icon: Leaf },
|
|
||||||
{ title: "GPS Tracking", href: "/dashboard/intelligence/gpstracking", icon: MapPin },],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "IoT Application",
|
|
||||||
icon: Radar,
|
|
||||||
children: [{ title: "Command Center", href: "/dashboard/iot-app/commandCenter", icon: Gauge },
|
|
||||||
{ title: "HVAC Plant", href: "/dashboard/iot-app/hvacPlant", icon: Snowflake },
|
|
||||||
{ title: "Energy & Utilities", href: "/dashboard/iot-app/energyUtility", icon: Zap },
|
|
||||||
{ title: "Device Fleet", href: "/dashboard/iot-app/deviceFleet", icon: LayoutGrid },
|
|
||||||
{ title: "Alarms & Rules", href: "/dashboard/iot-app/alarmsRules", icon: Shield, badge: 7, badgeColor: "bg-rose-500 text-white" },],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Insight",
|
|
||||||
icon: BarChart3,
|
|
||||||
children: [{ title: "Reports & MMR", href: "/dashboard/insight/report", icon: BarChart3 },],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Configure",
|
|
||||||
icon: Cog,
|
|
||||||
children: [{ title: "Master Data", href: "/dashboard/configure/masterdata", icon: Layers },
|
|
||||||
{ title: "Roles & Access", href: "/dashboard/configure/rolesAndAccess", icon: Shield },
|
|
||||||
{ title: "Workflow Automation", href: "/dashboard/configure/workflowautomation", icon: Bot },
|
|
||||||
{ title: "User Location", href: "/dashboard/configure/userLocation", icon: MapPin },
|
|
||||||
{ title: "Settings", href: "/dashboard/configure/settings", icon: Sun },],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
export const ADMIN_SIDEBAR_ITEMS = [
|
|
||||||
{
|
|
||||||
title: "Platform",
|
|
||||||
icon: Building2,
|
|
||||||
children: [
|
|
||||||
{ title: "Overview", href: "/dashboard/admin/overview", icon: LayoutGrid },
|
|
||||||
{ title: "Tenants", href: "/dashboard/admin/tenants", icon: Building2 },
|
|
||||||
{ title: "Users", href: "/dashboard/admin/users", icon: Users },
|
|
||||||
{ title: "Sites", href: "/dashboard/admin/site", icon: MapPin },
|
|
||||||
{ title: "Security", href: "/dashboard/admin/security", icon: Shield },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Configuration",
|
|
||||||
icon: LayoutGrid,
|
|
||||||
children: [
|
|
||||||
{ title: "Modules", href: "/dashboard/admin/modules", icon: LayoutGrid },
|
|
||||||
{ title: "Language", href: "/dashboard/admin/language", icon: Globe },
|
|
||||||
{ title: "Dynamic Dashboard", href: "/dashboard/admin/dynamicDashboard", icon: LayoutDashboard },
|
|
||||||
{ title: "Mobile Flows", href: "/dashboard/admin/mobileFlow", icon: Smartphone },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
export const schedulePerformanceHeaders = [
|
|
||||||
"Schedule",
|
|
||||||
"Total",
|
|
||||||
"Done",
|
|
||||||
"On Time",
|
|
||||||
"Delayed",
|
|
||||||
];
|
|
||||||
|
|
||||||
export const schedulePerformanceRows = [
|
|
||||||
["PPM", 24, 19, 17, 2],
|
|
||||||
["AMC", 8, 6, 6, 0],
|
|
||||||
];
|
|
||||||
|
|
||||||
//Overview dashboard data
|
|
||||||
|
|
||||||
export const chartData = [
|
export const chartData = [
|
||||||
{ month: 'J', height: 'h-24' },
|
{ month: 'J', height: 'h-24' },
|
||||||
@@ -562,325 +390,117 @@ export const scheduleItems = [
|
|||||||
{ frequency: "On call", stream: "Hazardous", vendor: "Ramky Enviro" },
|
{ frequency: "On call", stream: "Hazardous", vendor: "Ramky Enviro" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const stockItems = [
|
|
||||||
{
|
|
||||||
item: "Cooling tower fan belt",
|
|
||||||
group: "HVAC",
|
|
||||||
store: "Block Store",
|
|
||||||
min: 5,
|
|
||||||
presentValue: 8,
|
|
||||||
unit: "Gallon",
|
|
||||||
status: "COMPLETED",
|
|
||||||
isHighlighted: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
item: "Air filter 24×24",
|
|
||||||
group: "HVAC",
|
|
||||||
store: "Block Store",
|
|
||||||
min: 5,
|
|
||||||
presentValue: 2,
|
|
||||||
unit: "Nos",
|
|
||||||
status: "OVERDUE",
|
|
||||||
isHighlighted: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
item: "MCB 32A",
|
|
||||||
group: "Electrical",
|
|
||||||
store: "Block Store",
|
|
||||||
min: 5,
|
|
||||||
presentValue: 8,
|
|
||||||
unit: "Nos",
|
|
||||||
status: "COMPLETED",
|
|
||||||
isHighlighted: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
item: "Contactor 40A",
|
|
||||||
group: "Electrical",
|
|
||||||
store: "Block Store",
|
|
||||||
min: 2,
|
|
||||||
presentValue: 2,
|
|
||||||
unit: "Nos",
|
|
||||||
status: "OVERDUE",
|
|
||||||
isHighlighted: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
item: "PVC pipe 1\"",
|
|
||||||
group: "Plumbing",
|
|
||||||
store: "Main Store",
|
|
||||||
min: 3,
|
|
||||||
presentValue: 0,
|
|
||||||
unit: "Mtr",
|
|
||||||
status: "OVERDUE",
|
|
||||||
isHighlighted: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
item: "Submersible pump seal",
|
|
||||||
group: "Plumbing",
|
|
||||||
store: "Main Store",
|
|
||||||
min: 3,
|
|
||||||
presentValue: 2,
|
|
||||||
unit: "Nos",
|
|
||||||
status: "OVERDUE",
|
|
||||||
isHighlighted: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
item: "Refrigerant R410a",
|
|
||||||
group: "HVAC",
|
|
||||||
store: "Block Store",
|
|
||||||
min: 5,
|
|
||||||
presentValue: 0,
|
|
||||||
unit: "Kg",
|
|
||||||
status: "OVERDUE",
|
|
||||||
isHighlighted: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const consumptionLedger = [
|
export const plantLoadData = [
|
||||||
{
|
{ month: '08', height: 'h-[35%]' },
|
||||||
txn: "TXN-5200",
|
{ month: '09', height: 'h-[38%]' },
|
||||||
item: "Cooling tower fan belt",
|
{ month: '10', height: 'h-[32%]' },
|
||||||
type: "Consume",
|
{ month: '11', height: 'h-[40%]' },
|
||||||
qty: "2 Gallon",
|
{ month: '12', height: 'h-[52%]' },
|
||||||
jobCard: "026/1009",
|
{ month: '13', height: 'h-[68%]' },
|
||||||
date: "Jun 20, 2026",
|
{ month: '14', height: 'h-[78%]' },
|
||||||
},
|
{ month: '15', height: 'h-[78%]' },
|
||||||
{
|
{ month: '16', height: 'h-[78%]' },
|
||||||
txn: "TXN-5201",
|
{ month: '17', height: 'h-[78%]' },
|
||||||
item: "MCB 32A",
|
{ month: '18', height: 'h-[78%]' },
|
||||||
type: "Consume",
|
{ month: '19', height: 'h-[78%]' }
|
||||||
qty: "1 Nos",
|
];
|
||||||
jobCard: "026/1016",
|
|
||||||
date: "Jun 21, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5202",
|
|
||||||
item: "Air filter 24×24",
|
|
||||||
type: "Receipt",
|
|
||||||
qty: "10 Nos",
|
|
||||||
jobCard: "—",
|
|
||||||
date: "Jun 22, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5203",
|
|
||||||
item: "Submersible pump seal",
|
|
||||||
type: "Consume",
|
|
||||||
qty: "1 Nos",
|
|
||||||
jobCard: "026/1023",
|
|
||||||
date: "Jun 23, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5204",
|
|
||||||
item: "Air filter 24×24",
|
|
||||||
type: "Consume",
|
|
||||||
qty: "3 Nos",
|
|
||||||
jobCard: "026/1030",
|
|
||||||
date: "Jun 24, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5205",
|
|
||||||
item: "PVC pipe 1\"",
|
|
||||||
type: "Receipt",
|
|
||||||
qty: "20 Mtr",
|
|
||||||
jobCard: "—",
|
|
||||||
date: "Jun 25, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5406",
|
|
||||||
item: "Cooling tower fan belt",
|
|
||||||
type: "Consume",
|
|
||||||
qty: "2 Gallon",
|
|
||||||
jobCard: "026/1009",
|
|
||||||
date: "Jun 7, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5407",
|
|
||||||
item: "MCB 32A",
|
|
||||||
type: "Consume",
|
|
||||||
qty: "1 Nos",
|
|
||||||
jobCard: "026/1016",
|
|
||||||
date: "Jun 7, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5200",
|
|
||||||
item: "Cooling tower fan belt",
|
|
||||||
type: "Consume",
|
|
||||||
qty: "2 Gallon",
|
|
||||||
jobCard: "026/1009",
|
|
||||||
date: "Jun 20, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5201",
|
|
||||||
item: "MCB 32A",
|
|
||||||
type: "Consume",
|
|
||||||
qty: "1 Nos",
|
|
||||||
jobCard: "026/1016",
|
|
||||||
date: "Jun 21, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5202",
|
|
||||||
item: "Air filter 24×24",
|
|
||||||
type: "Receipt",
|
|
||||||
qty: "10 Nos",
|
|
||||||
jobCard: "—",
|
|
||||||
date: "Jun 22, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5203",
|
|
||||||
item: "Submersible pump seal",
|
|
||||||
type: "Consume",
|
|
||||||
qty: "1 Nos",
|
|
||||||
jobCard: "026/1023",
|
|
||||||
date: "Jun 23, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5204",
|
|
||||||
item: "Air filter 24×24",
|
|
||||||
type: "Consume",
|
|
||||||
qty: "3 Nos",
|
|
||||||
jobCard: "026/1030",
|
|
||||||
date: "Jun 24, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5205",
|
|
||||||
item: "PVC pipe 1\"",
|
|
||||||
type: "Receipt",
|
|
||||||
qty: "20 Mtr",
|
|
||||||
jobCard: "—",
|
|
||||||
date: "Jun 25, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5406",
|
|
||||||
item: "Cooling tower fan belt",
|
|
||||||
type: "Consume",
|
|
||||||
qty: "2 Gallon",
|
|
||||||
jobCard: "026/1009",
|
|
||||||
date: "Jun 7, 2026",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
txn: "TXN-5407",
|
|
||||||
item: "MCB 32A",
|
|
||||||
type: "Consume",
|
|
||||||
qty: "1 Nos",
|
|
||||||
jobCard: "026/1016",
|
|
||||||
date: "Jun 7, 2026",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
|
// Initial roles state
|
||||||
|
export const rolesList = [
|
||||||
|
{ id: "admin", label: "Admin", badge: "all" },
|
||||||
|
{ id: "helpdesk", label: "Helpdesk", badge: "scoped" },
|
||||||
|
{ id: "mne_supervisor", label: "M&E Supervisor", badge: "scoped" },
|
||||||
|
{ id: "technician", label: "Technician", badge: "scoped" },
|
||||||
|
{ id: "tenant", label: "Tenant", badge: "scoped" },
|
||||||
|
];
|
||||||
|
|
||||||
export const vendorData = [
|
// Initial permissions table data
|
||||||
{
|
export const initialPermissions = [
|
||||||
name: "Voltas Ltd",
|
{
|
||||||
id: "CTR-700",
|
id: 1,
|
||||||
scope: "HVAC AMC & breakdown",
|
module: "Help Desk",
|
||||||
rating: "4.6",
|
menu: "Daily Location Checklist",
|
||||||
sla: "95%",
|
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
||||||
slaColor: "text-emerald-400",
|
},
|
||||||
response: "4.0h",
|
{
|
||||||
openJobs: "2",
|
id: 2,
|
||||||
},
|
module: "Equipment",
|
||||||
{
|
menu: "Site-Wise Equipment",
|
||||||
name: "Blue Star",
|
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
||||||
id: "CTR-701",
|
},
|
||||||
scope: "Chiller & VRV service",
|
{
|
||||||
rating: "4.1",
|
id: 3,
|
||||||
sla: "88%",
|
module: "Equipment",
|
||||||
slaColor: "text-amber-400",
|
menu: "AMC Schedule",
|
||||||
response: "1.2h",
|
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
||||||
openJobs: "2",
|
},
|
||||||
},
|
{
|
||||||
{
|
id: 4,
|
||||||
name: "Sterling FM",
|
module: "Request",
|
||||||
id: "CTR-702",
|
menu: "TFM Request",
|
||||||
scope: "Integrated FM / soft services",
|
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
||||||
rating: "3.4",
|
},
|
||||||
sla: "94%",
|
{
|
||||||
slaColor: "text-emerald-400",
|
id: 5,
|
||||||
response: "2.4h",
|
module: "Energy",
|
||||||
openJobs: "4",
|
menu: "Meter Reading",
|
||||||
},
|
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
||||||
{
|
},
|
||||||
name: "OTIS Elevators",
|
{
|
||||||
id: "CTR-704",
|
id: 6,
|
||||||
scope: "Elevator AMC",
|
module: "Master",
|
||||||
rating: "4.8",
|
menu: "Request Location",
|
||||||
sla: "95%",
|
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
||||||
slaColor: "text-emerald-400",
|
},
|
||||||
response: "2.8h",
|
{
|
||||||
openJobs: "—",
|
id: 7,
|
||||||
},
|
module: "Security",
|
||||||
{
|
menu: "Users",
|
||||||
name: "Sodexo",
|
permissions: { all: false, view: true, add: true, edit: true, delete: false, cancel: true, print: true },
|
||||||
id: "CTR-705",
|
},
|
||||||
scope: "Soft services & cafeteria",
|
];
|
||||||
rating: "4.3",
|
|
||||||
sla: "90%",
|
|
||||||
slaColor: "text-amber-400",
|
|
||||||
response: "2.8h",
|
|
||||||
openJobs: "1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "In-house team",
|
|
||||||
id: "—",
|
|
||||||
scope: "Day-to-day maintenance",
|
|
||||||
rating: "4.0",
|
|
||||||
sla: "93%",
|
|
||||||
slaColor: "text-amber-400",
|
|
||||||
response: "3.2h",
|
|
||||||
openJobs: "3",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const fieldCrewData = [
|
|
||||||
{
|
|
||||||
initials: "RK",
|
|
||||||
name: "Ravi Kumar",
|
|
||||||
role: "M&E Technician • Chiller plant",
|
|
||||||
status: "ON-SITE",
|
|
||||||
statusType: "onsite",
|
|
||||||
time: "6.4h today",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
initials: "SI",
|
|
||||||
name: "Sana Iqbal",
|
|
||||||
role: "HVAC Engineer • AHU room L7",
|
|
||||||
status: "ON-SITE",
|
|
||||||
statusType: "onsite",
|
|
||||||
time: "6.1h today",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
initials: "MD",
|
|
||||||
name: "Mohan D.",
|
|
||||||
role: "Electrician • En route",
|
|
||||||
status: "EN-ROUTE",
|
|
||||||
statusType: "enroute",
|
|
||||||
time: "—",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
initials: "LN",
|
|
||||||
name: "Lakshmi N.",
|
|
||||||
role: "Housekeeping Lead • Lobby + L2",
|
|
||||||
status: "ON-SITE",
|
|
||||||
statusType: "onsite",
|
|
||||||
time: "6.7h today",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
initials: "AP",
|
|
||||||
name: "Arjun P.",
|
|
||||||
role: "Plumber • Off-site",
|
|
||||||
status: "OFF-SITE",
|
|
||||||
statusType: "offsite",
|
|
||||||
time: "—",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
initials: "FR",
|
|
||||||
name: "Fatima R.",
|
|
||||||
role: "BMS Operator • Control room",
|
|
||||||
status: "ON-SITE",
|
|
||||||
statusType: "onsite",
|
|
||||||
time: "7.6h today",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
|
export const blocks = ["Block 1", "Block 2", "Tower A"];
|
||||||
|
export const floors = ["Ground", "Floor 1", "Floor 2"];
|
||||||
|
export const zones = ["Zone N", "Zone Z1", "Zone Z2"];
|
||||||
|
// Mock user location data matching the screenshot
|
||||||
|
export const userData = [
|
||||||
|
{
|
||||||
|
name: "Dhananjay T.",
|
||||||
|
email: "dhananjay@kafm.io",
|
||||||
|
mobile: "7489477369",
|
||||||
|
latitude: "18.5450",
|
||||||
|
longitude: "73.7935",
|
||||||
|
site: "Apple One",
|
||||||
|
// Relative coordinates for the map visual dots (X%, Y%)
|
||||||
|
x: "19%",
|
||||||
|
y: "38%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ME Local",
|
||||||
|
email: "me.local@kafm.io",
|
||||||
|
mobile: "9876543210",
|
||||||
|
latitude: "18.5469",
|
||||||
|
longitude: "73.7945",
|
||||||
|
site: "Apple One",
|
||||||
|
x: "44%",
|
||||||
|
y: "43%",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TECH Local",
|
||||||
|
email: "tech.local@kafm.io",
|
||||||
|
mobile: "9123456780",
|
||||||
|
latitude: "18.5441",
|
||||||
|
longitude: "73.7951",
|
||||||
|
site: "Apple One",
|
||||||
|
x: "69%",
|
||||||
|
y: "48%",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export const permitsData = [
|
export const permitsData = [
|
||||||
{
|
{
|
||||||
permit: "PTW-2663",
|
permit: "PTW-2663",
|
||||||
|
|||||||
160
constants/sidebarConstant.ts
Normal file
160
constants/sidebarConstant.ts
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import {
|
||||||
|
LayoutGrid,
|
||||||
|
Smile,
|
||||||
|
Building2,
|
||||||
|
User,
|
||||||
|
Target,
|
||||||
|
CheckSquare,
|
||||||
|
FileText,
|
||||||
|
Box,
|
||||||
|
Zap,
|
||||||
|
ClipboardList,
|
||||||
|
Star,
|
||||||
|
Monitor,
|
||||||
|
UserCheck,
|
||||||
|
Calendar,
|
||||||
|
Layers,
|
||||||
|
Coins,
|
||||||
|
Receipt,
|
||||||
|
ShieldCheck,
|
||||||
|
Flame,
|
||||||
|
Recycle,
|
||||||
|
GraduationCap,
|
||||||
|
Brain,
|
||||||
|
Activity,
|
||||||
|
Bot,
|
||||||
|
Gauge,
|
||||||
|
Snowflake,
|
||||||
|
Leaf,
|
||||||
|
MapPin,
|
||||||
|
BarChart3,
|
||||||
|
Sun,
|
||||||
|
Shield,
|
||||||
|
Settings,
|
||||||
|
Wallet,
|
||||||
|
Radar,
|
||||||
|
Cog,
|
||||||
|
Smartphone,
|
||||||
|
Users,
|
||||||
|
Globe,
|
||||||
|
LayoutDashboard,
|
||||||
|
} from "lucide-react";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const OPERATIONS_SIDEBAR_ITEMS = [
|
||||||
|
{
|
||||||
|
title: "Overview",
|
||||||
|
icon: LayoutGrid,
|
||||||
|
children: [
|
||||||
|
{ title: "Dashboard", href: "/dashboard/overview/dashboard", icon: LayoutGrid },
|
||||||
|
{ title: "Engagement", href: "/dashboard/overview/engagement", icon: Smile },
|
||||||
|
{ title: "Building Owner", href: "/dashboard/overview/buildingOwner", icon: Building2 },
|
||||||
|
{ title: "Property Manager", href: "/dashboard/overview/propertyManager", icon: User },
|
||||||
|
{ title: "Service Engineer", href: "/dashboard/overview/serviceEngineer", icon: Target },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Operations",
|
||||||
|
icon: Settings,
|
||||||
|
children: [
|
||||||
|
{ title: "Help Desk", href: "/dashboard/operations/helpDesk", icon: CheckSquare, badge: 6, badgeColor: "bg-amber-500 text-black" },
|
||||||
|
{ title: "Equipment", href: "/dashboard/operations/equipment", icon: Target },
|
||||||
|
{ title: "Requests", href: "/dashboard/operations/request", icon: FileText, badge: 15, badgeColor: "bg-amber-400 text-black" },
|
||||||
|
{ title: "Inventory", href: "/dashboard/operations/inventory", icon: Box },
|
||||||
|
{ title: "Energy", href: "/dashboard/operations/energy", icon: Zap },
|
||||||
|
{ title: "Work Permit", href: "/dashboard/operations/workPermit", icon: ClipboardList, badge: 3, badgeColor: "bg-amber-500 text-black" },
|
||||||
|
{ title: "Vendor & Field Service", href: "/dashboard/operations/vendorFieldService", icon: Star, badge: 12, badgeColor: "bg-sky-400 text-black" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Workplace",
|
||||||
|
icon: Monitor,
|
||||||
|
children: [
|
||||||
|
{ title: "Visitor Management", href: "/dashboard/workplace/visitorManagement", icon: UserCheck },
|
||||||
|
{ title: "Meeting Rooms", href: "/dashboard/workplace/meetingRoom", icon: Calendar },
|
||||||
|
{ title: "Workspace", href: "/dashboard/workplace/workspace", icon: Layers },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Finance",
|
||||||
|
icon: Wallet,
|
||||||
|
children: [
|
||||||
|
{ title: "O&M Budget", href: "/dashboard/finance/budget", icon: Coins },
|
||||||
|
{ title: "Costing & Invoicing", href: "/dashboard/finance/costinvoice", icon: Receipt },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Compliance & Safety",
|
||||||
|
icon: ShieldCheck,
|
||||||
|
children: [
|
||||||
|
{ title: "Statutory Compliance", href: "/dashboard/compliance-safety/statutoryCompliance", icon: ShieldCheck },
|
||||||
|
{ title: "Contracts & SLA", href: "/dashboard/compliance-safety/contracts", icon: FileText },
|
||||||
|
{ title: "Fire & Safety", href: "/dashboard/compliance-safety/fireAndSafety", icon: Flame },
|
||||||
|
{ title: "Waste & ESG", href: "/dashboard/compliance-safety/wasteAndEsg", icon: Recycle },
|
||||||
|
{ title: "Training", href: "/dashboard/compliance-safety/training", icon: GraduationCap },
|
||||||
|
{ title: "Audit & Survey", href: "/dashboard/compliance-safety/auditAndSurvey", icon: GraduationCap },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Intelligence",
|
||||||
|
icon: Brain,
|
||||||
|
children: [{ title: "AI & Predictive", href: "/dashboard/intelligence/aiPredictive", icon: Brain },
|
||||||
|
{ title: "Asset Health", href: "/dashboard/intelligence/assetHealth", icon: ShieldCheck },
|
||||||
|
{ title: "Energy Benchmarking", href: "/dashboard/intelligence/energyBenchmarking", icon: Activity },
|
||||||
|
{ title: "AI Helpdesk", href: "/dashboard/intelligence/aiHelpdesk", icon: Bot },
|
||||||
|
{ title: "Connected Ops", href: "/dashboard/intelligence/connectedOps", icon: Gauge },
|
||||||
|
{ title: "Connected Assets", href: "/dashboard/intelligence/connectedAsset", icon: Snowflake },
|
||||||
|
{ title: "Sustainability", href: "/dashboard/intelligence/sustainability", icon: Leaf },
|
||||||
|
{ title: "GPS Tracking", href: "/dashboard/intelligence/gpstracking", icon: MapPin },],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "IoT Application",
|
||||||
|
icon: Radar,
|
||||||
|
children: [{ title: "Command Center", href: "/dashboard/iot-app/commandCenter", icon: Gauge },
|
||||||
|
{ title: "HVAC Plant", href: "/dashboard/iot-app/hvacPlant", icon: Snowflake },
|
||||||
|
{ title: "Energy & Utilities", href: "/dashboard/iot-app/energyUtility", icon: Zap },
|
||||||
|
{ title: "Device Fleet", href: "/dashboard/iot-app/deviceFleet", icon: LayoutGrid },
|
||||||
|
{ title: "Alarms & Rules", href: "/dashboard/iot-app/alarmRule", icon: Shield, badge: 7, badgeColor: "bg-rose-500 text-white" },],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Insight",
|
||||||
|
icon: BarChart3,
|
||||||
|
children: [{ title: "Reports & MMR", href: "/dashboard/insight/report", icon: BarChart3 },],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Configure",
|
||||||
|
icon: Cog,
|
||||||
|
children: [{ title: "Master Data", href: "/dashboard/configure/masterdata", icon: Layers },
|
||||||
|
{ title: "Roles & Access", href: "/dashboard/configure/rolesAndAccess", icon: Shield },
|
||||||
|
{ title: "Workflow Automation", href: "/dashboard/configure/workflowautomation", icon: Bot },
|
||||||
|
{ title: "User Location", href: "/dashboard/configure/userLocation", icon: MapPin },
|
||||||
|
{ title: "Settings", href: "/dashboard/configure/settings", icon: Sun },],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export const ADMIN_SIDEBAR_ITEMS = [
|
||||||
|
{
|
||||||
|
title: "Platform",
|
||||||
|
icon: Building2,
|
||||||
|
children: [
|
||||||
|
{ title: "Overview", href: "/dashboard/admin/overview", icon: LayoutGrid },
|
||||||
|
{ title: "Tenants", href: "/dashboard/admin/tenants", icon: Building2 },
|
||||||
|
{ title: "Users", href: "/dashboard/admin/users", icon: Users },
|
||||||
|
{ title: "Sites", href: "/dashboard/admin/site", icon: MapPin },
|
||||||
|
{ title: "Security", href: "/dashboard/admin/security", icon: Shield },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Configuration",
|
||||||
|
icon: LayoutGrid,
|
||||||
|
children: [
|
||||||
|
{ title: "Modules", href: "/dashboard/admin/modules", icon: LayoutGrid },
|
||||||
|
{ title: "Language", href: "/dashboard/admin/language", icon: Globe },
|
||||||
|
{ title: "Dynamic Dashboard", href: "/dashboard/admin/dynamicDashboard", icon: LayoutDashboard },
|
||||||
|
{ title: "Mobile Flows", href: "/dashboard/admin/mobileFlow", icon: Smartphone },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user