Add Polaris frontend: storefront + admin console (React 18/Vite/TS/Tailwind)
- Shared src/lib/api.ts fetch wrapper -> /api with Cache-Control: no-store - Storefront: home hero, shop grid (category filter + search), product detail, cart, checkout (POST /api/orders -> confirmation + order number), order tracking - Admin: JWT login, today KPI dashboard (revenue/orders/gross/net/margin/aov/refunds), top products, supplier performance, product import, lifecycle view, order list with tracking simulation - Multi-stage Dockerfile (Vite build -> nginx static + /api proxy -> api:8000) - nginx.conf with SPA fallback and no-store HTML caching - mock/mock_api.py for local verification (excluded from image)
This commit is contained in:
84
frontend/src/components/StoreLayout.tsx
Normal file
84
frontend/src/components/StoreLayout.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import { Link, NavLink, Outlet } from 'react-router-dom';
|
||||
import { useCart } from '../store/cart';
|
||||
import { IconCart, IconCoffee, IconExternalLink, IconStar, IconTruck } from './Icons';
|
||||
|
||||
const navLink = ({ isActive }: { isActive: boolean }) =>
|
||||
`rounded-lg px-3 py-2 text-sm font-medium transition ${
|
||||
isActive ? 'bg-white/[0.08] text-white' : 'text-slate-400 hover:text-white'
|
||||
}`;
|
||||
|
||||
export default function StoreLayout() {
|
||||
const { count } = useCart();
|
||||
|
||||
return (
|
||||
<div className="bg-app flex min-h-screen flex-col">
|
||||
<header className="sticky top-0 z-40 border-b border-white/[0.06] bg-night-950/70 backdrop-blur-xl">
|
||||
<div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-4 sm:px-6">
|
||||
<Link to="/" className="flex items-center gap-2.5">
|
||||
<span className="flex h-9 w-9 items-center justify-center rounded-xl bg-gradient-to-br from-indigo-500 to-violet-600 shadow-glow">
|
||||
<IconStar className="h-5 w-5 text-white" />
|
||||
</span>
|
||||
<span className="text-lg font-bold tracking-tight text-white">
|
||||
Polaris<span className="text-indigo-400">.</span>
|
||||
</span>
|
||||
</Link>
|
||||
|
||||
<nav className="hidden items-center gap-1 md:flex">
|
||||
<NavLink to="/" end className={navLink}>
|
||||
Home
|
||||
</NavLink>
|
||||
<NavLink to="/shop" className={navLink}>
|
||||
Shop
|
||||
</NavLink>
|
||||
<NavLink to="/track" className={navLink}>
|
||||
Track order
|
||||
</NavLink>
|
||||
</nav>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Link to="/track" className="btn-ghost !px-3 !py-2 md:hidden" title="Track order">
|
||||
<IconTruck className="h-4 w-4" />
|
||||
</Link>
|
||||
<Link to="/cart" className="btn-ghost relative !px-3.5 !py-2">
|
||||
<IconCart className="h-4 w-4" />
|
||||
<span className="hidden sm:inline">Cart</span>
|
||||
{count > 0 && (
|
||||
<span className="absolute -right-1.5 -top-1.5 flex h-5 min-w-[1.25rem] items-center justify-center rounded-full bg-gradient-to-r from-indigo-500 to-violet-500 px-1 text-[11px] font-bold text-white shadow-glow">
|
||||
{count}
|
||||
</span>
|
||||
)}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main className="flex-1">
|
||||
<Outlet />
|
||||
</main>
|
||||
|
||||
<footer className="border-t border-white/[0.06] bg-night-900/60">
|
||||
<div className="mx-auto flex max-w-7xl flex-col items-center justify-between gap-4 px-4 py-8 sm:flex-row sm:px-6">
|
||||
<div className="flex items-center gap-2 text-sm text-slate-400">
|
||||
<IconStar className="h-4 w-4 text-indigo-400" />
|
||||
<span>Polaris — automated commerce, by starlight.</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<Link to="/admin" className="text-slate-500 transition hover:text-indigo-300">
|
||||
Admin
|
||||
</Link>
|
||||
<a
|
||||
href="https://buymeacoffee.com/r26xrthzttg"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-1.5 rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-amber-200/90 transition hover:bg-white/[0.08]"
|
||||
>
|
||||
<IconCoffee className="h-4 w-4" />
|
||||
Buy me a coffee
|
||||
<IconExternalLink className="h-3.5 w-3.5 opacity-60" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user