import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { useState } from "react";
import { CategoryHeader } from "../../components/CategoryHeader";
import { ItemCard } from "../../components/ItemCard";
import { ItemPicker } from "../../components/ItemPicker";
import { WeightSummaryCard } from "../../components/WeightSummaryCard";
import {
useDeleteSetup,
useRemoveSetupItem,
useSetup,
useUpdateItemClassification,
} from "../../hooks/useSetups";
import { useCurrency } from "../../hooks/useCurrency";
import { useWeightUnit } from "../../hooks/useWeightUnit";
import { formatPrice, formatWeight } from "../../lib/formatters";
import { LucideIcon } from "../../lib/iconData";
export const Route = createFileRoute("/setups/$setupId")({
component: SetupDetailPage,
});
function SetupDetailPage() {
const { setupId } = Route.useParams();
const unit = useWeightUnit();
const currency = useCurrency();
const navigate = useNavigate();
const numericId = Number(setupId);
const { data: setup, isLoading } = useSetup(numericId);
const deleteSetup = useDeleteSetup();
const removeItem = useRemoveSetupItem(numericId);
const updateClassification = useUpdateItemClassification(numericId);
const [pickerOpen, setPickerOpen] = useState(false);
const [confirmDelete, setConfirmDelete] = useState(false);
if (isLoading) {
return (
{[1, 2, 3].map((i) => (
))}
);
}
if (!setup) {
return (
);
}
// Compute totals from items
const totalWeight = setup.items.reduce(
(sum, item) => sum + (item.weightGrams ?? 0),
0,
);
const totalCost = setup.items.reduce(
(sum, item) => sum + (item.priceCents ?? 0),
0,
);
const itemCount = setup.items.length;
const currentItemIds = setup.items.map((item) => item.id);
// Group items by category
const groupedItems = new Map<
number,
{
items: typeof setup.items;
categoryName: string;
categoryIcon: string;
}
>();
for (const item of setup.items) {
const group = groupedItems.get(item.categoryId);
if (group) {
group.items.push(item);
} else {
groupedItems.set(item.categoryId, {
items: [item],
categoryName: item.categoryName,
categoryIcon: item.categoryIcon,
});
}
}
function nextClassification(current: string): string {
const order = ["base", "worn", "consumable"];
const idx = order.indexOf(current);
return order[(idx + 1) % order.length];
}
function handleDelete() {
deleteSetup.mutate(numericId, {
onSuccess: () => navigate({ to: "/setups" }),
});
}
return (
{/* Setup-specific sticky bar */}
←
{setup.name}
{itemCount}{" "}
{itemCount === 1 ? "item" : "items"}
{formatWeight(totalWeight, unit)}
{" "}
total
{formatPrice(totalCost, currency)}
{" "}
cost
{/* Actions */}
{/* Empty state */}
{itemCount === 0 && (
No items in this setup
Add items from your collection to build this loadout.
)}
{/* Weight summary card + items grouped by category */}
{itemCount > 0 && (
{Array.from(groupedItems.entries()).map(
([
categoryId,
{ items: categoryItems, categoryName, categoryIcon },
]) => {
const catWeight = categoryItems.reduce(
(sum, item) => sum + (item.weightGrams ?? 0),
0,
);
const catCost = categoryItems.reduce(
(sum, item) => sum + (item.priceCents ?? 0),
0,
);
return (
{categoryItems.map((item) => (
removeItem.mutate(item.id)}
classification={item.classification}
onClassificationCycle={() =>
updateClassification.mutate({
itemId: item.id,
classification: nextClassification(
item.classification,
),
})
}
/>
))}
);
},
)}
)}
{/* Item Picker */}
setPickerOpen(false)}
/>
{/* Delete Confirmation Dialog */}
{confirmDelete && (
setConfirmDelete(false)}
/>
Delete Setup
Are you sure you want to delete{" "}
{setup.name}? This will not
remove items from your collection.
)}
);
}