"use client"; import { useState, useEffect, useRef } from "react"; import { useRouter } from "next/navigation"; import { setActiveBrand } from "@/actions/set-active-brand"; export type BrandSelectorItem = { id: string; name: string; slug: string; logo_url: string | null; }; type BrandSelectorProps = { brands: BrandSelectorItem[]; /** Currently-active brand id. `null` means "All brands" (platform_admin only). */ activeBrandId: string | null; /** When true, shows the "All brands" pseudo-option at the top. */ showAllBrandsOption: boolean; /** Whether the user has multi-brand access. Controls the "Multi-brand manager" badge. */ isMultiBrandAdmin: boolean; }; /** * Brand selector dropdown. * * Renders a compact pill showing the active brand (or "All brands" for * platform_admin) and opens a list of accessible brands on click. * * On select: calls `setActiveBrand` server action then `router.refresh()` * so all server components re-read the new cookie and reload their data. * The URL is NOT changed — the cookie is the source of truth. */ export default function BrandSelector({ brands, activeBrandId, showAllBrandsOption, isMultiBrandAdmin, }: BrandSelectorProps) { const router = useRouter(); const [open, setOpen] = useState(false); const [pending, setPending] = useState(false); const ref = useRef(null); // Close on outside click useEffect(() => { function handleClick(e: MouseEvent) { if (ref.current && !ref.current.contains(e.target as Node)) { setOpen(false); } } document.addEventListener("mousedown", handleClick); return () => document.removeEventListener("mousedown", handleClick); }, []); // Close on escape useEffect(() => { if (!open) return; function handleKey(e: KeyboardEvent) { if (e.key === "Escape") setOpen(false); } document.addEventListener("keydown", handleKey); return () => document.removeEventListener("keydown", handleKey); }, [open]); // No brands + no "All brands" option = don't render if (!showAllBrandsOption && brands.length === 0) return null; if (!showAllBrandsOption && brands.length < 2) return null; const activeBrand = brands.find((b) => b.id === activeBrandId); const label = showAllBrandsOption && !activeBrand ? "All brands" : activeBrand?.name ?? "Select brand"; async function selectBrand(brandId: string | null) { setOpen(false); if (brandId === activeBrandId) return; setPending(true); try { const res = await setActiveBrand(brandId); if (res.success) { router.refresh(); } else { // Keep UI usable if the server rejected; log for debugging console.error("setActiveBrand failed:", res.error); } } finally { setPending(false); } } return (
{open && (
{showAllBrandsOption && ( )} {brands.map((b) => { const isActive = b.id === activeBrandId; return ( ); })}
)}
); }