import React, { useState, useEffect, useMemo } from "react"; import { ShoppingCart, Heart, Search, X, Plus, Minus, Trash2, Lock, CheckCircle2, ChevronRight, ChevronLeft, Package, CreditCard, Truck, Pencil, LogOut, Star, MessageCircle, Copy, Landmark, User, Mail, KeyRound, Sun, Moon } from "lucide-react"; /* --------------------------------------------------------- SHOP ZONE Design tokens: bg #FFFFFF surface #FFF6EE chip #FFE4CC text #211A14 textDim #8C7C6D border #F2DFC9 accent #FF6A1A Display: Space Grotesk | Body: Inter | Data/mono: IBM Plex Mono --------------------------------------------------------- */ const FONT_LINK_ID = "sz-fonts"; function useFonts() { useEffect(() => { if (document.getElementById(FONT_LINK_ID)) return; const link = document.createElement("link"); link.id = FONT_LINK_ID; link.rel = "stylesheet"; link.href = "https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap"; document.head.appendChild(link); }, []); } const ACCENT = "#FF6A1A"; const BANK_DETAILS = { whatsapp: "08086061771", accountNumber: "2079040532", accountName: "Akerele James Ayomide", bankName: "Kuda MFB", }; const ADMIN_PASSWORD = "@ayomidey10"; const LIGHT = { bg: "#FFFFFF", surface: "#FFF6EE", surfaceAlt: "#FFFFFF", chip: "#FFE4CC", border: "#F2DFC9", text: "#211A14", textDim: "#8C7C6D", solidBg: "#211A14", solidText: "#FFFFFF", headerBg: "#FFFFFFEE", overlayChip: "#FFFFFFCC", scrollbar: "#E8D9C8", }; const DARK = { bg: "#0D0D12", surface: "#1A1611", surfaceAlt: "#221C16", chip: "#2E2519", border: "#3D3020", text: "#F5EFE7", textDim: "#B8A996", solidBg: "#F5EFE7", solidText: "#0D0D12", headerBg: "#0D0D12EE", overlayChip: "#0D0D12CC", scrollbar: "#3D3020", }; const money = (n) => `$${n.toFixed(2)}`; const SWATCHES = [ ["#4C6FFF", "#131A4A"], ["#FF6B5B", "#3E1712"], ["#3DDC97", "#0F3A2A"], ["#FFB84C", "#4A2E0A"], ["#B26CFF", "#2A1550"], ["#4CC9FF", "#0E2A3D"], ]; function Swatch({ product, size = "full" }) { const colors = product.swatch || SWATCHES[0]; return (
); } export default function ShopZoneStore() { useFonts(); const [products, setProducts] = useState([]); const [loaded, setLoaded] = useState(false); const [view, setView] = useState("shop"); // shop | wishlist | admin | account const [darkMode, setDarkMode] = useState(false); const t = (darkMode || view === "admin") ? DARK : LIGHT; // admin is always dark const [search, setSearch] = useState(""); const [cart, setCart] = useState({}); const [wishlist, setWishlist] = useState({}); const [cartOpen, setCartOpen] = useState(false); const [selectedProduct, setSelectedProduct] = useState(null); const [checkoutStep, setCheckoutStep] = useState(0); // 0 closed,1 shipping,2 payment,3 done const [orderNum, setOrderNum] = useState(null); const [orders, setOrders] = useState([]); const [processing, setProcessing] = useState(false); const [paymentMethod, setPaymentMethod] = useState("card"); const [showBankModal, setShowBankModal] = useState(false); const [shipForm, setShipForm] = useState({ fullName: "", email: "", phone: "", address: "" }); const [shipFormError, setShipFormError] = useState(null); const [adminAuthed, setAdminAuthed] = useState(false); const [pwInput, setPwInput] = useState(""); const [pwError, setPwError] = useState(false); const [editingProduct, setEditingProduct] = useState(null); const [accounts, setAccounts] = useState([]); const [session, setSession] = useState(null); // logged-in email const [toast, setToast] = useState(null); const showToast = (msg) => { setToast(msg); setTimeout(() => setToast(null), 1800); }; const copyText = (text, label) => { if (navigator.clipboard) navigator.clipboard.writeText(text).catch(() => {}); showToast(`${label} copied`); }; // Load persisted state useEffect(() => { (async () => { try { const [p, c, w, acc, sess, ord, dm] = await Promise.allSettled([ window.storage.get("shopzone:products"), window.storage.get("shopzone:cart"), window.storage.get("shopzone:wishlist"), window.storage.get("shopzone:accounts", true), window.storage.get("shopzone:session"), window.storage.get("shopzone:orders", true), window.storage.get("shopzone:darkmode"), ]); if (p.status === "fulfilled" && p.value) setProducts(JSON.parse(p.value.value)); if (c.status === "fulfilled" && c.value) setCart(JSON.parse(c.value.value)); if (w.status === "fulfilled" && w.value) setWishlist(JSON.parse(w.value.value)); if (acc.status === "fulfilled" && acc.value) setAccounts(JSON.parse(acc.value.value)); if (sess.status === "fulfilled" && sess.value) setSession(JSON.parse(sess.value.value)); if (ord.status === "fulfilled" && ord.value) setOrders(JSON.parse(ord.value.value)); if (dm.status === "fulfilled" && dm.value) setDarkMode(JSON.parse(dm.value.value)); } catch (e) { console.log("No prior data yet", e); } setLoaded(true); })(); }, []); useEffect(() => { if (loaded) window.storage.set("shopzone:products", JSON.stringify(products)).catch(() => {}); }, [products, loaded]); useEffect(() => { if (loaded) window.storage.set("shopzone:cart", JSON.stringify(cart)).catch(() => {}); }, [cart, loaded]); useEffect(() => { if (loaded) window.storage.set("shopzone:wishlist", JSON.stringify(wishlist)).catch(() => {}); }, [wishlist, loaded]); useEffect(() => { if (loaded) window.storage.set("shopzone:session", JSON.stringify(session)).catch(() => {}); }, [session, loaded]); useEffect(() => { if (loaded) window.storage.set("shopzone:darkmode", JSON.stringify(darkMode)).catch(() => {}); }, [darkMode, loaded]); const productMap = useMemo(() => Object.fromEntries(products.map((p) => [p.id, p])), [products]); const filtered = useMemo(() => { return products.filter((p) => { if (search.trim() && !p.name.toLowerCase().includes(search.trim().toLowerCase())) return false; return true; }); }, [products, search]); const cartItems = Object.entries(cart) .filter(([, qty]) => qty > 0) .map(([id, qty]) => ({ ...productMap[id], qty })) .filter((i) => i.id); const cartCount = cartItems.reduce((s, i) => s + i.qty, 0); const subtotal = cartItems.reduce((s, i) => s + i.price * i.qty, 0); const shipping = subtotal > 0 && subtotal < 100 ? 8 : 0; const total = subtotal + shipping; const wishlistItems = Object.keys(wishlist).filter((id) => wishlist[id] && productMap[id]).map((id) => productMap[id]); const addToCart = (id, qty = 1) => { setCart((c) => ({ ...c, [id]: (c[id] || 0) + qty })); showToast("Added to cart"); }; const setQty = (id, qty) => { setCart((c) => { const next = { ...c }; if (qty <= 0) delete next[id]; else next[id] = qty; return next; }); }; const toggleWishlist = (id) => setWishlist((w) => ({ ...w, [id]: !w[id] })); const startCheckout = () => { if (!session) { setCartOpen(false); setView("account"); showToast("Sign in to check out"); return; } setCartOpen(false); setShipForm((f) => ({ ...f, email: f.email || session, fullName: f.fullName || currentAccount?.name || "" })); setCheckoutStep(1); }; const proceedToPayment = () => { if (!shipForm.fullName.trim() || !shipForm.address.trim() || !shipForm.phone.trim() || !shipForm.email.trim()) { setShipFormError("Please fill in your name, address, phone number, and Gmail address."); return; } if (!/^\S+@gmail\.com$/i.test(shipForm.email.trim())) { setShipFormError("Please enter a valid Gmail address."); return; } setShipFormError(null); setCheckoutStep(2); }; const saveOrders = (next) => { setOrders(next); window.storage.set("shopzone:orders", JSON.stringify(next), true).catch(() => {}); }; const notifyBuyer = (email, message) => { showToast(`🔔 ${message}`); }; const completeOrder = () => { setProcessing(true); setTimeout(() => { setProcessing(false); const id = `SZ-${Math.floor(100000 + Math.random() * 900000)}`; const newOrder = { id, email: shipForm.email, buyerName: shipForm.fullName || currentAccount?.name || "Guest", phone: shipForm.phone, address: shipForm.address, items: cartItems.map((i) => ({ name: i.name, qty: i.qty, price: i.price })), total, status: "placed", createdAt: new Date().toISOString(), }; saveOrders([newOrder, ...orders]); notifyBuyer(shipForm.email, `your order ${id} has been placed.`, { orderId: id, status: "placed", buyerName: newOrder.buyerName, total }); setOrderNum(id); setCheckoutStep(3); setCart({}); }, 1300); }; const advanceOrderStatus = (orderId, status) => { const next = orders.map((o) => (o.id === orderId ? { ...o, status } : o)); saveOrders(next); const order = orders.find((o) => o.id === orderId); if (order) { const msg = status === "shipped" ? `your order ${orderId} has shipped.` : `your order ${orderId} was delivered.`; notifyBuyer(order.email, msg, { orderId, status, buyerName: order.buyerName, total: order.total }); } }; const saveProduct = (prod) => { setProducts((prev) => { const exists = prev.some((p) => p.id === prod.id); return exists ? prev.map((p) => (p.id === prod.id ? prod : p)) : [prod, ...prev]; }); setEditingProduct(null); showToast(prod._isNew ? "Product added" : "Product updated"); }; const deleteProduct = (id) => { setProducts((prev) => prev.filter((p) => p.id !== id)); showToast("Product removed"); }; const signUp = ({ name, email, password }) => { if (!name.trim() || !email.trim() || !password) return "Fill in every field."; if (accounts.some((a) => a.email.toLowerCase() === email.toLowerCase())) return "An account with that email already exists."; const next = [...accounts, { name, email, password }]; setAccounts(next); window.storage.set("shopzone:accounts", JSON.stringify(next), true).catch(() => {}); setSession(email); showToast(`Welcome, ${name}`); return null; }; const logIn = ({ email, password }) => { const acc = accounts.find((a) => a.email.toLowerCase() === email.toLowerCase()); if (!acc || acc.password !== password) return "Incorrect email or password."; setSession(email); showToast(`Welcome back, ${acc.name}`); return null; }; const logOut = () => { setSession(null); showToast("Signed out"); }; const currentAccount = accounts.find((a) => a.email === session); return (
{/* Header */}
{ setSearch(e.target.value); setView("shop"); }} placeholder="Search products" className="w-full pl-9 pr-3 py-1.5 rounded-full text-sm outline-none" style={{ background: t.surface, border: `1px solid ${t.border}`, color: t.text }} />
{view === "shop" && ( <>

Shop

{filtered.length} {filtered.length === 1 ? "item" : "items"}

{filtered.length === 0 ? (
{products.length === 0 ? "No products yet — check back soon." : "Nothing matches that search."}
) : (
{filtered.map((p) => (
setSelectedProduct(p)}>
{p.name}
{money(p.price)}
))}
)} )} {view === "wishlist" && ( <>

Wishlist

{wishlistItems.length === 0 ? (
Save items you like and they'll show up here.
) : (
{wishlistItems.map((p) => (
setSelectedProduct(p)}>
{p.name}
{money(p.price)}
))}
)} )} {view === "account" && ( o.email === session)} onLogout={logOut} onSignUp={signUp} onLogIn={logIn} /> )} {view === "admin" && ( { if (pwInput === ADMIN_PASSWORD) { setAdminAuthed(true); setPwError(false); } else setPwError(true); }} onLogout={() => { setAdminAuthed(false); setPwInput(""); }} products={products} editingProduct={editingProduct} setEditingProduct={setEditingProduct} saveProduct={saveProduct} deleteProduct={deleteProduct} orders={orders} advanceOrderStatus={advanceOrderStatus} /> )}
{/* Product detail modal */} {selectedProduct && (
setSelectedProduct(null)}>
e.stopPropagation()}>

