"use client"; import { useEffect, useState } from "react"; import { ConstructionEta } from "@/components/frontend/baseManagement/ConstructionEta"; interface ConstructionMaterial { name: string; required: number; delivered: number; } interface ConstructionPanelProps { status: "awaiting_materials" | "building" | "complete" | null; startedAt: string | null; completesAt: string | null; durationMinutes: number | null; materials: ConstructionMaterial[]; crew?: { required: number; effective: number } | null; } const STATUS_LABELS: Record = { awaiting_materials: { label: "Awaiting Materials", className: "border-amber-500/40 bg-amber-500/10 text-amber-300", }, building: { label: "Building", className: "border-blue-500/40 bg-blue-500/10 text-blue-300", }, complete: { label: "Operational", className: "border-emerald-500/40 bg-emerald-500/10 text-emerald-300", }, }; function progressPct(startedAt: string | null, completesAt: string | null, nowMs: number): number { if (!startedAt || !completesAt) return 0; const start = new Date(startedAt).getTime(); const end = new Date(completesAt).getTime(); if (!Number.isFinite(start) || !Number.isFinite(end) || end <= start) return 0; const ratio = (nowMs - start) / (end - start); if (!Number.isFinite(ratio)) return 0; return Math.min(100, Math.max(0, Math.round(ratio * 100))); } export function ConstructionPanel({ status, startedAt, completesAt, durationMinutes, materials, crew, }: ConstructionPanelProps) { const [nowMs, setNowMs] = useState(() => Date.now()); useEffect(() => { const timer = setInterval(() => setNowMs(Date.now()), 1000); return () => clearInterval(timer); }, []); if (!status || status === "complete") return null; const statusInfo = STATUS_LABELS[status] ?? STATUS_LABELS.awaiting_materials; const allDelivered = materials.every((material) => material.delivered >= material.required); const pct = status === "building" ? progressPct(startedAt, completesAt, nowMs) : 0; const crewRequired = crew?.required ?? 0; const crewEffective = crew?.effective ?? 0; const crewFactor = crewRequired > 0 ? Math.min(1, crewEffective / crewRequired) : 1; const crewLine = crewRequired > 0 ? crewEffective <= 0 ? { text: status === "building" ? "No crew assigned: construction is crawling at minimum speed." : "No crew assigned: construction cannot start once materials arrive.", className: "text-amber-300", } : crewFactor < 1 ? { text: `Crew ${crewEffective.toLocaleString()} / ${crewRequired.toLocaleString()}: understaffed, building at ${Math.round(crewFactor * 100)}% speed.`, className: "text-amber-300", } : { text: `Crew ${crewEffective.toLocaleString()} / ${crewRequired.toLocaleString()}: full build speed.`, className: "text-emerald-400", } : null; return (

Construction

{statusInfo.label}
{status === "building" && (
Build time {durationMinutes != null ? `${durationMinutes.toLocaleString()} min` : ""} {pct}%
)} {status === "awaiting_materials" && (

Ship the required materials to this site. Construction starts automatically once everything has arrived.

)} {crewLine &&

{crewLine.text}

}
{materials.map((material) => { const met = material.delivered >= material.required; return (
{material.name} {material.delivered.toLocaleString()} / {material.required.toLocaleString()}
); })} {materials.length === 0 && (

No materials required by this blueprint.

)}
{status === "awaiting_materials" && !allDelivered && (

{materials.filter((material) => material.delivered < material.required).length} material type(s) still missing.

)}
); }