"use client"; import { useEffect, useState, useCallback } from "react"; import { toast } from "sonner"; import { fetchFireStatus, type FireZoneStatus } from "@/lib/api"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Skeleton } from "@/components/ui/skeleton"; import { Flame, RefreshCw, CheckCircle2, AlertTriangle, Zap, Wind, Activity } from "lucide-react"; import { cn } from "@/lib/utils"; const SITE_ID = "sg-01"; const LEVEL_CONFIG: Record = { normal: { label: "Normal", bg: "bg-green-500/10", border: "border-green-500/20", text: "text-green-400", icon: CheckCircle2, pulsing: false, }, alert: { label: "Alert", bg: "bg-amber-500/10", border: "border-amber-500/40", text: "text-amber-400", icon: AlertTriangle, pulsing: false, }, action: { label: "Action", bg: "bg-orange-500/10", border: "border-orange-500/40", text: "text-orange-400", icon: AlertTriangle, pulsing: true, }, fire: { label: "FIRE", bg: "bg-destructive/10", border: "border-destructive/60", text: "text-destructive", icon: Flame, pulsing: true, }, }; function ObscurationBar({ value }: { value: number | null }) { if (value == null) return null; const pct = Math.min(100, value * 20); // 0–5 %/m mapped to 0–100% const color = value > 3 ? "#ef4444" : value > 1.5 ? "#f59e0b" : "#94a3b8"; return (
Obscuration {value.toFixed(2)} %/m
); } function StatusIndicator({ label, ok, icon: Icon }: { label: string; ok: boolean; icon: React.ElementType; }) { return (

{label}

{ok ? "OK" : "Fault"}

); } function VesdaCard({ zone }: { zone: FireZoneStatus }) { const level = zone.level; const cfg = LEVEL_CONFIG[level] ?? LEVEL_CONFIG.normal; const Icon = cfg.icon; const isAlarm = level !== "normal"; return (
{zone.zone_id.toUpperCase()} {cfg.label}
{level === "fire" && (
FIRE ALARM — Initiate evacuation and contact emergency services immediately
)} {level === "action" && (
Action threshold reached — investigate smoke source immediately
)} {level === "alert" && (
Alert level — elevated smoke particles detected, monitor closely
)} {/* Detector status */}
{[ { label: "Detector 1", ok: zone.detector_1_ok }, { label: "Detector 2", ok: zone.detector_2_ok }, ].map(({ label, ok }) => (
{ok ? : } {label} {ok ? "Online" : "Fault"}
))}
{/* System status */}
); } export default function FireSafetyPage() { const [zones, setZones] = useState([]); const [loading, setLoading] = useState(true); const load = useCallback(async () => { try { setZones(await fetchFireStatus(SITE_ID)); } catch { toast.error("Failed to load fire safety data"); } finally { setLoading(false); } }, []); useEffect(() => { load(); const id = setInterval(load, 10_000); return () => clearInterval(id); }, [load]); const fireZones = zones.filter((z) => z.level === "fire"); const actionZones = zones.filter((z) => z.level === "action"); const alertZones = zones.filter((z) => z.level === "alert"); const normalZones = zones.filter((z) => z.level === "normal"); const anyAlarm = fireZones.length + actionZones.length + alertZones.length > 0; const worstLevel = fireZones.length > 0 ? "fire" : actionZones.length > 0 ? "action" : alertZones.length > 0 ? "alert" : "normal"; const worstCfg = LEVEL_CONFIG[worstLevel]; const WIcon = worstCfg.icon; return (
{/* Header */}

Fire & Life Safety

Singapore DC01 — VESDA aspirating detector network · refreshes every 10s

{!loading && ( {anyAlarm ? `${fireZones.length + actionZones.length + alertZones.length} zone${fireZones.length + actionZones.length + alertZones.length > 1 ? "s" : ""} in alarm` : `All ${zones.length} zones normal`} )}
{/* System summary bar */} {!loading && (
VESDA zones monitored: {zones.length}
{[ { label: "Fire", count: fireZones.length, cls: "text-destructive" }, { label: "Action", count: actionZones.length, cls: "text-orange-400" }, { label: "Alert", count: alertZones.length, cls: "text-amber-400" }, { label: "Normal", count: normalZones.length, cls: "text-green-400" }, ].map(({ label, count, cls }) => (
{label}: {count}
))}
All detectors use VESDA aspirating smoke detection technology
)} {/* Fire alarm banner */} {!loading && fireZones.length > 0 && (

FIRE ALARM ACTIVE — {fireZones.length} zone{fireZones.length > 1 ? "s" : ""}

Initiate building evacuation. Contact SCDF (995). Do not re-enter until cleared by fire services.

)} {/* Zone cards — alarms first */} {loading ? (
{Array.from({ length: 4 }).map((_, i) => )}
) : zones.length === 0 ? (
No VESDA zone data available
) : (
{[...fireZones, ...actionZones, ...alertZones, ...normalZones].map((zone) => ( ))}
)} {/* Legend */}

VESDA Alert Levels

{Object.entries(LEVEL_CONFIG).map(([key, cfg]) => { const Icon = cfg.icon; return (
{cfg.label}

{key === "normal" ? "No smoke detected, system clear" : key === "alert" ? "Trace smoke particles, monitor" : key === "action" ? "Significant smoke, investigate now" : "Confirmed fire, evacuate immediately"}

); })}
); }