{selectedProduct.name}

{selectedProduct.rating && (
{selectedProduct.rating}
)}
{money(selectedProduct.price)}
)} {/* Cart drawer */} {cartOpen && (
setCartOpen(false)}>
e.stopPropagation()}>

Your cart

{cartItems.length === 0 ? (
Your cart is empty.
) : (
{cartItems.map((item) => (
{item.name}
{money(item.price)}
{item.qty}
))}
)} {cartItems.length > 0 && (
Subtotal{money(subtotal)}
Shipping{shipping === 0 ? "Free" : money(shipping)}
Total{money(total)}
{!session &&

You'll be asked to sign in first.

}
)}
)} {/* Checkout flow */} {checkoutStep > 0 && (
{checkoutStep !== 3 && (
{[1, 2].map((s) => (
= s ? ACCENT : t.border }} />))}
)} {checkoutStep === 1 && (

Shipping

setShipForm({ ...shipForm, fullName: e.target.value })} placeholder="Full name" className="w-full px-3 py-2.5 rounded-lg text-sm outline-none" style={{ background: t.surfaceAlt, border: `1px solid ${t.border}` }} /> setShipForm({ ...shipForm, email: e.target.value })} placeholder="Gmail address" type="email" className="w-full px-3 py-2.5 rounded-lg text-sm outline-none" style={{ background: t.surfaceAlt, border: `1px solid ${t.border}` }} /> setShipForm({ ...shipForm, phone: e.target.value })} placeholder="Phone number" type="tel" className="w-full px-3 py-2.5 rounded-lg text-sm outline-none" style={{ background: t.surfaceAlt, border: `1px solid ${t.border}` }} /> setShipForm({ ...shipForm, address: e.target.value })} placeholder="Delivery address" className="w-full px-3 py-2.5 rounded-lg text-sm outline-none" style={{ background: t.surfaceAlt, border: `1px solid ${t.border}` }} />
{shipFormError &&

{shipFormError}

}
)} {checkoutStep === 2 && (

Payment

{paymentMethod === "card" ? ( <>

Demo checkout — no real payment is processed.

) : (

Pay by bank transfer — tap below to see the account to pay into.

)}
Total due{money(total)}
)} {checkoutStep === 3 && (

Order confirmed

Order {orderNum} is on its way.

)}
)} {/* Bank transfer account details pop-up */} {showBankModal && (
setShowBankModal(false)}>
e.stopPropagation()}>

