import React, { useState, useMemo } from "react"; // Single-file React component for a small e-commerce storefront focused on // Sports cards and Pokémon cards. Uses Tailwind CSS for styling (no external // component libs required). Default-exported React component so it can be // previewed in the canvas. // Usage notes (short): // - Add Tailwind to your project (postcss) and include this component as App.jsx // - Replace the `PRODUCTS` array with API data or connect to a CMS/backend // - Integrate Stripe/PayPal for real payments (checkout() is a stub) // ---------- Sample data ---------- const PRODUCTS = [ { id: "p1", title: "1999 Pokémon Base Set - Charizard Holo", category: "pokemon", sportOrGame: "pokemon", price: 1200.0, condition: "Near Mint", rarity: "Holo", image: "https://picsum.photos/seed/charizard/400/300", stock: 1, }, { id: "p2", title: "2020 Topps Series 1 - Mike Trout", category: "sports", sportOrGame: "baseball", price: 35.0, condition: "Mint", rarity: "Common", image: "https://picsum.photos/seed/trout/400/300", stock: 7, }, { id: "p3", title: "2016 Pokémon - Full Art Trainer", category: "pokemon", sportOrGame: "pokemon", price: 25.0, condition: "Mint", rarity: "Rare", image: "https://picsum.photos/seed/poke1/400/300", stock: 3, }, { id: "p4", title: "2019 Panini - Luka Dončić Rookie", category: "sports", sportOrGame: "basketball", price: 150.0, condition: "Near Mint", rarity: "Rookie", image: "https://picsum.photos/seed/luka/400/300", stock: 2, }, // add more demo items as desired ]; // ---------- Helpers ---------- function currency(n) { return `$${Number(n).toFixed(2)}`; } // ---------- Main component ---------- export default function CardShopApp() { // product state would normally come from an API const [products] = useState(PRODUCTS); const [query, setQuery] = useState(""); const [category, setCategory] = useState("all"); const [sportFilter, setSportFilter] = useState("all"); const [conditionFilter, setConditionFilter] = useState("all"); const [cart, setCart] = useState([]); const [selected, setSelected] = useState(null); // product detail modal // derived lists for UI controls const categories = useMemo(() => ["all", ...new Set(products.map(p => p.category))], [products]); const sports = useMemo(() => ["all", ...new Set(products.map(p => p.sportOrGame))], [products]); const conditions = useMemo(() => ["all", ...new Set(products.map(p => p.condition))], [products]); // filtered products const filtered = useMemo(() => { return products.filter(p => { if (category !== "all" && p.category !== category) return false; if (sportFilter !== "all" && p.sportOrGame !== sportFilter) return false; if (conditionFilter !== "all" && p.condition !== conditionFilter) return false; if (query && !(`${p.title} ${p.rarity}`.toLowerCase()).includes(query.toLowerCase())) return false; return true; }); }, [products, category, sportFilter, conditionFilter, query]); // cart ops function addToCart(product, qty = 1) { setCart(prev => { const found = prev.find(i => i.id === product.id); if (found) { return prev.map(i => i.id === product.id ? { ...i, qty: Math.min(product.stock, i.qty + qty) } : i); } return [...prev, { id: product.id, product, qty: Math.min(product.stock, qty) }]; }); } function removeFromCart(id) { setCart(prev => prev.filter(i => i.id !== id)); } function updateQty(id, qty) { setCart(prev => prev.map(i => i.id === id ? { ...i, qty: Math.max(1, Math.min(i.product.stock, qty)) } : i)); } const subtotal = cart.reduce((s, i) => s + i.product.price * i.qty, 0); const shipping = cart.length ? 6.99 : 0; const tax = subtotal * 0.07; // example fixed tax const total = subtotal + shipping + tax; // checkout stub — replace with real payment flow function checkout() { alert(`Checkout stub — total: ${currency(total)}.\nReplace this with your payment integration (Stripe/PayPal).`); } return (

CardRack — Sports & Pokémon Cards

Curated cards, graded or raw — buy, sell, trade.

setQuery(e.target.value)} placeholder="Search cards or rarity..." className="border rounded-md px-3 py-2 w-64 focus:ring focus:ring-indigo-200" />
{ /* focus handled below */ }} total={total} />
{filtered.map(p => (
{p.title}

{p.title}

{p.rarity} • {p.condition}
{currency(p.price)}
))}
{filtered.length === 0 && (
No matching cards. Try adjusting filters.
)}
{/* Product detail modal */} {selected && (
{selected.title}

{selected.title}

{selected.rarity} • {selected.condition}

Demo description: condition, grading notes, provenance, whether sleeve/Toploader included, and shipping restrictions.

{currency(selected.price)}
)} {/* Bottom-right cart tray */}

Cart

{cart.length === 0 ? (
Your cart is empty.
) : (
{cart.map(i => (
thumb
{i.product.title}
{currency(i.product.price)} • Stock {i.product.stock}
updateQty(i.id, Number(e.target.value))} />
))}
Subtotal
{currency(subtotal)}
Shipping
{currency(shipping)}
Total
{currency(total)}
)}
); } // Simple small cart icon component for header function CartButton({ cart = [], total = 0 }) { return ( ); } /* ----------------------- Next steps & integration tips (keep external to code): - Backend: create simple REST endpoints: /products, /cart, /orders. Use MongoDB/Postgres + Node/Express or Firebase. - Payments: integrate Stripe Checkout or PayPal. On successful payment, create order record and decrement stock. - Inventory: add simple admin area to add/edit listings, upload images (use S3). - Grading & certificates: add fields for grade (PSA/Beckett) and ability to upload certificate images. - SEO & Listings: include structured data (schema.org/Offer) for each product page so cards show price in search. - Fraud prevention: require account for high-value purchases and manual review for >$500 orders. If you want, I can: - convert this to Next.js pages and API routes, - add authentication (NextAuth) and seller dashboards, - wire it to Stripe with server-side checkout, or - produce a mock admin panel to manage inventory. */

Products

Product title

Product title

$19.99

Product title

Product title

$19.99

Product title

Product title

$19.99

Product title

Product title

$19.99

Product title

Product title

$19.99

Product title

Product title

$19.99

Product title

Product title

$19.99

Product title

Product title

$19.99