fixing platform routing. not done. updated logo on builder

This commit is contained in:
2025-12-10 14:32:09 -05:00
parent 54c30b1d8a
commit b26dcb947e
8 changed files with 255 additions and 265 deletions
+54 -9
View File
@@ -2,7 +2,7 @@
import { useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { useParams, useRouter } from "next/navigation";
import { useParams, useRouter, useSearchParams } from "next/navigation";
import { CATEGORIES } from "@/data/gunbuilderParts";
import type { CategoryId, Part } from "@/types/gunbuilder";
@@ -26,6 +26,8 @@ type UiPart = Part & {
inStock?: boolean;
};
const PLATFORMS = ["AR-15", "AR-10"];
const API_BASE_URL =
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
@@ -37,10 +39,18 @@ type SortOption = "relevance" | "price-asc" | "price-desc" | "brand-asc";
type BuildState = Partial<Record<CategoryId, string>>;
const STORAGE_KEY = "gunbuilder-build-state";
// support for url id-slug
const slugify = (str: string) =>
str
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/(^-|-$)/g, "");
export default function CategoryPage() {
const params = useParams();
const categoryId = params.categoryId as CategoryId;
const router = useRouter();
const searchParams = useSearchParams();
const [viewMode, setViewMode] = useState<ViewMode>("list");
const [parts, setParts] = useState<UiPart[]>([]);
@@ -70,6 +80,10 @@ export default function CategoryPage() {
}
});
const initialPlatform =
(searchParams.get("platform") as string) || "AR-15";
const [platform, setPlatform] = useState<string>(initialPlatform);
const category = useMemo(
() => CATEGORIES.find((c) => c.id === categoryId),
[categoryId],
@@ -86,10 +100,9 @@ export default function CategoryPage() {
setError(null);
const search = new URLSearchParams();
search.set("platform", "AR-15");
search.set("categorySlug", categoryId);
search.set("platform", platform);
const url = `${API_BASE_URL}/api/gunbuilder/products/by-category?${search.toString()}`;
const url = `${API_BASE_URL}/api/products?${search.toString()}`;
const res = await fetch(url, { signal: controller.signal });
@@ -123,7 +136,7 @@ export default function CategoryPage() {
fetchCategoryParts();
return () => controller.abort();
}, [categoryId]);
}, [categoryId, platform]);
// persist build to localStorage whenever it changes
useEffect(() => {
@@ -275,10 +288,16 @@ export default function CategoryPage() {
return filteredParts.slice(startIndex, startIndex + PAGE_SIZE);
}, [filteredParts, currentPage, PAGE_SIZE]);
useEffect(() => {
useEffect(() => {
// whenever the category or filters change, jump back to page 1
setCurrentPage(1);
}, [categoryId, brandFilter, sortBy, searchQuery, priceRange, inStockOnly]);
}, [categoryId, brandFilter, sortBy, searchQuery, priceRange, inStockOnly, platform]);
useEffect(() => {
const nextPlatform =
(searchParams.get("platform") as string) || "AR-15";
setPlatform(nextPlatform);
}, [searchParams]);
const visibleRange = useMemo(() => {
if (filteredParts.length === 0) {
@@ -588,6 +607,26 @@ export default function CategoryPage() {
)}
</div>
</div>
<div className="flex items-center gap-2">
<label
htmlFor="platform-select"
className="text-xs text-zinc-500"
>
Platform
</label>
<select
id="platform-select"
value={platform}
onChange={(e) => setPlatform(e.target.value)}
className="rounded-md border border-zinc-700 bg-zinc-900/70 px-2 py-1 text-xs text-zinc-200 focus:outline-none focus:ring-1 focus:ring-amber-400"
>
{PLATFORMS.map((p) => (
<option key={p} value={p}>
{p}
</option>
))}
</select>
</div>
<div className="flex items-center gap-2">
<label
htmlFor="sort-by"
@@ -660,7 +699,10 @@ export default function CategoryPage() {
</div>
<div className="mt-2 flex gap-2">
<Link
href={`/builder/${categoryId}/${part.id}`}
href={{
pathname: `/builder/${categoryId}/${part.id}-${slugify(part.name)}`,
query: { platform },
}}
className="flex-1 rounded-md border border-zinc-700 bg-zinc-800/50 px-3 py-2 text-center text-xs font-medium text-zinc-300 transition-colors hover:border-zinc-600 hover:bg-zinc-700"
>
View Details
@@ -723,7 +765,10 @@ export default function CategoryPage() {
</div>
<div className="flex justify-end gap-2">
<Link
href={`/builder/${categoryId}/${part.id}`}
href={{
pathname: `/builder/${categoryId}/${part.id}-${slugify(part.name)}`,
query: { platform },
}}
className="whitespace-nowrap rounded-md border border-zinc-700 bg-zinc-800/50 px-3 py-1.5 text-xs font-medium text-zinc-300 transition-colors hover:border-zinc-600 hover:bg-zinc-700"
>
View Details