Pay by transfer

Transfer {money(total)} to the account below, then confirm in the app.

{[ { label: "Bank", value: BANK_DETAILS.bankName }, { label: "Account name", value: BANK_DETAILS.accountName }, { label: "Account number", value: BANK_DETAILS.accountNumber }, ].map((row) => (
{row.label}
{row.value}
))}
Send payment proof on WhatsApp
)} {toast && (
{toast}
)}
); } const STATUS_META = { placed: { label: "Placed", color: "#8C7C6D" }, shipped: { label: "Shipped", color: "#FFB84C" }, delivered: { label: "Delivered", color: "#3DDC97" }, }; function AccountPage({ t, session, account, orders, onLogout, onSignUp, onLogIn }) { const [mode, setMode] = useState("login"); // login | signup const [form, setForm] = useState({ name: "", email: "", password: "" }); const [error, setError] = useState(null); if (session && account) { return (

{account.name}

{account.email}

Order emails are sent to this address.

My orders

{orders.length === 0 ? (

No orders yet.

) : (
{orders.map((o) => (
{o.id} {STATUS_META[o.status].label}

{o.items.map((i) => `${i.qty}× ${i.name}`).join(", ")}

Total{money(o.total)}
))}
)}
); } const submit = () => { setError(null); const err = mode === "signup" ? onSignUp(form) : onLogIn(form); if (err) setError(err); }; return (

{mode === "login" ? "Welcome back" : "Create your account"}

{mode === "login" ? "Log in to check out and track orders." : "Sign up to start shopping at Shop Zone."}

{mode === "signup" && (
setForm({ ...form, name: e.target.value })} placeholder="Full name" className="w-full pl-9 pr-3 py-2.5 rounded-lg text-sm outline-none" style={{ background: t.surface, border: `1px solid ${t.border}` }} />
)}
setForm({ ...form, email: e.target.value })} placeholder="Email" type="email" className="w-full pl-9 pr-3 py-2.5 rounded-lg text-sm outline-none" style={{ background: t.surface, border: `1px solid ${t.border}` }} />
setForm({ ...form, password: e.target.value })} onKeyDown={(e) => e.key === "Enter" && submit()} placeholder="Password" type="password" className="w-full pl-9 pr-3 py-2.5 rounded-lg text-sm outline-none" style={{ background: t.surface, border: `1px solid ${t.border}` }} />
{error &&

{error}

}
); } function AdminPanel({ t, authed, pwInput, setPwInput, pwError, onLogin, onLogout, products, editingProduct, setEditingProduct, saveProduct, deleteProduct, orders, advanceOrderStatus }) { const blank = { id: "", name: "", price: "", rating: "", swatch: SWATCHES[Math.floor(Math.random() * SWATCHES.length)], _isNew: true }; const [form, setForm] = useState(editingProduct || blank); const [tab, setTab] = useState("products"); // products | orders useEffect(() => { setForm(editingProduct || blank); }, [editingProduct]); if (!authed) { return (

Admin sign-in

Only admins can add products.

setPwInput(e.target.value)} onKeyDown={(e) => e.key === "Enter" && onLogin()} placeholder="Password" className="w-full px-3 py-2.5 rounded-lg text-sm outline-none text-center" style={{ background: t.surface, border: `1px solid ${pwError ? "#FF6B5B" : t.border}` }} /> {pwError &&

Incorrect password.

}
); } const submit = () => { if (!form.name.trim() || !form.price) return; const id = form.id || `p${Date.now()}`; saveProduct({ ...form, id, price: parseFloat(form.price), _isNew: !form.id }); setForm(blank); }; return (

Admin

{tab === "products" ? (

{form.id ? "Edit product" : "Add product"}

setForm({ ...form, name: e.target.value })} placeholder="Product name" className="w-full px-3 py-2 rounded-lg text-sm outline-none" style={{ background: t.surface, border: `1px solid ${t.border}` }} /> setForm({ ...form, price: e.target.value })} placeholder="Price" type="number" step="0.01" className="w-full px-3 py-2 rounded-lg text-sm sz-mono outline-none" style={{ background: t.surface, border: `1px solid ${t.border}` }} />
{form.id && }
{products.length === 0 &&

No products yet. Add your first one on the left.

} {products.map((p) => (
{p.name}
{money(p.price)}
))}
) : (
{orders.length === 0 ? (

No orders yet.

) : orders.map((o) => (
{o.id} {o.buyerName} · {o.email}
{STATUS_META[o.status].label}

{o.items.map((i) => `${i.qty}× ${i.name}`).join(", ")} — {money(o.total)}

))}
)}
); }