1
0
Fork 0
polaris-task-force/src/components/frontend/locker/LockerGridToolbar.tsx

131 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { Button } from "@/components/ui/button";
import {
LayoutGridIcon,
ListIcon,
RotateCwIcon,
ScissorsIcon,
ShuffleIcon,
SlidersHorizontalIcon,
TrashIcon,
} from "lucide-react";
import {
findLockerEmptySpot,
getAssetTypeLabel,
getLockerGridOccupancy,
getLockerItemFootprint,
type LockerGridItem,
lockerIsRotatable,
lockerIsStackable,
} from "@/lib/locker";
interface LockerGridToolbarProps {
gridWidth: number;
gridHeight: number;
items: LockerGridItem[];
selectedItem: LockerGridItem | null;
viewMode: "grid" | "list";
onViewModeChange: (mode: "grid" | "list") => void;
onAutoArrange: () => Promise<void>;
onRotate: (entryId: string) => Promise<void>;
onRemove: (entryId: string) => Promise<void>;
onSplit: (entryId: string, amount: number) => Promise<void>;
onCustomize: () => void;
}
export function LockerGridToolbar({
gridWidth,
gridHeight,
items,
selectedItem,
viewMode,
onViewModeChange,
onAutoArrange,
onRotate,
onRemove,
onSplit,
onCustomize,
}: LockerGridToolbarProps) {
const occupancy = getLockerGridOccupancy(items, gridWidth, gridHeight);
const asset = selectedItem?.asset ?? null;
const fp = selectedItem && asset ? getLockerItemFootprint(asset, selectedItem.rotated) : null;
const displayName = selectedItem?.equipment?.customName?.trim() || asset?.name || null;
const hasCustomName =
selectedItem?.equipment?.customName?.trim() != null &&
selectedItem.equipment.customName.trim() !== "";
const canSplit =
selectedItem && asset && fp
? findLockerEmptySpot(items, fp.width, fp.height, gridWidth, gridHeight) !== null
: false;
return (
<div className="flex flex-col gap-3">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Button variant="outline" size="sm" onClick={onAutoArrange}>
<ShuffleIcon className="size-3.5 mr-1" />
Auto-Arrange
</Button>
</div>
<div className="flex items-center gap-1">
<Button
variant={viewMode === "grid" ? "default" : "outline"}
size="sm"
onClick={() => onViewModeChange("grid")}
>
<LayoutGridIcon className="size-3.5" />
</Button>
<Button
variant={viewMode === "list" ? "default" : "outline"}
size="sm"
onClick={() => onViewModeChange("list")}
>
<ListIcon className="size-3.5" />
</Button>
</div>
</div>
{selectedItem && asset && (
<div className="flex items-center gap-3 p-2 rounded-md border bg-muted/30 text-xs">
<div className="flex-1 min-w-0">
<div className="font-medium truncate">{displayName}</div>
<div className="text-muted-foreground">
{selectedItem.quantity.toLocaleString()}× · {getAssetTypeLabel(asset.assetType)}
{hasCustomName && asset && displayName !== asset.name && ` · as "${asset.name}"`}
{fp && ` · ${fp.width}x${fp.height}`}
{selectedItem.rotated && " · rotated"}
</div>
</div>
<div className="flex items-center gap-1">
{asset?.assetType === "weapon" && (
<Button variant="outline" size="sm" onClick={onCustomize}>
<SlidersHorizontalIcon className="size-3.5" />
Customize
</Button>
)}
{lockerIsRotatable(asset) && (
<Button variant="outline" size="sm" onClick={() => onRotate(selectedItem.id)}>
<RotateCwIcon className="size-3.5" />
</Button>
)}
{lockerIsStackable(asset) && selectedItem.quantity > 1 && (
<Button
variant="outline"
size="sm"
disabled={!canSplit}
onClick={() => onSplit(selectedItem.id, Math.floor(selectedItem.quantity / 2))}
>
<ScissorsIcon className="size-3.5" />
</Button>
)}
<Button variant="outline" size="sm" onClick={() => onRemove(selectedItem.id)}>
<TrashIcon className="size-3.5" />
</Button>
</div>
</div>
)}
</div>
);
}