// accessories.jsx - Refurb Ping recommended accessories // Reuses Logo / ProductIcon from art.jsx (loaded first). const { useState, useEffect, useRef } = React; // Placeholder thumbnail icons // Monoline fallback icons for items without photos. const stroke = { fill: "none", stroke: "var(--ink-3)", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" }; const IconDock = () => ( ); const IconHubStand = () => ( ); const IconAdapter = () => ( ); const IconKeyboard = () => ( ); const IconTrackpad = () => ( ); const ICONS = { dock: IconDock, hub: IconHubStand, adapter: IconAdapter, keyboard: IconKeyboard, trackpad: IconTrackpad, }; // Data is injected by the server-rendered accessories.html template. const ACCESSORIES_DATA = window.REFURBPING_ACCESSORIES || { items: {}, products: [] }; const ITEMS = ACCESSORIES_DATA.items || {}; const PRODUCTS = ACCESSORIES_DATA.products || []; const DEVICE_NAME = { "mac-mini": "Mac mini", "mac-studio": "Mac Studio" }; const FILTERS = [ { id: "all", label: "All accessories" }, { id: "mac-mini", label: "Mac mini" }, { id: "mac-studio", label: "Mac Studio" }, ]; const FEATURED_ORDER = [ "anker-7in1-usb-adapter", "nuphy-air75-v3-keyboard", "apple-magic-trackpad", "mac-mini-satechi-m4-dock", "satechi-hub-stand-ssd-enclosure", ]; function buildAccessoryRows() { const fitByKey = {}; PRODUCTS.forEach((product) => { (product.keys || []).forEach((key) => { if (!fitByKey[key]) fitByKey[key] = []; if (!fitByKey[key].includes(product.id)) fitByKey[key].push(product.id); }); }); return Object.keys(fitByKey) .filter((key) => ITEMS[key]) .map((key) => ({ key, item: ITEMS[key], fit: fitByKey[key] })) .sort((a, b) => { const aIndex = FEATURED_ORDER.includes(a.key) ? FEATURED_ORDER.indexOf(a.key) : FEATURED_ORDER.length; const bIndex = FEATURED_ORDER.includes(b.key) ? FEATURED_ORDER.indexOf(b.key) : FEATURED_ORDER.length; return aIndex - bIndex || a.item.title.localeCompare(b.item.title); }); } const LIST = buildAccessoryRows(); // Components function Nav() { return (
); } function AccHero() { return (
After the ping - gear we'd actually buy

Now make it yours.

You scored the refurb - here's the short list of accessories worth adding. Most work with both machines; the tag on each tells you what it fits. Every pick links straight to the buy page.

); } function FitTag({ fit }) { const both = fit.length > 1; return ( {fit.map((kind) => )} {both ? "Works with both" : `${DEVICE_NAME[fit[0]] || fit[0]} only`} ); } function AccessoryCard({ item, fit }) { const Icon = ICONS[item.icon]; return (
{item.image ? ( ) : ( )}
{item.title}
{item.reason}
View on Amazon
); } function AccessoryList() { const [filter, setFilter] = useState("all"); const rows = filter === "all" ? LIST : LIST.filter((row) => row.fit.includes(filter)); return (
{FILTERS.map((option) => ( ))} {rows.length} {rows.length === 1 ? "pick" : "picks"}
{rows.map((row) => ( ))}
); } function Footer() { return ( ); } function App() { return (