"use client"; import { useMemo, useState, useEffect } from "react"; import Link from "next/link"; import { useSearchParams, useRouter } from "next/navigation"; import { CATEGORIES, PARTS } from "@/data/gunbuilderParts"; import type { CategoryId, Part } from "@/types/gunbuilder"; type BuildState = Partial>; // categoryId -> partId const STORAGE_KEY = "gunbuilder-build-state"; // Encode build state to URL-friendly string function encodeBuildState(build: BuildState): string { const entries = Object.entries(build) .filter(([_, partId]) => partId) .map(([categoryId, partId]) => `${categoryId}:${partId}`) .join(","); return btoa(entries); } // Decode URL string to build state function decodeBuildState(encoded: string): BuildState { try { const decoded = atob(encoded); const build: BuildState = {}; decoded.split(",").forEach((entry) => { const [categoryId, partId] = entry.split(":"); if (categoryId && partId) { build[categoryId as CategoryId] = partId; } }); return build; } catch { return {}; } } export default function BuildDetailsPage() { const searchParams = useSearchParams(); const router = useRouter(); const [build, setBuild] = useState({}); const [shareUrl, setShareUrl] = useState(""); const [copied, setCopied] = useState(false); // Load build from URL params or localStorage useEffect(() => { const buildParam = searchParams.get("build"); if (buildParam) { const decoded = decodeBuildState(buildParam); setBuild(decoded); // Also save to localStorage localStorage.setItem(STORAGE_KEY, JSON.stringify(decoded)); } else if (typeof window !== "undefined") { // Load from localStorage const stored = localStorage.getItem(STORAGE_KEY); if (stored) { try { const parsed = JSON.parse(stored); setBuild(parsed); } catch { // Invalid stored data } } } }, [searchParams]); // Generate shareable URL useEffect(() => { if (typeof window !== "undefined" && Object.keys(build).length > 0) { const encoded = encodeBuildState(build); const url = `${window.location.origin}/gunbuilder/build?build=${encoded}`; setShareUrl(url); } }, [build]); 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 handleCopyLink = async () => { if (shareUrl) { try { await navigator.clipboard.writeText(shareUrl); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch (err) { console.error("Failed to copy:", err); } } }; const handleShare = async () => { if (navigator.share && shareUrl) { try { await navigator.share({ title: "My AR-15 Build", text: `Check out my AR-15 build: $${totalPrice.toFixed(2)}`, url: shareUrl, }); } catch (err) { // User cancelled or share failed, fall back to copy handleCopyLink(); } } else { handleCopyLink(); } }; if (selectedParts.length === 0) { return (

No Build Selected

You need to select at least one part to view your build.

Go to Gunbuilder
); } return (
{/* Header */}
← Back to Gunbuilder

Shadow Standard

Build Summary

Review your build, purchase parts from our affiliate partners, or share your build with others.

Total Build Price
${totalPrice.toFixed(2)}
{selectedParts.length} / {CATEGORIES.length} parts selected
{/* Share Section */}

Share Your Build

Share this link to let others view your build or bookmark it to come back later.

{shareUrl && (

Shareable URL:

{shareUrl}

)}
{/* Build Parts */}

Selected Parts

{CATEGORIES.map((category) => { const selectedPartId = build[category.id]; const part = PARTS.find( (p) => p.id === selectedPartId && p.categoryId === category.id, ); return (
{category.name}
{part ? ( <>
{part.brand}{" "} {part.name}
{part.notes && (

{part.notes}

)} ) : (
Not selected
)}
{part && (
${part.price.toFixed(2)}
)}
); })}
{/* Actions */}
Edit Build
); }