"use client"; import React, { useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Checkbox } from "@/components/ui/checkbox"; import { formatCurrency } from "@/lib/currency"; import { cn } from "@/lib/utils"; import { X, Plus } from "lucide-react"; /** Minimal part shape for the overlay; compatible with builder Component type */ export interface PartSelectorPart { id: string; name: string; price: number; image?: string | null; category: string; retailer?: { name: string; address?: string | null } | null; brand?: string; /** Optional specs for display (e.g. Socket, Total Cores, Boost Clock) */ specifications?: Record; } export interface PartSelectorOverlayProps { /** Whether the overlay is visible */ open: boolean; /** Called when the overlay should close (e.g. close button, escape) */ onClose: () => void; /** Title shown in the overlay header (e.g. "Processors - Quick Add") */ title: string; /** List of parts to display in the grid */ parts: PartSelectorPart[]; /** Number of parts currently in the build (for Part List display) */ selectedPartCount: number; /** Total build price to show in the sidebar */ totalBuildPrice: number; /** Whether the compatibility filter is enabled */ compatibilityChecked: boolean; /** Called when the compatibility toggle changes */ onCompatibilityChange: (checked: boolean) => void; /** Called when user clicks "Add to build" on a part */ onAddToBuild: (part: PartSelectorPart) => void; /** Optional class for the overlay container */ className?: string; } /** * Fullscreen overlay part selector (PCPartPicker-style). * - Fullscreen (w-screen h-screen), disables background scroll * - Left sidebar: Part List, total price, Compatibility toggle * - Right: responsive product grid (1–4 columns) with independent scroll * - Responsive: sidebar stacks on mobile */ export function PartSelectorOverlay({ open, onClose, title, parts, selectedPartCount, totalBuildPrice, compatibilityChecked, onCompatibilityChange, onAddToBuild, className, }: PartSelectorOverlayProps) { // Disable background scrolling when overlay is open useEffect(() => { if (!open) return; const prev = document.body.style.overflow; document.body.style.overflow = "hidden"; return () => { document.body.style.overflow = prev; }; }, [open]); // Escape to close useEffect(() => { if (!open) return; const handleKeyDown = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, [open, onClose]); if (!open) return null; return (
{/* Header: title + close */}

{title}

{/* Split view: sidebar + main */}
{/* Left sidebar — fixed width on desktop, full width on mobile */} {/* Right main: product grid with independent scroll */}
{parts.length === 0 ? (

No parts in this category.

) : (
{parts.map((part) => { const specEntries = part.specifications ? Object.entries(part.specifications).filter(([_, v]) => v != null && v !== "").slice(0, 4) : []; return (
{part.name}

{part.name}

{formatCurrency(part.price)}

{specEntries.length > 0 && (
    {specEntries.map(([key, value]) => (
  • {key}: {String(value)}
  • ))}
)}

Category: {part.category}

{part.retailer?.name && (

Retailer: {part.retailer.name}

)}
); })}
)}
); }