import { useEffect, useState } from "react";
import SharedNavbar from "../components/SharedNavbar";
import { formatChf } from "../shop/money";
import { useShop } from "../shop/useShop";
import "./SmallBatchPage.css";
function Requirement({ label, met, children }) {
return (
{label}
{children || (met ? "met" : "open")}
);
}
function SmallBatchPage() {
const { openProfile, token, user } = useShop();
const [state, setState] = useState({
loading: false,
error: "",
loyaltyStatus: user?.loyaltyStatus || null,
releases: [],
});
useEffect(() => {
if (!token) return;
fetch("/api/small-batch", {
headers: { Authorization: `Bearer ${token}` },
})
.then(async (response) => {
const data = await response.json().catch(() => ({}));
if (!response.ok) throw new Error(data.error || "Small Batch request failed.");
setState({
loading: false,
error: "",
loyaltyStatus: data.loyaltyStatus,
releases: data.releases || [],
});
})
.catch((error) => {
setState((current) => ({
...current,
loading: false,
error:
error instanceof Error
? error.message
: "Shop API unreachable. Start it with npm run dev and try again.",
}));
});
}, [token, user?.loyaltyStatus]);
const loyalty = state.loyaltyStatus || {
hasDiscoverySet: false,
hasFullSize: false,
purchases: 0,
spent_cents: 0,
unlocked: false,
};
return (
SMALL BATCH / ARCHIVE / PROTOTYPE
EARLY ACCESS
Limited releases are reserved for customers with enough purchase
history to understand the atmos material language.
{!user ? (
LOGIN REQUIRED
Sign in to check access.
Small Batch access is calculated from your completed orders.
) : (
<>
ACCESS STATUS
{loyalty.unlocked ? "Unlocked" : "Locked"}
= 3}>
{loyalty.purchases}/3 Purchases
50000}>
{formatChf(loyalty.spent_cents)} / CHF 500+
{state.error && {state.error}
}
{state.loading && Loading access...
}
{loyalty.unlocked && (
{state.releases.map((release) => (
{release.type}
{release.name}
{release.note}
))}
)}
>
)}
);
}
export default SmallBatchPage;