// app.jsx — RefurbPing main app
const { useState, useMemo, useEffect, useLayoutEffect, useRef } = React;
// ─── Data ─────────────────────────────────────────────────────────────────────
const PRODUCTS = {
"mac-mini": {
id: "mac-mini",
name: "Mac mini",
tagline: "Small. Mighty. And often on the refurb shelf.",
basePrice: 519,
storeName: "Apple",
art: () => ,
specs: {
cpu: ["M4", "M4 Pro"],
ram: [16, 24, 32, 48, 64],
storage: [256, 512, 1024, 2048, 4096, 8192],
},
},
"mac-studio": {
id: "mac-studio",
name: "Mac Studio",
tagline: "Outrageously powerful — when it shows up refurbished.",
basePrice: 1699,
storeName: "Apple",
art: () => ,
specs: {
cpu: ["M2 Max", "M2 Ultra", "M4 Max", "M3 Ultra"],
ram: [32, 36, 48, 64, 96, 128, 192, 256],
storage: [512, 1024, 2048, 4096, 8192, 16384],
},
},
"steam-deck": {
id: "steam-deck",
name: "Steam Deck",
tagline: "Valve certified refurbished handhelds, checked every half hour.",
basePrice: 279,
storeName: "Steam",
art: () => ,
filterLabels: { cpu: "Display", cpuAny: "any display" },
specs: {
cpu: ["LCD", "OLED"],
ram: [],
storage: [64, 256, 512, 1024],
},
},
};
const COMING_SOON = [
{ id: "macbook-pro", name: "MacBook Pro", art: () => },
{ id: "ipad-pro", name: "iPad Pro", art: () => },
{ id: "more-devices", name: "More devices", art: () => , blurb: "Sony, Microsoft, Nintendo, Framework, and more on the way." },
];
const REGIONS = [
{ id: "us", label: "United States", flag: "🇺🇸", active: true },
{ id: "ca", label: "Canada", flag: "🇨🇦", active: true },
{ id: "uk", label: "United Kingdom", flag: "🇬🇧", active: true },
{ id: "de", label: "Germany", flag: "🇩🇪", active: true },
{ id: "au", label: "Australia", flag: "🇦🇺", active: true },
{ id: "nz", label: "New Zealand", flag: "🇳🇿", active: true },
{ id: "jp", label: "Japan", flag: "🇯🇵", active: true },
{ id: "sg", label: "Singapore", flag: "🇸🇬", active: true },
{ id: "hk", label: "Hong Kong", flag: "🇭🇰", active: true },
{ id: "tw", label: "Taiwan", flag: "🇹🇼", active: true },
{ id: "kr", label: "South Korea", flag: "🇰🇷", active: true },
{ id: "fr", label: "France", flag: "🇫🇷", active: true },
{ id: "es", label: "Spain", flag: "🇪🇸", active: true },
{ id: "it", label: "Italy", flag: "🇮🇹", active: true },
{ id: "nl", label: "Netherlands", flag: "🇳🇱", active: true },
{ id: "ie", label: "Ireland", flag: "🇮🇪", active: true },
{ id: "at", label: "Austria", flag: "🇦🇹", active: true },
{ id: "ch", label: "Switzerland", flag: "🇨🇭", active: true },
{ id: "be", label: "Belgium", flag: "🇧🇪", active: true },
{ id: "pl", label: "Poland", flag: "🇵🇱", active: true },
{ id: "se", label: "Sweden", flag: "🇸🇪", active: true },
];
const APPLE_PRODUCT_IDS = new Set(["mac-mini", "mac-studio"]);
const KOFI_TIP_URL = "https://ko-fi.com/refurbping";
const regionById = (id) => REGIONS.find(r => r.id === id) || REGIONS[0];
// ─── Helpers ──────────────────────────────────────────────────────────────────
const formatStorage = (gb) => gb >= 1024 ? `${gb/1024}TB` : `${gb}GB`;
const formatRam = (gb) => `${gb}GB`;
const emptyRange = () => ({ min: null, max: null });
const rangeFromFilters = (filters, key) => ({
min: filters?.[key] ?? null,
max: filters?.[`${key}Max`] ?? null,
});
const isAnyRange = (range) => !range || (range.min == null && range.max == null);
const formatRange = (range, format) => {
if (isAnyRange(range)) return "Any";
if (range.min === range.max) return format(range.min);
if (range.min == null) return `≤ ${format(range.max)}`;
if (range.max == null) return `≥ ${format(range.min)}`;
return `${format(range.min)} – ${format(range.max)}`;
};
const withFilterRange = (filters, key, range) => ({
...filters,
[key]: range?.min ?? null,
[`${key}Max`]: range?.max ?? null,
});
const selectedCpuValues = (value) => Array.isArray(value) ? value : (value ? [value] : []);
const formatCpuFilter = (value, anyLabel) => {
const selected = selectedCpuValues(value);
return selected.length ? selected.join(" / ") : anyLabel;
};
const summarize = (productId, f) => {
const p = PRODUCTS[productId];
const parts = [{p.name} ];
if (p.specs.cpu.length) {
const selected = selectedCpuValues(f.cpu);
parts.push(, {selected.length ? {selected.join(" / ")} : (p.filterLabels?.cpuAny || "any chip")} );
}
if (p.specs.ram.length) {
const ram = rangeFromFilters(f, "ram");
parts.push(, {!isAnyRange(ram) ? {formatRange(ram, formatRam)} RAM : "any RAM"} );
}
if (p.specs.storage.length) {
const storage = rangeFromFilters(f, "storage");
parts.push(, {!isAnyRange(storage) ? {formatRange(storage, formatStorage)} storage : "any storage"} );
}
return parts;
};
const validEmail = (e) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e);
async function api(path, options = {}) {
const res = await fetch(path, {
credentials: "same-origin",
headers: { "Content-Type": "application/json", ...(options.headers || {}) },
...options,
});
const data = await res.json().catch(() => ({}));
if (!res.ok) {
throw new Error(data.error || "request_failed");
}
return data;
}
const sessionAuth = (session) => ({
signedIn: !!session.signedIn,
email: session.user?.email || null,
userId: session.user?.id || null,
});
// ─── Components ───────────────────────────────────────────────────────────────
function Nav({ alertCount, auth, authLoading, onSignIn, onSignOut }) {
const [menuOpen, setMenuOpen] = useState(false);
const ref = useRef(null);
useEffect(() => {
if (!menuOpen) return;
const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setMenuOpen(false); };
document.addEventListener("mousedown", onDoc);
return () => document.removeEventListener("mousedown", onDoc);
}, [menuOpen]);
const initial = (auth.email || "?").slice(0, 1).toUpperCase();
return (
);
}
function Hero({ watching }) {
return (
Refurbished inventory · real-time monitor
Real-time refurb Mac alerts, without delay.
Watching {watching.toLocaleString()} configurations · pushed as soon as matches appear
);
}
function RegionDropdown({ region, setRegion }) {
const [open, setOpen] = useState(false);
const ref = useRef(null);
const current = REGIONS.find(r => r.id === region) || REGIONS[0];
useEffect(() => {
if (!open) return;
const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
const onKey = (e) => { if (e.key === "Escape") setOpen(false); };
document.addEventListener("mousedown", onDoc);
document.addEventListener("keydown", onKey);
return () => {
document.removeEventListener("mousedown", onDoc);
document.removeEventListener("keydown", onKey);
};
}, [open]);
return (
setOpen(o => !o)}
>
{current.flag}
{current.label}
{open && (
{REGIONS.map(r => (
{ if (r.active) { setRegion(r.id); setOpen(false); } }}
>
{r.flag}
{r.label}
{r.active
? (region === r.id && (
))
: Soon }
))}
)}
);
}
function ProductCard({ product, onPick, selected, dim, comingSoon }) {
return (
!dim && onPick && onPick(product.id)}
role={dim ? undefined : "button"}
tabIndex={dim ? -1 : 0}
>
{comingSoon &&
Coming soon }
{product.art()}
{product.name}
{comingSoon
? (product.blurb || "We'll let you know when monitoring is on.")
: `Refurb listings start around $${product.basePrice.toLocaleString()}`}
{!comingSoon && (
Set up alert →
)}
);
}
function PillGroup({ label, hint, options, value, onChange, format, prefix }) {
return (
{label}
{hint && {hint} }
onChange(null)}
>
Any
{options.map(opt => (
onChange(opt)}
>
{prefix && {prefix} }{format ? format(opt) : opt}
))}
);
}
function MultiPillGroup({ label, hint, options, value, onChange, format }) {
const selected = selectedCpuValues(value);
const toggle = (option) => {
if (selected.includes(option)) {
onChange(selected.filter((item) => item !== option));
return;
}
onChange([...selected, option]);
};
return (
{label}
{hint && {selected.length ? `${selected.length} selected` : hint} }
onChange([])}
>
Any
{options.map(option => (
toggle(option)}
>
{format ? format(option) : option}
))}
);
}
function RangePillGroup({ label, options, value, onChange, format }) {
const range = value || emptyRange();
const minIndex = range.min == null ? -1 : options.indexOf(range.min);
const maxIndex = range.max == null ? -1 : options.indexOf(range.max);
const hasRange = minIndex !== -1 && maxIndex !== -1;
const lowIndex = Math.min(minIndex, maxIndex);
const highIndex = Math.max(minIndex, maxIndex);
const wrapRef = useRef(null);
const handleClick = (option, index) => {
if (!hasRange) {
onChange({ min: option, max: option });
return;
}
if (minIndex === maxIndex) {
if (index === minIndex) {
onChange(emptyRange());
return;
}
const low = Math.min(index, minIndex);
const high = Math.max(index, minIndex);
onChange({ min: options[low], max: options[high] });
return;
}
onChange({ min: option, max: option });
};
const inRange = (index) => hasRange && index >= lowIndex && index <= highIndex;
const pillClass = (index) => {
if (!inRange(index)) return "pill";
let className = "pill sel";
if (index === lowIndex) className += " sel-l";
if (index === highIndex) className += " sel-r";
if (index > lowIndex) className += " join";
return className;
};
useLayoutEffect(() => {
const root = wrapRef.current;
if (!root) return;
const recompute = () => {
const selected = [...root.querySelectorAll(".pill.sel")];
selected.forEach((el) => el.classList.remove("row-start", "row-end"));
for (let index = 1; index < selected.length; index++) {
if (selected[index].offsetTop !== selected[index - 1].offsetTop) {
selected[index].classList.add("row-start");
selected[index - 1].classList.add("row-end");
}
}
};
recompute();
window.addEventListener("resize", recompute);
return () => window.removeEventListener("resize", recompute);
});
return (
{label}
{isAnyRange(range) ? "Any range" : formatRange(range, format)}
onChange(emptyRange())}
>
Any
{options.map((option, index) => (
handleClick(option, index)}
>
{format ? format(option) : option}
))}
);
}
function Configurator({ productId, region, onClose, onCreate, prefilledEmail, lockEmail }) {
const product = PRODUCTS[productId];
const selectedRegion = regionById(region);
const isAppleProduct = APPLE_PRODUCT_IDS.has(productId);
const [filters, setFilters] = useState({ cpu: [], ram: null, ramMax: null, storage: null, storageMax: null });
const [email, setEmail] = useState(prefilledEmail || "");
const [touched, setTouched] = useState(false);
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState(null);
const emailOk = lockEmail ? validEmail(email) : true;
const stats = [
`From $${product.basePrice}`,
product.specs.cpu.length ? `${product.specs.cpu.length} ${product.filterLabels?.cpu || "chip"}${product.specs.cpu.length === 1 ? "" : "s"} watched` : null,
product.specs.ram.length ? `${product.specs.ram.length} RAM tiers watched` : null,
product.specs.storage.length ? `${product.specs.storage.length} storage tiers watched` : null,
].filter(Boolean);
const submit = async () => {
setTouched(true);
if (lockEmail && !emailOk) return;
setSubmitting(true);
setError(null);
try {
await onCreate({
productId,
email: lockEmail ? email : null,
filters: isAppleProduct ? { ...filters, region } : filters,
});
} catch (err) {
setError("Could not create alert. Try again.");
} finally {
setSubmitting(false);
}
return;
};
return (
← All products
{product.name}
{product.tagline}
{product.art()}
{stats.map((label, index) => (
{index > 0 && }
{label}
))}
{submitting ? "Creating..." : "Create alert"}
Tell us what you want.
Pick a range or leave it as Any. We email you when a listing matches every selection.
{product.specs.cpu.length > 0 && (
setFilters(f => ({ ...f, cpu: value }))}
/>
)}
{product.specs.ram.length > 0 && (
setFilters(f => withFilterRange(f, "ram", range))}
format={formatRam}
/>
)}
setFilters(f => withFilterRange(f, "storage", range))}
format={formatStorage}
/>
You'll get an email when {product.storeName} lists a {summarize(productId, filters)}{isAppleProduct ? in {selectedRegion.label} : null}.
{lockEmail ? (
setEmail(e.target.value)}
onBlur={() => setTouched(true)}
onKeyDown={(e) => e.key === "Enter" && submit()}
aria-invalid={touched && !emailOk}
style={{background:"var(--bg-soft)", color:"var(--ink-2)"}}
/>
{submitting ? "Creating..." : "Create alert"}
Sending to your Google account email.
) : (
{submitting ? "Opening Google..." : "Continue with Google"}
Google verifies the email we use for alerts.
)}
{error && (
{error}
)}
{lockEmail && touched && !emailOk && (
Enter a valid email.
)}
);
}
function AlertsList({ alerts, onDelete }) {
return (
{alerts.length === 0 && (
No alerts yet. Pick a product below to create your first.
)}
{alerts.map(a => {
const p = PRODUCTS[a.productId];
const bits = [];
if (APPLE_PRODUCT_IDS.has(a.productId)) {
const r = regionById(a.filters.region || "us");
bits.push(`${r.flag} ${r.label}`);
}
const cpuText = formatCpuFilter(a.filters.cpu, null);
if (cpuText) bits.push(cpuText);
const ramRange = rangeFromFilters(a.filters, "ram");
const storageRange = rangeFromFilters(a.filters, "storage");
if (p.specs.ram.length) bits.push(!isAnyRange(ramRange) ? `${formatRange(ramRange, formatRam)} RAM` : "any RAM");
bits.push(!isAnyRange(storageRange) ? `${formatRange(storageRange, formatStorage)} storage` : "any storage");
return (
{p.name} · {bits.join(" · ")}
Notifying {a.email} · created {a.createdLabel}
Active
onDelete(a.id)}>
);
})}
);
}
function SignInModal({ open, onClose, onGoogleSignIn }) {
const [busy, setBusy] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
if (open) {
setBusy(false);
setError(null);
}
}, [open]);
useEffect(() => {
if (!open) return;
const onKey = (e) => { if (e.key === "Escape") onClose(); };
document.addEventListener("keydown", onKey);
return () => document.removeEventListener("keydown", onKey);
}, [open, onClose]);
if (!open) return null;
const submit = async () => {
if (busy) return;
setBusy(true);
setError(null);
try {
await onGoogleSignIn();
} catch (err) {
setError("Could not start Google sign-in. Try again.");
setBusy(false);
}
};
return (
e.stopPropagation()}>
Use your Google account so we can attach alerts to a verified email. RefurbPing only stores your email for sign-in and notifications.
{busy ? "Opening Google..." : "Continue with Google"}
No password to remember. You can revoke access from your Google account at any time.
{error &&
{error}
}
);
}
function SignedOutAlerts({ onSignIn }) {
return (
Sign in to manage alerts
View, pause, edit, or delete alerts tied to your Google email.
);
}
function HowItWorks() {
const steps = [
{ n: "1", t: "Set your spec", d: "Pick a product, then a chip, minimum RAM, and minimum storage. Or leave any field as Any." },
{ n: "2", t: "We watch in real time", d: "The monitor checks Apple refurb inventory continuously and pushes matching updates without an intentional delay." },
{ n: "3", t: "Email lands immediately", d: "When a listing matches every field of your alert, the notification email includes the direct Apple buy link." },
];
return (
);
}
// ─── Tweak defaults ───────────────────────────────────────────────────────────
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"accent": "#0071e3",
"ping": "#30d158",
"density": "regular"
}/*EDITMODE-END*/;
// ─── App ──────────────────────────────────────────────────────────────────────
function App() {
const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
const [region, setRegion] = useState("us");
const [activeProduct, setActiveProduct] = useState(null);
const [auth, setAuth] = useState({ signedIn: false, email: null, userId: null });
const [authLoading, setAuthLoading] = useState(true);
const [alerts, setAlerts] = useState([]);
const [toast, setToast] = useState(null);
const [signInOpen, setSignInOpen] = useState(false);
const watchingCount = 12834 + alerts.length;
const showToast = (message, ms = 3200) => {
setToast(message);
setTimeout(() => setToast(null), ms);
};
const refreshSession = async () => {
const session = await api("/api/session");
setAuth(sessionAuth(session));
setAlerts(session.alerts || []);
setAuthLoading(false);
return session;
};
// Push tweak values into CSS vars + body classes
useEffect(() => {
document.documentElement.style.setProperty("--accent", t.accent);
document.documentElement.style.setProperty("--ping", t.ping);
document.body.classList.remove("density-compact", "density-comfy");
if (t.density === "compact") document.body.classList.add("density-compact");
if (t.density === "comfy") document.body.classList.add("density-comfy");
}, [t.accent, t.ping, t.density]);
useEffect(() => {
refreshSession().then((session) => {
const url = new URL(window.location.href);
const authResult = url.searchParams.get("auth");
const wantsAlertManager = url.searchParams.get("manage") === "alerts";
const sessionState = sessionAuth(session);
if (authResult === "ok") showToast("Signed in");
if (authResult === "expired") showToast("That sign-in link expired. Request a new one.", 4200);
if (authResult === "google-expired") showToast("That Google sign-in expired. Try again.", 4200);
if (authResult === "google-denied") showToast("Google sign-in was cancelled.", 3200);
if (authResult === "google-unverified") showToast("Your Google email is not verified.", 4200);
if (authResult === "google-error") showToast("Could not finish Google sign-in. Try again.", 4200);
if (authResult) {
url.searchParams.delete("auth");
window.history.replaceState({}, "", url.pathname + url.search + url.hash);
}
if (wantsAlertManager) {
setTimeout(() => {
document.getElementById("alerts")?.scrollIntoView({ behavior: "smooth", block: "start" });
}, 80);
if (!sessionState.signedIn) setSignInOpen(true);
}
}).catch(() => {
setAuthLoading(false);
showToast("Could not load your session", 4200);
});
}, []);
const startGoogleAuth = async (payload = { purpose: "sign-in" }) => {
const nextPayload = { ...payload };
const url = new URL(window.location.href);
if (!nextPayload.returnTo && nextPayload.purpose === "sign-in" && url.searchParams.get("manage") === "alerts") {
nextPayload.returnTo = "/?manage=alerts#alerts";
}
const res = await api("/api/auth/google/start", {
method: "POST",
body: JSON.stringify(nextPayload),
});
window.location.href = res.authorizeUrl;
};
const signOut = async () => {
await api("/api/auth/sign-out", { method: "POST", body: JSON.stringify({}) });
setAuth({ signedIn: false, email: null, userId: null });
setAlerts([]);
setAuthLoading(false);
showToast("Signed out", 2200);
};
const handleCreate = async ({ productId, email, filters }) => {
if (auth.signedIn && email === auth.email) {
const res = await api("/api/alerts", {
method: "POST",
body: JSON.stringify({ productId, filters }),
});
setAlerts(a => [res.alert, ...a]);
setActiveProduct(null);
showToast("Alert saved — we'll email " + email + " when it matches.", 3500);
setTimeout(() => {
const el = document.getElementById("alerts");
if (el) window.scrollTo({ top: el.offsetTop - 60, behavior: "smooth" });
}, 80);
} else {
await startGoogleAuth({
purpose: "alert",
pendingAlert: { productId, filters },
});
}
};
const handleDelete = async (id) => {
await api("/api/alerts/" + encodeURIComponent(id), { method: "DELETE" });
setAlerts(a => a.filter(x => x.id !== id));
};
const pickProduct = (id) => {
setActiveProduct(id);
setTimeout(() => {
const el = document.getElementById("configurator");
if (el) window.scrollTo({ top: el.offsetTop - 40, behavior: "smooth" });
}, 60);
};
return (
setSignInOpen(true)} onSignOut={signOut} />
21 Apple refurbished stores live
{activeProduct ? (
setActiveProduct(null)}
onCreate={handleCreate}
prefilledEmail={!authLoading && auth.signedIn ? auth.email : ""}
lockEmail={!authLoading && auth.signedIn}
/>
) : (
Choose a product
What should we watch?
{Object.keys(PRODUCTS).length} products live · {COMING_SOON.length} on the way
{Object.values(PRODUCTS).map(product => (
))}
{COMING_SOON.map(p => (
))}
)}
{authLoading ? (
) : auth.signedIn ? (
Your alerts
{alerts.length > 0 ? `${alerts.length} alert${alerts.length === 1 ? "" : "s"} live` : "No alerts yet"}
{alerts.length > 0 && (
Add more anytime · unsubscribe from any email
)}
) : (
Manage your alerts
Already created some?
setSignInOpen(true)} />
)}
How it works
Three steps. Then nothing — until it matters.
{toast && (
{toast}
)}
setSignInOpen(false)}
onGoogleSignIn={() => startGoogleAuth({ purpose: "sign-in" })}
/>
setTweak("accent", v)} />
setTweak("ping", v)} />
setTweak("density", v)} />
);
}
ReactDOM.createRoot(document.getElementById("root")).render( );