feat(products-ui): admin nav + Products page with import history (§5.2)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,16 @@
|
||||
// Admin shell (SD-0001 §5.4) — the storefront's stable home; honestly empty this release
|
||||
// (PUC-8; PUC-9 sign-out). Renders from /me alone: storefront name + signed-in email. No
|
||||
// zeroed metric tiles, no locked-feature teasers (OHM: Agency & Anti-Manipulation).
|
||||
// Visuals per the ui/designs export (hf-admin).
|
||||
// Admin shell (SD-0001 §5.4) — the storefront's stable home; the home view is honestly
|
||||
// empty this release (PUC-8; PUC-9 sign-out). Renders from /me alone: storefront name +
|
||||
// signed-in email. No zeroed metric tiles, no locked-feature teasers (OHM: Agency &
|
||||
// Anti-Manipulation). Visuals per the ui/designs export (hf-admin). SD-0002 §5 adds the
|
||||
// admin nav strip + hash-routed products section (adminRouting.ts).
|
||||
import { useEffect, useState } from "react";
|
||||
import { adminViewFor, type AdminView } from "../adminRouting";
|
||||
import { logout } from "../api";
|
||||
import { AccountChip, Banner, Eyebrow, Screen, TopBar } from "../ui/kit";
|
||||
import ImportPreview from "./products/ImportPreview";
|
||||
import ImportUpload from "./products/ImportUpload";
|
||||
import ProductsPage from "./products/ProductsPage";
|
||||
import RunDetail from "./products/RunDetail";
|
||||
|
||||
interface Props {
|
||||
storefrontName: string;
|
||||
@@ -13,6 +20,14 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function Admin({ storefrontName, email, welcome, onSignedOut }: Props) {
|
||||
const [view, setView] = useState<AdminView>(adminViewFor(window.location.hash));
|
||||
|
||||
useEffect(() => {
|
||||
const onHashChange = () => setView(adminViewFor(window.location.hash));
|
||||
window.addEventListener("hashchange", onHashChange);
|
||||
return () => window.removeEventListener("hashchange", onHashChange);
|
||||
}, []);
|
||||
|
||||
async function signOut() {
|
||||
await logout();
|
||||
onSignedOut();
|
||||
@@ -32,27 +47,41 @@ export default function Admin({ storefrontName, email, welcome, onSignedOut }: P
|
||||
}
|
||||
right={<AccountChip email={email} onSignOut={signOut} />}
|
||||
/>
|
||||
<nav className="adminnav" aria-label="Admin sections">
|
||||
<a className={`adminnav__item${view.view === "home" ? " adminnav__item--active" : ""}`} href="#/">
|
||||
Overview
|
||||
</a>
|
||||
<a className={`adminnav__item${view.view !== "home" ? " adminnav__item--active" : ""}`} href="#/products">
|
||||
Products
|
||||
</a>
|
||||
</nav>
|
||||
<main className="screen__main">
|
||||
<div className="empty">
|
||||
{welcome && (
|
||||
<div style={{ marginBottom: 24, width: "100%" }}>
|
||||
<Banner tone="info" title={welcome === "new" ? "Welcome to ecomm" : "Welcome back"}>
|
||||
{welcome === "new"
|
||||
? "A new account was created for this email."
|
||||
: "Signed in to your existing account."}
|
||||
</Banner>
|
||||
{view.view === "home" && (
|
||||
<div className="empty">
|
||||
{welcome && (
|
||||
<div style={{ marginBottom: 24, width: "100%" }}>
|
||||
<Banner tone="info" title={welcome === "new" ? "Welcome to ecomm" : "Welcome back"}>
|
||||
{welcome === "new"
|
||||
? "A new account was created for this email."
|
||||
: "Signed in to your existing account."}
|
||||
</Banner>
|
||||
</div>
|
||||
)}
|
||||
<div className="empty__seal" aria-hidden="true">
|
||||
<img src="/brand/mark-mono-gold.svg" width={36} height={36} alt="" />
|
||||
</div>
|
||||
)}
|
||||
<div className="empty__seal" aria-hidden="true">
|
||||
<img src="/brand/mark-mono-gold.svg" width={36} height={36} alt="" />
|
||||
<Eyebrow>Your storefront</Eyebrow>
|
||||
<h1>{storefrontName}</h1>
|
||||
<p className="empty__copy">
|
||||
There's nothing to manage yet — and that's a finished state, not a missing one.
|
||||
Catalog, orders, and settings will appear here as ecomm grows.
|
||||
</p>
|
||||
</div>
|
||||
<Eyebrow>Your storefront</Eyebrow>
|
||||
<h1>{storefrontName}</h1>
|
||||
<p className="empty__copy">
|
||||
There's nothing to manage yet — and that's a finished state, not a missing one.
|
||||
Catalog, orders, and settings will appear here as ecomm grows.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{view.view === "products" && <ProductsPage />}
|
||||
{view.view === "import-upload" && <ImportUpload />}
|
||||
{view.view === "import-preview" && <ImportPreview draftId={view.draftId} />}
|
||||
{view.view === "run-detail" && <RunDetail runId={view.runId} />}
|
||||
</main>
|
||||
</Screen>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user