355 lines
17 KiB
TypeScript
355 lines
17 KiB
TypeScript
import React from 'react';
|
||
import { BarChart2, Zap, Snowflake, Activity, Target } from "lucide-react";
|
||
import Button from "@/components/common/button";
|
||
import { Card } from '@/components/common/cardWrapper';
|
||
|
||
import BarChart from "@/components/charts/barchart"; // Replace path with your actual BarChart component import path
|
||
|
||
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() {
|
||
return (
|
||
<div className="my-15 text-slate-100 font-sans">
|
||
|
||
{/* --- HEADER SECTION --- */}
|
||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
|
||
<div>
|
||
<div className="flex items-center gap-2 text-[11px] font-semibold tracking-widest text-[#4e6178] uppercase font-mono">
|
||
<span className="text-emerald-400 font-bold">APPLE ONE — HQ TOWER</span>
|
||
<span>•</span>
|
||
<span>IOT</span>
|
||
<span>•</span>
|
||
<span>HVAC PLANT</span>
|
||
</div>
|
||
<h1 className="text-3xl font-bold text-white tracking-tight mt-1">
|
||
Chiller plant & air side
|
||
</h1>
|
||
<p className="text-sm text-[#7f93ac] mt-2 max-w-xl leading-relaxed">
|
||
Live chiller, AHU and plant telemetry with start/stop control — commands are audit-logged.
|
||
</p>
|
||
</div>
|
||
|
||
{/* --- HEADER BUTTONS --- */}
|
||
<div className="flex items-center gap-3 self-start md:mt-2">
|
||
<Button className="bg-[#0e1c2e] hover:bg-slate-800 text-slate-200 border border-[#162942] text-xs px-4 py-2 rounded-lg flex items-center gap-2 font-semibold transition-colors">
|
||
<BarChart2 className="w-4 h-4 text-slate-400" />
|
||
<span>Plant report</span>
|
||
</Button>
|
||
|
||
<Button className="bg-[#10b981] hover:bg-emerald-400 text-slate-950 font-bold text-xs px-4 py-2 rounded-lg flex items-center gap-2 transition-colors shadow-lg">
|
||
<Activity className="w-4 h-4 text-slate-950" />
|
||
<span>Optimise staging</span>
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* --- STAT CARDS (WITH ICON BADGES) --- */}
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
|
||
|
||
{/* Card 1: Chillers running */}
|
||
<Card className="p-4 min-h-[120px]">
|
||
<div className="flex justify-between items-start">
|
||
<div className="p-2.5 rounded-lg bg-blue-950/60 border border-blue-800/40 text-blue-400">
|
||
<Snowflake className="w-5 h-5" />
|
||
</div>
|
||
<span className="text-[10px] font-bold text-[#5c738e] tracking-wider uppercase font-mono">
|
||
staged
|
||
</span>
|
||
</div>
|
||
<div className="mt-3">
|
||
<div className="text-3xl font-extrabold text-white">2 / 3</div>
|
||
<p className="text-xs text-[#5c738e] mt-1">Chillers running</p>
|
||
</div>
|
||
</Card>
|
||
|
||
{/* Card 2: Avg COP */}
|
||
<Card className="p-4 min-h-[120px]">
|
||
<div className="flex justify-between items-start">
|
||
<div className="p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800/40 text-emerald-400">
|
||
<Activity className="w-5 h-5" />
|
||
</div>
|
||
<span className="text-[10px] font-bold text-emerald-400 tracking-wider uppercase font-mono">
|
||
plant efficiency
|
||
</span>
|
||
</div>
|
||
<div className="mt-3">
|
||
<div className="text-3xl font-extrabold text-white">5.60</div>
|
||
<p className="text-xs text-[#5c738e] mt-1">Avg COP</p>
|
||
</div>
|
||
</Card>
|
||
|
||
{/* Card 3: Plant load */}
|
||
<Card className="p-4 min-h-[120px]">
|
||
<div className="flex justify-between items-start">
|
||
<div className="p-2.5 rounded-lg bg-amber-950/50 border border-amber-800/40 text-amber-400">
|
||
<Zap className="w-5 h-5" />
|
||
</div>
|
||
<span className="text-[10px] font-bold text-[#5c738e] tracking-wider uppercase font-mono">
|
||
now
|
||
</span>
|
||
</div>
|
||
<div className="mt-3">
|
||
<div className="text-3xl font-extrabold text-white">401 kW</div>
|
||
<p className="text-xs text-[#5c738e] mt-1">Plant load</p>
|
||
</div>
|
||
</Card>
|
||
|
||
{/* Card 4: AHUs running */}
|
||
<Card className="p-4 min-h-[120px]">
|
||
<div className="flex justify-between items-start">
|
||
<div className="p-2.5 rounded-lg bg-teal-950/60 border border-teal-800/40 text-teal-400">
|
||
<Target className="w-5 h-5" />
|
||
</div>
|
||
<span className="text-[10px] font-bold text-[#5c738e] tracking-wider uppercase font-mono">
|
||
air side
|
||
</span>
|
||
</div>
|
||
<div className="mt-3">
|
||
<div className="text-3xl font-extrabold text-white">3 / 4</div>
|
||
<p className="text-xs text-[#5c738e] mt-1">AHUs running</p>
|
||
</div>
|
||
</Card>
|
||
</div>
|
||
|
||
{/* --- TELEMETRY SECTION --- */}
|
||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6">
|
||
|
||
{/* Left Card: Chillers & Plant Load Chart */}
|
||
<Card className="lg:col-span-7 p-6">
|
||
<div className="mb-6">
|
||
<h2 className="text-lg font-bold text-white">Chillers</h2>
|
||
<p className="text-xs text-[#5c738e] font-mono mt-0.5">live • 5 s refresh</p>
|
||
</div>
|
||
|
||
{/* Chillers Table */}
|
||
<div className="overflow-x-auto mb-8">
|
||
<table className="w-full text-left text-xs">
|
||
<thead>
|
||
<tr className="text-[#5c738e] font-mono uppercase text-[10px] border-b border-[#162942]/60">
|
||
<th className="pb-3 font-normal">UNIT</th>
|
||
<th className="pb-3 font-normal">STATUS</th>
|
||
<th className="pb-3 font-normal">LOAD</th>
|
||
<th className="pb-3 font-normal">COP</th>
|
||
<th className="pb-3 font-normal">CHW SUPPLY / RETURN</th>
|
||
<th className="pb-3 font-normal">KW</th>
|
||
<th className="pb-3 font-normal text-right"></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody className="divide-y divide-[#162942]/40 font-mono">
|
||
{/* CH-01 */}
|
||
<tr>
|
||
<td className="py-3.5 font-bold text-teal-400">CH-01</td>
|
||
<td className="py-3.5">
|
||
<span className="px-2 py-0.5 rounded-full bg-emerald-950/80 border border-emerald-800/50 text-emerald-400 text-[10px] font-bold">
|
||
• RUNNING
|
||
</span>
|
||
</td>
|
||
<td className="py-3.5">
|
||
<div className="flex items-center gap-2">
|
||
<div className="w-16 bg-[#122339] h-2 rounded-full overflow-hidden">
|
||
<div className="bg-emerald-400 h-full rounded-full" style={{ width: '72%' }}></div>
|
||
</div>
|
||
<span className="text-slate-300">72%</span>
|
||
</div>
|
||
</td>
|
||
<td className="py-3.5 font-bold text-emerald-400">5.8</td>
|
||
<td className="py-3.5 text-slate-300">6.2 °C / 11.8 °C</td>
|
||
<td className="py-3.5 text-slate-300">212</td>
|
||
<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">
|
||
Stop
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
|
||
{/* CH-02 */}
|
||
<tr>
|
||
<td className="py-3.5 font-bold text-teal-400">CH-02</td>
|
||
<td className="py-3.5">
|
||
<span className="px-2 py-0.5 rounded-full bg-emerald-950/80 border border-emerald-800/50 text-emerald-400 text-[10px] font-bold">
|
||
• RUNNING
|
||
</span>
|
||
</td>
|
||
<td className="py-3.5">
|
||
<div className="flex items-center gap-2">
|
||
<div className="w-16 bg-[#122339] h-2 rounded-full overflow-hidden">
|
||
<div className="bg-emerald-400 h-full rounded-full" style={{ width: '64%' }}></div>
|
||
</div>
|
||
<span className="text-slate-300">64%</span>
|
||
</div>
|
||
</td>
|
||
<td className="py-3.5 font-bold text-amber-400">5.4</td>
|
||
<td className="py-3.5 text-slate-300">6.5 °C / 12.1 °C</td>
|
||
<td className="py-3.5 text-slate-300">189</td>
|
||
<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">
|
||
Stop
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
|
||
{/* CH-03 */}
|
||
<tr>
|
||
<td className="py-3.5 font-bold text-teal-400">CH-03</td>
|
||
<td className="py-3.5">
|
||
<span className="px-2 py-0.5 rounded-full bg-slate-800/60 border border-slate-700/50 text-slate-400 text-[10px] font-bold">
|
||
• STANDBY
|
||
</span>
|
||
</td>
|
||
<td className="py-3.5">
|
||
<div className="flex items-center gap-2">
|
||
<div className="w-16 bg-[#122339] h-2 rounded-full overflow-hidden">
|
||
<div className="bg-slate-700 h-full rounded-full" style={{ width: '0%' }}></div>
|
||
</div>
|
||
<span className="text-slate-400">0%</span>
|
||
</div>
|
||
</td>
|
||
<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-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">
|
||
Start
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
{/* Plant Load Reusable Bar Chart Component */}
|
||
<div>
|
||
<h3 className="text-[10px] font-bold
|
||
tracking-wider uppercase font-mono mb-4">
|
||
PLANT LOAD • TODAY
|
||
</h3>
|
||
<div className="flex-grow flex flex-col justify-end">
|
||
<BarChart data={plantLoadData} />
|
||
</div>
|
||
</div>
|
||
</Card>
|
||
|
||
{/* Right Card: Air Handling Units */}
|
||
<Card className="lg:col-span-5 p-6 flex flex-col justify-between">
|
||
<div>
|
||
<div className="mb-6">
|
||
<h2 className="text-lg font-bold text-white">Air handling units</h2>
|
||
<p className="text-xs text-[#5c738e] font-mono mt-0.5">supply air • fan speed</p>
|
||
</div>
|
||
|
||
{/* AHUs Table */}
|
||
<div className="overflow-x-auto">
|
||
<table className="w-full text-left text-xs">
|
||
<thead>
|
||
<tr className="text-[#5c738e] font-mono uppercase text-[10px] border-b border-[#162942]/60">
|
||
<th className="pb-3 font-normal">UNIT</th>
|
||
<th className="pb-3 font-normal">ZONE</th>
|
||
<th className="pb-3 font-normal">STATUS</th>
|
||
<th className="pb-3 font-normal">SAT</th>
|
||
<th className="pb-3 font-normal">FAN</th>
|
||
<th className="pb-3 font-normal">FILTER</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody className="divide-y divide-[#162942]/40 font-mono">
|
||
{/* AHU-01 */}
|
||
<tr>
|
||
<td className="py-4 font-bold text-teal-400 leading-tight">AHU-01</td>
|
||
<td className="py-4 text-slate-200 font-sans font-medium leading-tight">Lobby & atrium</td>
|
||
<td className="py-4">
|
||
<span className="px-2 py-0.5 rounded-full bg-emerald-950/80 border border-emerald-800/50 text-emerald-400 text-[10px] font-bold">
|
||
• ON
|
||
</span>
|
||
</td>
|
||
<td className="py-4 text-slate-200">14.2 °C</td>
|
||
<td className="py-4 text-slate-200">62%</td>
|
||
<td className="py-4">
|
||
<span className="px-2 py-0.5 rounded-full bg-emerald-950/80 border border-emerald-800/50 text-emerald-400 text-[10px] font-bold">
|
||
• OK
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
|
||
{/* AHU-04 */}
|
||
<tr>
|
||
<td className="py-4 font-bold text-teal-400 leading-tight">AHU-04</td>
|
||
<td className="py-4 text-slate-200 font-sans font-medium leading-tight">Floors 2–4</td>
|
||
<td className="py-4">
|
||
<span className="px-2 py-0.5 rounded-full bg-emerald-950/80 border border-emerald-800/50 text-emerald-400 text-[10px] font-bold">
|
||
• ON
|
||
</span>
|
||
</td>
|
||
<td className="py-4 text-slate-200">13.8 °C</td>
|
||
<td className="py-4 text-slate-200">71%</td>
|
||
<td className="py-4">
|
||
<span className="px-2 py-0.5 rounded-full bg-emerald-950/80 border border-emerald-800/50 text-emerald-400 text-[10px] font-bold">
|
||
• OK
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
|
||
{/* AHU-07 */}
|
||
<tr>
|
||
<td className="py-4 font-bold text-teal-400 leading-tight">AHU-07</td>
|
||
<td className="py-4 text-slate-200 font-sans font-medium leading-tight">Floors 5–7</td>
|
||
<td className="py-4">
|
||
<span className="px-2 py-0.5 rounded-full bg-emerald-950/80 border border-emerald-800/50 text-emerald-400 text-[10px] font-bold">
|
||
• ON
|
||
</span>
|
||
</td>
|
||
<td className="py-4 text-slate-200">15.1 °C</td>
|
||
<td className="py-4 text-slate-200">84%</td>
|
||
<td className="py-4">
|
||
<span className="px-2 py-0.5 rounded-full bg-amber-950/80 border border-amber-800/50 text-amber-400 text-[10px] font-bold">
|
||
• REPLACE
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
|
||
{/* AHU-09 */}
|
||
<tr>
|
||
<td className="py-4 font-bold text-teal-400 leading-tight">AHU-09</td>
|
||
<td className="py-4 text-slate-200 font-sans font-medium leading-tight">
|
||
Basement · parking
|
||
</td>
|
||
<td className="py-4">
|
||
<span className="px-2 py-0.5 rounded-full bg-slate-800/60 border border-slate-700/50 text-slate-400 text-[10px] font-bold">
|
||
• OFF
|
||
</span>
|
||
</td>
|
||
<td className="py-4 text-slate-500">—</td>
|
||
<td className="py-4 text-slate-400">0%</td>
|
||
<td className="py-4">
|
||
<span className="px-2 py-0.5 rounded-full bg-emerald-950/80 border border-emerald-800/50 text-emerald-400 text-[10px] font-bold">
|
||
• OK
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Footer Warning Notice */}
|
||
<div className="pt-6 border-t border-[#162942]/60 mt-6 text-xs text-[#7f93ac] leading-relaxed">
|
||
AHU-07 filter ΔP is beyond limit — a PPM task can be raised automatically from{' '}
|
||
<strong className="text-slate-200 hover:underline cursor-pointer">Alarms & Rules</strong>.
|
||
</div>
|
||
</Card>
|
||
|
||
</div>
|
||
</div>
|
||
);
|
||
} |