"use client"; import { useMemo, useState } from "react"; import { CATEGORIES, PARTS } from "@/data/gunbuilderParts"; import type { CategoryId, Part } from "@/types/gunbuilder"; import { CategoryColumn } from "@/components/CategoryColumn"; type BuildState = Partial>; // categoryId -> partId export default function GunbuilderPage() { const [build, setBuild] = useState({}); const partsByCategory: Record = useMemo(() => { const grouped = {} as Record; for (const category of CATEGORIES) { grouped[category.id] = PARTS.filter( (p) => p.categoryId === category.id, ); } return grouped; }, []); const selectedParts: Part[] = useMemo(() => { return Object.entries(build) .map(([categoryId, partId]) => PARTS.find((p) => p.id === partId && p.categoryId === categoryId), ) .filter(Boolean) as Part[]; }, [build]); const totalPrice = useMemo( () => selectedParts.reduce((sum, p) => sum + p.price, 0), [selectedParts], ); const handleSelectPart = (categoryId: CategoryId, partId: string) => { setBuild((prev) => ({ ...prev, [categoryId]: partId, })); }; return (
{/* Header */}

Shadow Standard

Gunbuilder Prototype

Choose one part per category to assemble an AR-15 build. Prices and links are mock data for now—but the flow is close to what the real tool will be.

Current build total
${totalPrice.toFixed(2)}
{selectedParts.length} / {CATEGORIES.length} categories filled
{/* Layout */}
{/* Categories/parts */}
{CATEGORIES.map((category) => (
handleSelectPart(category.id, partId) } />
))}
{/* Build Summary */}
); }