Operations dashboard screens are added

This commit is contained in:
2026-07-20 18:06:04 +05:30
parent a0426e8c8a
commit 0c9151b3a0
33 changed files with 826 additions and 47 deletions

226
utils/table.tsx Normal file
View File

@@ -0,0 +1,226 @@
import React, { useState } from 'react';
import {
Pencil,
Menu,
ShieldCheck,
QrCode,
Power,
Check,
Sparkles,
} from 'lucide-react';
// Data model interface
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';
}
// Sample data extracted from your screenshot
const mockData: TableRowData[] = [
{ id: '1', block: 'Block 1', floor: 'G', zone: 'Z2', department: 'Electrical', location: 'Main lobby', window: '06:0017:30', tat: '60m', sched: 8, approval: true, status: 'INACTIVE' },
{ id: '2', block: 'Block 2', floor: '3', zone: 'Z2', department: 'Electrical', location: 'Main lobby', window: '08:0023:59', tat: '30m', sched: 4, approval: false, status: 'ACTIVE' },
{ id: '3', block: 'Block 2', floor: '3', zone: 'Z1', department: 'Inspection work', location: 'Cafeteria', window: '06:0017:30', tat: '20m', sched: 8, approval: true, status: 'ACTIVE' },
{ id: '4', block: 'Block 1', floor: 'G', zone: 'Z1', department: 'HVAC', location: 'Server room', window: '08:0018:00', tat: '30m', sched: 4, approval: false, status: 'INACTIVE' },
{ id: '5', block: 'Block 2', floor: '3', zone: 'N', department: 'Inspection work', location: 'Server room', window: '08:0018:00', tat: '60m', sched: 8, approval: true, status: 'ACTIVE' },
{ id: '6', block: 'Block 2', floor: 'G', zone: 'Z1', department: 'Electrical', location: 'Reception', window: '06:0018:00', tat: '60m', sched: 6, approval: false, status: 'ACTIVE' },
{ id: '7', block: 'Block 1', floor: 'G', zone: 'Z2', department: 'Electrical', location: 'Food court', window: '06:0017:30', tat: '60m', sched: 8, approval: true, status: 'ACTIVE' },
{ id: '8', block: 'Block 2', floor: '3', zone: 'Z2', department: 'Electrical', location: 'Cafeteria', window: '08:0023: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:0017:30', tat: '20m', sched: 8, approval: true, status: 'INACTIVE' },
{ id: '10', block: 'Block 1', floor: 'G', zone: 'Z1', department: 'HVAC', location: 'Lobby', window: '08:0018:00', tat: '30m', sched: 4, approval: false, status: 'ACTIVE' },
];
export default function LocationTable(){
const [selectedIds, setSelectedIds] = useState<string[]>(['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 (
<div className="w-full bg-[#071321] text-slate-300 rounded-xl overflow-hidden border border-slate-800/80 shadow-2xl relative font-sans">
<div className="overflow-x-auto">
<table className="w-full text-left text-xs border-collapse">
{/* TABLE HEADER */}
<thead>
<tr className="border-b border-slate-800/90 text-[11px] font-bold tracking-wider text-slate-500 uppercase font-mono">
<th className="py-4 px-4 w-12 text-center">
<input
type="checkbox"
checked={selectedIds.length === mockData.length}
onChange={toggleSelectAll}
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"
/>
</th>
<th className="py-4 px-3 font-mono">BLOCK</th>
<th className="py-4 px-3 font-mono">FLOOR</th>
<th className="py-4 px-3 font-mono">ZONE</th>
<th className="py-4 px-3 font-mono">DEPARTMENT</th>
<th className="py-4 px-3 font-mono">LOCATION</th>
<th className="py-4 px-3 font-mono">WINDOW</th>
<th className="py-4 px-3 font-mono">TAT</th>
<th className="py-4 px-3 font-mono">SCHED.</th>
<th className="py-4 px-3 font-mono">APPROVAL</th>
<th className="py-4 px-3 font-mono">STATUS</th>
<th className="py-4 px-4 font-mono text-right pr-6">ACTIONS</th>
</tr>
</thead>
{/* TABLE BODY */}
<tbody className="divide-y divide-slate-800/50">
{mockData.map((row) => {
const isSelected = selectedIds.includes(row.id);
return (
<tr
key={row.id}
className={`group relative transition-colors ${
isSelected
? 'bg-[#0e2238]/60 hover:bg-[#122942]/80'
: 'hover:bg-slate-800/30'
}`}
>
{/* Left Selection Indicator Bar (for Row 1 / Selected Rows) */}
<td className="py-3 px-4 text-center relative">
{isSelected && (
<span className="absolute left-0 top-0 bottom-0 w-[3px] bg-teal-400 rounded-r" />
)}
<input
type="checkbox"
checked={isSelected}
onChange={() => 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"
/>
</td>
{/* Block */}
<td className="py-3 px-3 font-semibold text-slate-100 whitespace-nowrap">
{row.block}
</td>
{/* Floor */}
<td className="py-3 px-3 font-medium text-slate-200">
{row.floor}
</td>
{/* Zone */}
<td className="py-3 px-3 font-medium text-slate-300">
{row.zone}
</td>
{/* Department */}
<td className="py-3 px-3 font-semibold text-slate-200 whitespace-nowrap">
{row.department}
</td>
{/* Location */}
<td className="py-3 px-3 font-extrabold text-white whitespace-nowrap">
{row.location}
</td>
{/* Window */}
<td className="py-3 px-3 font-mono text-slate-400 text-[11px] whitespace-nowrap">
{row.window}
</td>
{/* TAT */}
<td className="py-3 px-3 font-mono text-slate-200 font-medium">
{row.tat}
</td>
{/* Sched */}
<td className="py-3 px-3 font-mono text-slate-200 font-medium">
{row.sched}
</td>
{/* Approval */}
<td className="py-3 px-3 whitespace-nowrap">
{row.approval ? (
<span className="inline-flex items-center gap-1.5 text-emerald-400 font-semibold">
<Check size={14} className="stroke-[3]" />
<span>Yes</span>
</span>
) : (
<span className="text-slate-500 font-mono"></span>
)}
</td>
{/* Status Badge */}
<td className="py-3 px-3 whitespace-nowrap">
{row.status === 'ACTIVE' ? (
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[10px] font-bold font-mono tracking-wider bg-emerald-950/80 border border-emerald-800/40 text-emerald-400">
<span className="h-1.5 w-1.5 rounded-full bg-emerald-400"></span>
ACTIVE
</span>
) : (
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[10px] font-bold font-mono tracking-wider bg-slate-800/80 border border-slate-700/50 text-slate-400">
<span className="h-1.5 w-1.5 rounded-full bg-slate-400"></span>
INACTIVE
</span>
)}
</td>
{/* Action Icon Buttons */}
<td className="py-3 px-4 text-right whitespace-nowrap pr-6">
<div className="inline-flex items-center gap-1.5">
<button
title="Edit"
className="p-1.5 rounded-md bg-[#0b1b2d] hover:bg-slate-700/60 border border-slate-800 text-slate-400 hover:text-slate-200 transition-colors"
>
<Pencil size={13} />
</button>
<button
title="Options"
className="p-1.5 rounded-md bg-[#0b1b2d] hover:bg-slate-700/60 border border-slate-800 text-slate-400 hover:text-slate-200 transition-colors"
>
<Menu size={13} />
</button>
<button
title="Security"
className="p-1.5 rounded-md bg-[#0b1b2d] hover:bg-slate-700/60 border border-slate-800 text-slate-400 hover:text-slate-200 transition-colors"
>
<ShieldCheck size={13} />
</button>
<button
title="QR Code"
className="p-1.5 rounded-md bg-[#0b1b2d] hover:bg-slate-700/60 border border-slate-800 text-slate-400 hover:text-slate-200 transition-colors"
>
<QrCode size={13} />
</button>
<button
title="Toggle Power"
className="p-1.5 rounded-md bg-[#0b1b2d] hover:bg-slate-700/60 border border-slate-800 text-slate-400 hover:text-slate-200 transition-colors"
>
<Power size={13} />
</button>
</div>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
}