import { useState, useEffect } from "react"; import { X } from "lucide-react"; import { get, post, del } from "../../api/client"; import type { Item, Project, Revision } from "../../api/types"; interface MainTabProps { item: Item; onReload: () => void; isEditor: boolean; } function formatDate(s: string) { if (!s) return "—"; return new Date(s).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", }); } function formatFileSize(bytes: number) { if (bytes < 1024) return `${bytes} B`; if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`; if (bytes < 1073741824) return `${(bytes / 1048576).toFixed(1)} MB`; return `${(bytes / 1073741824).toFixed(1)} GB`; } export function MainTab({ item, onReload, isEditor }: MainTabProps) { const [itemProjects, setItemProjects] = useState([]); const [allProjects, setAllProjects] = useState([]); const [latestRev, setLatestRev] = useState(null); const [addProject, setAddProject] = useState(""); useEffect(() => { get( `/api/items/${encodeURIComponent(item.part_number)}/projects`, ) .then(setItemProjects) .catch(() => setItemProjects([])); get("/api/projects") .then(setAllProjects) .catch(() => {}); get( `/api/items/${encodeURIComponent(item.part_number)}/revisions`, ) .then((revs) => { if (revs.length > 0) setLatestRev(revs[revs.length - 1]!); }) .catch(() => {}); }, [item.part_number]); const handleAddProject = async () => { if (!addProject) return; try { await post( `/api/items/${encodeURIComponent(item.part_number)}/projects`, { projects: [addProject] }, ); const proj = allProjects.find((p) => p.code === addProject); if (proj) setItemProjects((prev) => [...prev, proj]); setAddProject(""); onReload(); } catch (e) { alert(e instanceof Error ? e.message : "Failed to add project"); } }; const handleRemoveProject = async (code: string) => { try { await del( `/api/items/${encodeURIComponent(item.part_number)}/projects/${encodeURIComponent(code)}`, ); setItemProjects((prev) => prev.filter((p) => p.code !== code)); onReload(); } catch (e) { alert(e instanceof Error ? e.message : "Failed to remove project"); } }; const row = (label: string, value: React.ReactNode) => (
{label} {value}
); return (
{row( "Part Number", {item.part_number} , )} {row("Description", item.description)} {row("Type", item.item_type)} {row("Sourcing", item.sourcing_type || "—")} {item.properties?.sourcing_link != null && row( "Source Link", {String(item.properties.sourcing_link)} , )} {item.properties?.standard_cost != null && row("Std Cost", `$${Number(item.properties.standard_cost).toFixed(2)}`)} {row("Revision", `Rev ${item.current_revision}`)} {row("Created", formatDate(item.created_at))} {row("Updated", formatDate(item.updated_at))} {item.long_description && (
Long Description
{item.long_description}
)} {/* Project Tags */}
Projects
{itemProjects.map((proj) => ( {proj.code} {isEditor && ( )} ))} {isEditor && ( <> {addProject && ( )} )}
{/* File Info */} {latestRev?.file_key && (
File Attachment (Rev {latestRev.revision_number})
{latestRev.file_size != null && ( {formatFileSize(latestRev.file_size)} )} {latestRev.file_checksum && ( SHA256: {latestRev.file_checksum.substring(0, 12)}... )}
)}
); }