part cards

This commit is contained in:
2025-11-25 16:42:37 -05:00
parent 1c07310c44
commit 1db854a01f
32 changed files with 298 additions and 40 deletions
+48 -2
View File
@@ -1,14 +1,60 @@
"use client";
import { useMemo, useState } from "react";
import { useMemo, useState, useEffect } from "react";
import { useSearchParams, useRouter } from "next/navigation";
import { CATEGORIES, PARTS } from "@/data/gunbuilderParts";
import type { CategoryId, Part } from "@/types/gunbuilder";
import { CategoryColumn } from "@/components/CategoryColumn";
type BuildState = Partial<Record<CategoryId, string>>; // categoryId -> partId
const STORAGE_KEY = "gunbuilder-build-state";
export default function GunbuilderPage() {
const [build, setBuild] = useState<BuildState>({});
const searchParams = useSearchParams();
const router = useRouter();
const [build, setBuild] = useState<BuildState>(() => {
// Initialize from localStorage if available
if (typeof window !== "undefined") {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored) {
try {
return JSON.parse(stored);
} catch {
return {};
}
}
}
return {};
});
// Handle URL query parameter for part selection
useEffect(() => {
const selectParam = searchParams.get("select");
if (selectParam) {
const [categoryId, partId] = selectParam.split(":");
if (categoryId && partId && CATEGORIES.some((c) => c.id === categoryId)) {
setBuild((prev) => {
const updated = {
...prev,
[categoryId]: partId,
};
// Persist to localStorage
localStorage.setItem(STORAGE_KEY, JSON.stringify(updated));
return updated;
});
// Remove query param from URL
router.replace("/gunbuilder", { scroll: false });
}
}
}, [searchParams, router]);
// Persist build state to localStorage whenever it changes
useEffect(() => {
if (typeof window !== "undefined") {
localStorage.setItem(STORAGE_KEY, JSON.stringify(build));
}
}, [build]);
const partsByCategory: Record<CategoryId, Part[]> = useMemo(() => {
const grouped = {} as Record<CategoryId, Part[]>;