-
-
- Apple One — HQ Tower
- •
- Operations
- •
- Equipment
-
-
- Equipment & maintenance
-
-
- Asset register, preventive (PPM) and contract (AMC) maintenance, scoped to the active tenant.
-
-
+
+
+
+
+
+
+
+ {/* TABLE HEADER */}
+
+
+
+
+
+
+
+
+
+
+
+ BLOCK
+
+ FLOOR
+
+ ZONE
+
+ DEPARTMENT
+
+ LOCATION
+
+ WINDOW
+
+ TAT
+
+ SCHED.
+
+ APPROVAL
+
+ STATUS
+
+ ACTIONS
+
+
+
+
+
+
+
+ {/* TABLE BODY */}
+
+
+
+ {mockData.map((row) => {
+
+ const isSelected = selectedIds.includes(row.id);
+
+
+
+ return (
+
+
+
+ {/* Left Selection Indicator Bar (for Row 1 / Selected Rows) */}
+
+
+
+ {isSelected && (
+
+
+
+ )}
+
+ toggleSelectRow(row.id)}
+
+ className="rounded border-slate-700 bg-slate-900/80 text-teal-400 focus:ring-0 focus:ring-offset-0 cursor-pointer accent-teal-400 h-3.5 w-3.5"
+
+ />
+
+
+
+
+
+ {/* Block */}
+
+
+
+ {row.block}
+
+
+
+
+
+ {/* Floor */}
+
+
+
+ {row.floor}
+
+
+
+
+
+ {/* Zone */}
+
+
+
+ {row.zone}
+
+
+
+
+
+ {/* Department */}
+
+
+
+ {row.department}
+
+
+
+
+
+ {/* Location */}
+
+
+
+ {row.location}
+
+
+
+
+
+ {/* Window */}
+
+
+
+ {row.window}
+
+
+
+
+
+ {/* TAT */}
+
+
+
+ {row.tat}
+
+
+
+
+
+ {/* Sched */}
+
+
+
+ {row.sched}
+
+
+
+
+
+ {/* Approval */}
+
+
+
+ {row.approval ? (
+
+
+
+
+
+ Yes
+
+
+
+ ) : (
+
+ ——
+
+ )}
+
+
+
+
+
+ {/* Status Badge */}
+
+
+
+ {row.status === 'ACTIVE' ? (
+
+
+
+
+
+ ACTIVE
+
+
+
+ ) : (
+
+
+
+
+
+ INACTIVE
+
+
+
+ )}
+
+
+
+
+
+ {/* Action Icon Buttons */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+
+ })}
+
+
+
+
+
-
- {/* Navigation Tabs */}
-
- {/* --- STAT CARDS --- */}
-
- {/* Total Equipment */}
-
-
- {/* Critical Assets */}
-
- {/* PPM Attention */}
-
-
- {/* On Plan */}
-
-
- {/* --- ROW 2: SEARCH, FILTERS & ACTION BUTTONS --- */}
-
- {/* Search & Select Filters */}
-
- {/* Search Bar */}
-
-
-
-
+
- {/* Groups Dropdown */}
-
- All groups
- HVAC
-
- Electrical
- Plumbing
- Fire
-
-
-
- {/* Action Buttons */}
-
-
-
- All QR
-
-
-
-
- Download
-
-
-
-
- Bulk upload
-
-
-
-
- Add equipment
-
-
-
-
-
+
);
-}
\ No newline at end of file
+
+}
\ No newline at end of file
diff --git a/components/dashboard/helpDesk.tsx b/components/dashboard/helpDesk.tsx
index 823c403..e4ebb9e 100644
--- a/components/dashboard/helpDesk.tsx
+++ b/components/dashboard/helpDesk.tsx
@@ -12,7 +12,7 @@ import {
} from 'lucide-react';
import Button from "@/utils/button";
import StatCard from "@/utils/dashStatCard";
-import LocationTable from '../../utils/table';
+import LocationTable from '@/utils/dataTable';
import NavigationTabs from '@/utils/tabs';
import { helpdeskTtabs } from '@/constants/constant';
diff --git a/components/dashboard/inventory.tsx b/components/dashboard/inventory.tsx
index e69de29..bb72548 100644
--- a/components/dashboard/inventory.tsx
+++ b/components/dashboard/inventory.tsx
@@ -0,0 +1,456 @@
+import {
+ Package,
+ AlertTriangle,
+ Activity,
+ FileText,
+ LayoutGrid,
+ Plus
+} from "lucide-react";
+import Button from "@/utils/button";
+import StatCard from "@/utils/dashStatCard";
+import InfoBanner from "@/utils/infoBanner";
+
+
+
+
+export default function InventoryPortal() {
+ 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,
+ },
+ ];
+
+ const consumptionLedger = [
+ {
+ 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",
+ },
+ {
+ 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",
+ },
+ ];
+
+ return (
+
+ {/* --- HEADER SECTION --- */}
+
+
+
+ Apple One — HQ Tower
+ •
+ Operations
+ •
+ Inventory
+
+
+ Inventory & stock
+
+
+ Stock master with receipt / consume transactions. Consumption posts back to the
+ originating request job card; items at or below minimum are flagged for reorder.
+
+
+
+ {/* --- HEADER BUTTONS --- */}
+
+
+
+ Bulk upload
+
+
+
+ Add item
+
+
+ Receive stock
+
+
+
+
+ {/* --- STAT CARDS --- */}
+
+ {/* Stock items */}
+
+
+ {/* Below minimum */}
+
+
+ {/* Units consumed */}
+
+
+ {/* Posted to requests */}
+
+
+
+ {/* --- TABLES GRID (SIDE-BY-SIDE) --- */}
+
+
+ {/* LEFT TABLE: STOCK MASTER */}
+
+
+
Stock master
+ 7 items
+
+
+ {/* Corrected column layout and removed horizontal scrollbar to align with the right UI. */}
+
+
+
+
+ Item
+ Group
+ Store
+ Min
+ Present
+ Status
+
+
+
+ {stockItems.map((row, index) => {
+ const isOverdue = row.status === "OVERDUE";
+ return (
+
+
+ {row.isHighlighted && (
+
+ )}
+ {row.item}
+
+
+ {row.group}
+
+
+ {row.store}
+
+
+ {row.min}
+
+
+
+ {row.presentValue}{" "}
+
+
+ {row.unit}
+
+
+
+ {row.status === "COMPLETED" ? (
+
+
+ COMPLETED
+
+ ) : (
+
+
+ OVERDUE
+
+ )}
+
+
+ );
+ })}
+
+
+
+
+
+ {/* RIGHT TABLE: CONSUMPTION LEDGER */}
+
+
+
Consumption ledger
+
+ posts back to job card
+
+
+
+
+
+
+
+ Txn
+ Item
+ Type
+ Qty
+ Job Card
+ Date
+
+
+
+ {consumptionLedger.map((row, index) => (
+
+
+ {row.txn}
+
+
+ {row.item}
+
+
+ {row.type === "Consume" ? (
+
+
+ Consume
+
+ ) : (
+
+
+ Receipt
+
+ )}
+
+
+ {row.qty}
+
+
+ {row.jobCard}
+
+
+ {row.date}
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/components/dashboard/request.tsx b/components/dashboard/request.tsx
index 284f227..26e426d 100644
--- a/components/dashboard/request.tsx
+++ b/components/dashboard/request.tsx
@@ -1,7 +1,7 @@
import { useState } from 'react';
import { Plus } from 'lucide-react';
import Button from "@/utils/button";
-import LocationTable from '@/utils/table';
+import LocationTable from '@/utils/dataTable';
import NavigationTabs from '@/utils/tabs';
import { Reqeusttabs,statusFilters } from '@/constants/constant';
import FilterTabs from '@/utils/roundedFilters';
diff --git a/components/dashboard/vendorService.tsx b/components/dashboard/vendorService.tsx
new file mode 100644
index 0000000..3fe9087
--- /dev/null
+++ b/components/dashboard/vendorService.tsx
@@ -0,0 +1,331 @@
+import { useState } from 'react';
+import {
+ Star,
+ ShieldCheck,
+ Activity,
+ Clock,
+ BarChart2,
+ Plus
+} from "lucide-react";
+import Button from "@/utils/button";
+import StatCard from "@/utils/dashStatCard";
+import InfoBanner from "@/utils/infoBanner";
+
+export default function VendorServicePortal() {
+ const vendorData = [
+ {
+ name: "Voltas Ltd",
+ id: "CTR-700",
+ scope: "HVAC AMC & breakdown",
+ rating: "4.6",
+ sla: "95%",
+ slaColor: "text-emerald-400",
+ response: "4.0h",
+ openJobs: "2",
+ },
+ {
+ name: "Blue Star",
+ id: "CTR-701",
+ scope: "Chiller & VRV service",
+ rating: "4.1",
+ sla: "88%",
+ slaColor: "text-amber-400",
+ response: "1.2h",
+ openJobs: "2",
+ },
+ {
+ name: "Sterling FM",
+ id: "CTR-702",
+ scope: "Integrated FM / soft services",
+ rating: "3.4",
+ sla: "94%",
+ slaColor: "text-emerald-400",
+ response: "2.4h",
+ openJobs: "4",
+ },
+ {
+ name: "OTIS Elevators",
+ id: "CTR-704",
+ scope: "Elevator AMC",
+ rating: "4.8",
+ sla: "95%",
+ slaColor: "text-emerald-400",
+ response: "2.8h",
+ openJobs: "—",
+ },
+ {
+ name: "Sodexo",
+ 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",
+ },
+ ];
+
+ 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",
+ },
+ ];
+
+ return (
+
+ {/* --- HEADER SECTION --- */}
+
+
+
+ Apple One — HQ Tower
+ •
+ Operations
+ •
+ Vendors
+
+
+ Vendor & field service
+
+
+ Vendor performance scorecards and live field-crew status in one view — SLA adherence, response times and job dispatch across your service partners.
+
+
+
+ {/* --- HEADER BUTTONS --- */}
+
+
+
+ SLA report
+
+
+
+
+ Dispatch job
+
+
+
+
+ {/* --- STAT CARDS --- */}
+
+ {/* Active vendors */}
+
+
+ {/* Avg SLA adherence */}
+
+
+ {/* Open field jobs */}
+
+
+ {/* Avg response time */}
+
+
+
+ {/* --- TABLES GRID (SIDE-BY-SIDE) --- */}
+
+
+ {/* LEFT TABLE: VENDOR SCORECARD */}
+
+
+
Vendor scorecard
+
+ SLA • rating • jobs
+
+
+
+
+
+
+
+ Vendor
+ Scope
+ Rating
+ SLA
+ Response
+ Open
+
+
+
+ {vendorData.map((row, index) => (
+
+
+ {row.name}
+ {row.id}
+
+
+ {row.scope}
+
+
+
+ {row.rating}
+
+
+
+
+ {row.sla}
+
+
+ {row.response}
+
+
+ {row.openJobs}
+
+
+ ))}
+
+
+
+
+
+ {/* RIGHT TABLE: FIELD CREW • LIVE */}
+
+
+
Field crew • live
+
+ 4 on site
+
+
+
+
+ {fieldCrewData.map((crew, index) => {
+ return (
+
+
+
+ {crew.initials}
+
+
+
{crew.name}
+
{crew.role}
+
+
+
+
+ {crew.statusType === "onsite" && (
+
+
+ {crew.status}
+
+ )}
+ {crew.statusType === "enroute" && (
+
+
+ {crew.status}
+
+ )}
+ {crew.statusType === "offsite" && (
+
+
+ {crew.status}
+
+ )}
+
+ {crew.time}
+
+
+
+ );
+ })}
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/components/dashboard/workpermit.tsx b/components/dashboard/workpermit.tsx
new file mode 100644
index 0000000..f402ea8
--- /dev/null
+++ b/components/dashboard/workpermit.tsx
@@ -0,0 +1,352 @@
+import { useState } from 'react';
+import { Plus, ShieldCheck, Clock, Check, AlertTriangle, QrCode, FileText, Eye } from 'lucide-react';
+import Button from "@/utils/button";
+import { workPermitFilters } from '@/constants/constant';
+import FilterTabs from '@/utils/roundedFilters';
+import StatCard from '@/utils/dashStatCard';
+import InfoBanner from '@/utils/infoBanner';
+
+export default function WorkPermitPortal() {
+ const [activeTab, setActiveTab] = useState
('TFM Requests');
+ const [activeFilter, setActiveFilter] = useState('All');
+
+ // Permit Data matching the UI
+ const permitsData = [
+ {
+ permit: "PTW-2663",
+ workingType: "Work at Height",
+ location: "Atrium void",
+ contractor: "Blue Star",
+ validityDate: "Jun 26, 2026",
+ validityTime: "08:30–17:00",
+ crew: 2,
+ status: "ACTIVE",
+ actionText: "Close out",
+ isHighlighted: false,
+ },
+ {
+ permit: "PTW-2664",
+ workingType: "Electrical Isolation",
+ location: "STP wet well",
+ contractor: "Sterling FM",
+ validityDate: "Jun 26, 2026",
+ validityTime: "09:00–13:00",
+ crew: 3,
+ status: "SUBMITTED",
+ actionText: "Approve",
+ isHighlighted: true, // Row with highlight bar
+ },
+ {
+ permit: "PTW-2665",
+ workingType: "Confined Space",
+ location: "DG yard",
+ contractor: "In-house team",
+ validityDate: "Jun 26, 2026",
+ validityTime: "14:00–18:00",
+ crew: 4,
+ status: "APPROVED",
+ actionText: "Activate",
+ isHighlighted: false,
+ },
+ {
+ permit: "PTW-2666",
+ workingType: "Hot Work",
+ location: "Roof terrace",
+ contractor: "Voltas Ltd",
+ validityDate: "Jun 25, 2026",
+ validityTime: "08:00–12:00",
+ crew: 5,
+ status: "EXPIRED",
+ hasViewIconOnly: true,
+ isHighlighted: false,
+ },
+ {
+ permit: "PTW-2667",
+ workingType: "Work at Height",
+ location: "LT panel room",
+ contractor: "Blue Star",
+ validityDate: "Jun 25, 2026",
+ validityTime: "10:00–16:00",
+ crew: 2,
+ status: "CLOSED",
+ hasViewIconOnly: true,
+ isHighlighted: false,
+ },
+ {
+ permit: "PTW-2668",
+ workingType: "Electrical Isolation",
+ location: "Chiller plant",
+ contractor: "Sterling FM",
+ validityDate: "Jun 26, 2026",
+ validityTime: "11:00–15:00",
+ crew: 3,
+ status: "REJECTED",
+ hasViewIconOnly: true,
+ isHighlighted: false,
+ },
+ {
+ permit: "PTW-2726",
+ workingType: "Work at Height",
+ location: "Atrium void",
+ contractor: "Blue Star",
+ validityDate: "Jun 26, 2026",
+ validityTime: "08:30–17:00",
+ crew: 2,
+ status: "DRAFT",
+ actionText: "Submit",
+ isHighlighted: false,
+ },
+ ];
+
+ const renderStatusBadge = (status: string) => {
+ switch (status) {
+ case "ACTIVE":
+ return (
+
+
+ ACTIVE
+
+ );
+ case "SUBMITTED":
+ return (
+
+
+ SUBMITTED
+
+ );
+ case "APPROVED":
+ return (
+
+
+ APPROVED
+
+ );
+ case "EXPIRED":
+ return (
+
+
+ EXPIRED
+
+ );
+ case "CLOSED":
+ return (
+
+
+ CLOSED
+
+ );
+ case "REJECTED":
+ return (
+
+
+ REJECTED
+
+ );
+ case "DRAFT":
+ return (
+
+
+ DRAFT
+
+ );
+ default:
+ return null;
+ }
+ };
+
+ return (
+
+ {/* --- HEADER SECTION --- */}
+
+
+
+ Apple One — HQ Tower
+ •
+ Operations
+ •
+ Work Permit
+
+
+ Permit to Work
+
+
+ A controlled permit-to-work lifecycle — request, risk review, approval, activation and close-out — per site and hazard type. QR-driven on the floor.
+
+
+
+ {/* Action Buttons */}
+
+
+
+ Scan QR
+
+
+
+
+ New permit
+
+
+
+
+ {/* --- NAVIGATION TABS & TOP ACTION BUTTONS --- */}
+
+ {/* Navigation tabs component if needed */}
+
+
+ {/* --- STAT CARDS --- */}
+
+ {/* Active on site */}
+
+
+ {/* Awaiting approval */}
+
+
+ {/* Approved · ready */}
+
+
+ {/* Expired · breach */}
+
+
+
+ {/* --- STATUS PILL FILTERS --- */}
+
+
+
+
+ {/* --- PERMIT TABLE SECTION --- */}
+
+
+
+
+ Permit
+ Working Type
+ Location
+ Contractor
+ Validity
+ Crew
+ Status
+
+
+
+
+ {permitsData.map((row, index) => (
+
+ {/* Permit ID */}
+
+ {row.isHighlighted && (
+
+ )}
+ {row.permit}
+
+
+ {/* Working Type */}
+
+ {row.workingType}
+
+
+ {/* Location */}
+
+ {row.location}
+
+
+ {/* Contractor */}
+
+ {row.contractor}
+
+
+ {/* Validity */}
+
+ {row.validityDate}
+ {row.validityTime}
+
+
+ {/* Crew */}
+
+ {row.crew}
+
+
+ {/* Status Badge */}
+
+ {renderStatusBadge(row.status)}
+
+
+ {/* Actions */}
+
+
+ {row.hasViewIconOnly ? (
+
+
+
+
+
+
+
+
+ ) : (
+
+
+
+
+
+ {row.actionText}
+
+
+ )}
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/constants/constant.ts b/constants/constant.ts
index ea88dc8..1effc72 100644
--- a/constants/constant.ts
+++ b/constants/constant.ts
@@ -216,6 +216,16 @@ export const Reqeusttabs: string[] = [
];
+ export const workPermitFilters = [
+ { label: 'All', count: 10 },
+ { label: 'Awaiting', count: 3 },
+ { label: 'Approved', count: 1},
+ { label: 'Active', count: 2 },
+ { label: 'Closed', count: 1 },
+ { label: 'Expired', count: 1 },
+ { label: 'Rejected', count: 1 },
+ ];
+
// Data model interface
@@ -232,4 +242,5 @@ export const Reqeusttabs: string[] = [
{ id: '8', block: 'Block 2', floor: '3', zone: 'Z2', department: 'Electrical', location: 'Cafeteria', window: '08:00–23:59', tat: '30m', sched: 4, approval: false, status: 'ACTIVE' },
{ id: '9', block: 'Block 2', floor: '3', zone: 'Z1', department: 'Inspection work', location: 'Gym', window: '06:00–17:30', tat: '20m', sched: 8, approval: true, status: 'INACTIVE' },
{ id: '10', block: 'Block 1', floor: 'G', zone: 'Z1', department: 'HVAC', location: 'Lobby', window: '08:00–18:00', tat: '30m', sched: 4, approval: false, status: 'ACTIVE' },
- ];
\ No newline at end of file
+ ];
+
\ No newline at end of file
diff --git a/constants/types.ts b/constants/types.ts
index 1c6d66f..aaed3bb 100644
--- a/constants/types.ts
+++ b/constants/types.ts
@@ -101,4 +101,17 @@ export interface FilterTabsProps {
export interface InfoBannerProps {
boldText?: string;
normalText?: string;
-}
\ No newline at end of file
+}
+export interface TableRowData {
+ id: string;
+ block: string;
+ floor: string;
+ zone: string;
+ department: string;
+ location: string;
+ window: string;
+ tat: string;
+ sched: number;
+ approval: boolean;
+ status: 'ACTIVE' | 'INACTIVE';
+}
diff --git a/utils/table.tsx b/utils/dataTable.tsx
similarity index 97%
rename from utils/table.tsx
rename to utils/dataTable.tsx
index 748462f..36b2d52 100644
--- a/utils/table.tsx
+++ b/utils/dataTable.tsx
@@ -1,199 +1,397 @@
import { useState } from 'react';
+
import {
+
Pencil,
+
Menu,
+
ShieldCheck,
+
QrCode,
+
Power,
+
Check,
+
Sparkles,
+
} from 'lucide-react';
+
import { mockData } from '@/constants/constant';
+
+
+
export default function LocationTable(){
+
const [selectedIds, setSelectedIds] = useState(['1']); // Row 1 selected by default (teal indicator bar)
+
+
const toggleSelectAll = () => {
+
if (selectedIds.length === mockData.length) {
+
setSelectedIds([]);
+
} else {
+
setSelectedIds(mockData.map((row) => row.id));
+
}
+
};
+
+
const toggleSelectRow = (id: string) => {
+
setSelectedIds((prev) =>
+
prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]
+
);
+
};
+
+
return (
+
+
+
+
{/* TABLE HEADER */}
+
+
+
+
+
+
BLOCK
+
FLOOR
+
ZONE
+
DEPARTMENT
+
LOCATION
+
WINDOW
+
TAT
+
SCHED.
+
APPROVAL
+
STATUS
+
ACTIONS
+
+
+
+
{/* TABLE BODY */}
+
+
{mockData.map((row) => {
+
const isSelected = selectedIds.includes(row.id);
+
+
return (
+
+
{/* Left Selection Indicator Bar (for Row 1 / Selected Rows) */}
+
+
{isSelected && (
+
+
)}
+
toggleSelectRow(row.id)}
+
className="rounded border-slate-700 bg-slate-900/80 text-teal-400 focus:ring-0 focus:ring-offset-0 cursor-pointer accent-teal-400 h-3.5 w-3.5"
+
/>
+
+
+
{/* Block */}
+
+
{row.block}
+
+
+
{/* Floor */}
+
+
{row.floor}
+
+
+
{/* Zone */}
+
+
{row.zone}
+
+
+
{/* Department */}
+
+
{row.department}
+
+
+
{/* Location */}
+
+
{row.location}
+
+
+
{/* Window */}
+
+
{row.window}
+
+
+
{/* TAT */}
+
+
{row.tat}
+
+
+
{/* Sched */}
+
+
{row.sched}
+
+
+
{/* Approval */}
+
+
{row.approval ? (
+
+
+
Yes
+
+
) : (
+
——
+
)}
+
+
+
{/* Status Badge */}
+
+
{row.status === 'ACTIVE' ? (
+
+
+
ACTIVE
+
+
) : (
+
+
+
INACTIVE
+
+
)}
+
+
+
{/* Action Icon Buttons */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
+
})}
+
+
+
+
+
+
+
);
-}
\ No newline at end of file
+
+}
\ No newline at end of file