"use client"; import { useState, useCallback } from "react"; import { useRouter } from "next/navigation"; import { GameStructure, Structure, Resource } from "@/payload-types"; import { InventoryGrid } from "./InventoryGrid"; import { GridToolbar } from "./GridToolbar"; import { ResourceList } from "./ResourceList"; import { type GridItem } from "@/lib/logistics"; import { pluralize } from "@/lib/utils"; import { Item, ItemContent, ItemDescription, ItemHeader, ItemSeparator, ItemMedia, ItemTitle, } from "@/components/ui/item"; import { PackageOpenIcon, AlertTriangleIcon, DropletIcon, ZapIcon, BrainIcon, } from "lucide-react"; import { moveGridItem, mergeGridStacks, rotateGridItem, removeGridItem, splitGridStack, autoArrangeGrid, removeResource, retrieveFromVoid, } from "@/app/(frontend)/logistics/structures/actions"; function getResourceIcon(type: Resource["type"]) { switch (type) { case "fluid": return ; case "energy": return ; case "abstract": return ; default: return ; } } interface StructureStorageViewProps { structure: GameStructure & { type: Structure }; } export function StructureStorageView({ structure }: StructureStorageViewProps) { const router = useRouter(); const [viewMode, setViewMode] = useState<"grid" | "list">("grid"); const [selectedItem, setSelectedItem] = useState(null); const storedRaw = structure.storedResources ?? []; const gridWidth = structure.type.xSize ?? 0; const gridHeight = structure.type.ySize ?? 0; const hasGrid = gridWidth > 0 && gridHeight > 0; const storedResources: GridItem[] = storedRaw .filter((entry) => { const res = entry.resource as Resource; return res && typeof res === "object" && "id" in res; }) .map((entry) => ({ id: entry.id ?? `${(entry.resource as Resource).id}-${entry.gridX}-${entry.gridY}`, resourceId: (entry.resource as Resource).id, amount: entry.amount, gridX: entry.gridX ?? 0, gridY: entry.gridY ?? 0, rotated: entry.rotated ?? false, resource: entry.resource as Resource, })); const refresh = useCallback(() => { router.refresh(); }, [router]); const handleMoveItem = useCallback( async (entryId: string, gridX: number, gridY: number, rotated?: boolean) => { const result = await moveGridItem(structure.id, entryId, gridX, gridY, rotated); if (result.success) refresh(); }, [structure.id, refresh], ); const handleMergeStacks = useCallback( async (sourceId: string, targetId: string) => { const result = await mergeGridStacks(structure.id, sourceId, targetId); if (result.success) refresh(); }, [structure.id, refresh], ); const handleRotateItem = useCallback( async (entryId: string) => { const result = await rotateGridItem(structure.id, entryId); if (result.success) refresh(); }, [structure.id, refresh], ); const handleRemoveItem = useCallback( async (entryId: string) => { const result = await removeGridItem(structure.id, entryId); if (result.success) { setSelectedItem(null); refresh(); } }, [structure.id, refresh], ); const handleSplitStack = useCallback( async (entryId: string, amount: number) => { const result = await splitGridStack(structure.id, entryId, amount); if (result.success) refresh(); }, [structure.id, refresh], ); const handleAutoArrange = useCallback(async () => { const result = await autoArrangeGrid(structure.id); if (result.success) refresh(); }, [structure.id, refresh]); const handleWithdrawFromVoid = useCallback( async (resourceId: number, amount: number) => { const result = await removeResource(structure.id, resourceId, amount); if (result.success) refresh(); }, [structure.id, refresh], ); const handleRetrieveFromVoid = useCallback(async () => { const result = await retrieveFromVoid(structure.id); if (result.success) refresh(); }, [structure.id, refresh]); if (!hasGrid) { return ( ); } const voidStorageRaw = (structure as any).voidStorage ?? []; const voidStorageItems = voidStorageRaw .filter((entry: any) => { const res = entry.resource as Resource; return res && typeof res === "object" && "id" in res; }) .map((entry: any) => ({ id: entry.id ?? `${(entry.resource as Resource).id}-void`, resourceId: (entry.resource as Resource).id, amount: entry.amount, gridX: entry.gridX ?? 0, gridY: entry.gridY ?? 0, rotated: entry.rotated ?? false, resource: entry.resource as Resource, })); const hasVoidStorage = voidStorageItems.length > 0; return (
{viewMode === "grid" ? ( ) : ( )} {hasVoidStorage && ( Void Storage {voidStorageItems.length} item{voidStorageItems.length !== 1 ? "s" : ""} — these no longer fit in the grid.
{voidStorageItems.map((entry: any, index: number) => { const resource = entry.resource as Resource; if (!resource || typeof resource === "number") return null; const mass = (resource.massPerUnit ?? 0) * entry.amount; return (
{resource.icon ? ( {resource.name} ) : ( getResourceIcon(resource.type) )} {resource.name}
{entry.amount.toLocaleString()} {pluralize(entry.amount, resource.unitOfMeasure)}
{mass > 0 && `${mass.toLocaleString()} kg`}
{index < voidStorageItems.length - 1 && }
); })}
)}
); }