/* =========================================================== Cart + Checkout + Order confirmation =========================================================== */ function Countdown({ expires }) { const [left, setLeft] = useState(Math.max(0, (expires || 0) - Date.now())); useEffect(() => { const t = setInterval(() => setLeft(Math.max(0, (expires || 0) - Date.now())), 1000); return () => clearInterval(t); }, [expires]); if (!expires) return null; const m = Math.floor(left / 60000), s = Math.floor((left % 60000) / 1000); return React.createElement("div", { className: "reservation" + (left < 120000 ? " urgent" : "") }, React.createElement(Icon, { name: "clock", size: 15 }), left > 0 ? React.createElement("span", null, "Parts reserved for ", React.createElement("b", null, m + ":" + String(s).padStart(2, "0"))) : React.createElement("span", null, "Reservation expired — totals may update")); } function CartPage() { const cart = useCart(); const { navigate } = useRouter(); if (cart.items.length === 0) return React.createElement("div", { className: "wrap quote-empty", style: { margin: "60px auto" } }, React.createElement(Icon, { name: "cart", size: 40, style: { color: "var(--ink-30)" } }), React.createElement("h3", null, "Your cart is empty"), React.createElement(Link, { to: "/c/heavy-duty-clutches", className: "btn btn-ink" }, "Browse parts")); return React.createElement("div", { className: "wrap", style: { padding: "30px 0 60px" } }, React.createElement(Crumbs, { items: [{ label: "Home", to: "/" }, { label: "Cart" }] }), React.createElement("h1", { style: { fontSize: 34, margin: "12px 0 6px" } }, "Your cart"), React.createElement(Countdown, { expires: cart.reservationExpires }), React.createElement("div", { className: "cart-layout" }, React.createElement("div", { className: "cart-lines" }, cart.items.map(l => React.createElement("div", { key: l.variant_id, className: "cart-line" }, React.createElement("div", { className: "cart-ph ph", "data-label": "" }), React.createElement("div", { className: "cart-line-main" }, React.createElement(Link, { to: "/p/" + l.product_slug, className: "cart-name" }, l.name), React.createElement("div", { className: "qline-sku mono" }, l.sku), React.createElement("button", { className: "linkbtn", onClick: () => cart.remove(l.variant_id), style: { marginTop: 6 } }, "Remove")), React.createElement("div", { className: "cart-line-right" }, React.createElement(Stepper, { value: l.quantity, onChange: q => cart.setQty(l.variant_id, q) }), React.createElement("div", { className: "cart-line-prices" }, React.createElement("div", { className: "price-now", style: { fontFamily: "var(--display)", fontSize: 18 } }, money((l.unit_price || 0) * l.quantity)), l.core_charge ? React.createElement("div", { className: "cart-core" }, "+ core " + money(l.core_charge * l.quantity)) : null)) )) ), React.createElement("aside", { className: "cart-side" }, React.createElement("div", { className: "quote-card" }, React.createElement("h3", null, "Order summary"), React.createElement("div", { className: "qsum-row" }, React.createElement("span", null, "Subtotal"), React.createElement("b", null, money(cart.subtotal))), cart.coreTotal ? React.createElement("div", { className: "qsum-row" }, React.createElement("span", null, "Core charges (refundable)"), React.createElement("b", null, money(cart.coreTotal))) : null, React.createElement("div", { className: "qsum-row" }, React.createElement("span", null, "Freight"), React.createElement("span", { className: "muted" }, "Calculated at checkout")), React.createElement("div", { className: "qsum-total" }, React.createElement("span", null, "Estimated total"), React.createElement("b", null, money(cart.subtotal + cart.coreTotal))), React.createElement("button", { className: "btn btn-primary btn-block btn-lg", style: { marginTop: 14 }, onClick: () => navigate("/checkout") }, "Proceed to checkout"), React.createElement(Link, { to: "/quote", className: "btn btn-ghost btn-block", style: { marginTop: 10 } }, "Convert to a quote instead") ) ) ) ); } /* ---------------- CHECKOUT ---------------- */ function CheckoutPage() { const cart = useCart(); const { navigate } = useRouter(); const toast = useToast(); const [step, setStep] = useState(1); // 1 contact, 2 address, 3 payment const [email, setEmail] = useState(""); const [addr, setAddr] = useState({ name: "", company: "", line1: "", city: "", state: "", zip: "" }); const [placing, setPlacing] = useState(false); const freight = 0; const tax = +(cart.subtotal * 0.06).toFixed(2); const grand = cart.subtotal + cart.coreTotal + tax + freight; if (cart.items.length === 0) return React.createElement("div", { className: "wrap quote-empty", style: { margin: "60px auto" } }, React.createElement("h3", null, "Nothing to check out"), React.createElement(Link, { to: "/c/heavy-duty-clutches", className: "btn btn-ink" }, "Browse parts")); const setA = (k, v) => setAddr(a => ({ ...a, [k]: v })); const place = () => { setPlacing(true); setTimeout(() => { const n = "DW" + (100000 + Math.floor(Math.random() * 900000)); cart.clear(); navigate("/order/" + n); }, 1500); }; return React.createElement("div", { className: "wrap", style: { padding: "30px 0 60px" } }, React.createElement(Crumbs, { items: [{ label: "Home", to: "/" }, { label: "Cart", to: "/cart" }, { label: "Checkout" }] }), React.createElement("h1", { style: { fontSize: 32, margin: "12px 0 20px" } }, "Checkout"), React.createElement("div", { className: "checkout-layout" }, React.createElement("div", { className: "checkout-main" }, // step 1 React.createElement(CheckoutStep, { n: 1, step, title: "Contact", done: step > 1, onEdit: () => setStep(1) }, step === 1 ? React.createElement("div", null, React.createElement("div", { className: "guest-login" }, React.createElement("label", { className: "field" }, React.createElement("span", null, "Email"), React.createElement("input", { type: "email", value: email, onChange: e => setEmail(e.target.value), placeholder: "you@company.com" })), React.createElement("button", { className: "btn btn-ink btn-block", disabled: !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email), onClick: () => setStep(2) }, "Continue as guest"), React.createElement("div", { className: "or-line" }, React.createElement("span", null, "or")), React.createElement(Link, { to: "/account", className: "btn btn-ghost btn-block" }, React.createElement(Icon, { name: "user", size: 16 }), "Sign in / B2B account")) ) : React.createElement("div", { className: "step-summary" }, email) ), // step 2 React.createElement(CheckoutStep, { n: 2, step, title: "Shipping address", done: step > 2, onEdit: () => step > 2 && setStep(2), locked: step < 2 }, step === 2 ? React.createElement("div", null, React.createElement("div", { className: "field-row" }, React.createElement("label", { className: "field" }, React.createElement("span", null, "Full name"), React.createElement("input", { value: addr.name, onChange: e => setA("name", e.target.value) })), React.createElement("label", { className: "field" }, React.createElement("span", null, "Company"), React.createElement("input", { value: addr.company, onChange: e => setA("company", e.target.value), placeholder: "Optional" }))), React.createElement("label", { className: "field" }, React.createElement("span", null, "Street address"), React.createElement("input", { value: addr.line1, onChange: e => setA("line1", e.target.value) })), React.createElement("div", { className: "field-row field-row-3" }, React.createElement("label", { className: "field" }, React.createElement("span", null, "City"), React.createElement("input", { value: addr.city, onChange: e => setA("city", e.target.value) })), React.createElement("label", { className: "field" }, React.createElement("span", null, "State"), React.createElement("input", { value: addr.state, onChange: e => setA("state", e.target.value) })), React.createElement("label", { className: "field" }, React.createElement("span", null, "ZIP"), React.createElement("input", { value: addr.zip, onChange: e => setA("zip", e.target.value) }))), React.createElement("button", { className: "btn btn-ink", disabled: !(addr.name && addr.line1 && addr.city && addr.zip), onClick: () => setStep(3) }, "Continue to payment") ) : step > 2 ? React.createElement("div", { className: "step-summary" }, addr.name + ", " + addr.line1 + ", " + addr.city + " " + addr.state + " " + addr.zip) : null ), // step 3 React.createElement(CheckoutStep, { n: 3, step, title: "Payment", locked: step < 3 }, step === 3 ? React.createElement("div", null, React.createElement("div", { className: "stripe-mock" }, React.createElement("div", { className: "stripe-head" }, React.createElement(Icon, { name: "lock", size: 13 }), "Secured by Stripe"), React.createElement("label", { className: "field" }, React.createElement("span", null, "Card number"), React.createElement("div", { className: "fake-input" }, "4242 4242 4242 4242", React.createElement("span", { className: "card-brand" }, "VISA"))), React.createElement("div", { className: "field-row" }, React.createElement("label", { className: "field" }, React.createElement("span", null, "Expiry"), React.createElement("div", { className: "fake-input" }, "12 / 28")), React.createElement("label", { className: "field" }, React.createElement("span", null, "CVC"), React.createElement("div", { className: "fake-input" }, "•••")))), React.createElement("button", { className: "btn btn-primary btn-block btn-lg", onClick: place, disabled: placing }, placing ? "Processing…" : "Pay " + money(grand)) ) : null ) ), React.createElement("aside", { className: "checkout-side" }, React.createElement("div", { className: "quote-card" }, React.createElement("h3", null, "Order summary"), React.createElement("div", { className: "checkout-items" }, cart.items.map(l => React.createElement("div", { key: l.variant_id, className: "co-item" }, React.createElement("div", { className: "co-ph ph", "data-label": "" }, React.createElement("span", { className: "co-qty" }, l.quantity)), React.createElement("div", { style: { flex: 1, minWidth: 0 } }, React.createElement("div", { className: "co-name" }, l.name), React.createElement("div", { className: "qline-sku mono" }, l.sku)), React.createElement("b", null, money((l.unit_price || 0) * l.quantity))))), React.createElement("div", { className: "qsum-row" }, React.createElement("span", null, "Subtotal"), React.createElement("span", null, money(cart.subtotal))), cart.coreTotal ? React.createElement("div", { className: "qsum-row" }, React.createElement("span", null, "Core charges"), React.createElement("span", null, money(cart.coreTotal))) : null, React.createElement("div", { className: "qsum-row" }, React.createElement("span", null, "Freight (prepaid)"), React.createElement("span", null, "FREE")), React.createElement("div", { className: "qsum-row" }, React.createElement("span", null, "Tax (est.)"), React.createElement("span", null, money(tax))), React.createElement("div", { className: "qsum-total" }, React.createElement("span", null, "Total"), React.createElement("b", null, money(grand))), React.createElement("p", { className: "qsum-note" }, "Net-30 terms available for approved B2B accounts.") ) ) ) ); } function CheckoutStep({ n, step, title, children, done, onEdit, locked }) { const active = step === n; return React.createElement("div", { className: "co-step" + (active ? " active" : "") + (locked ? " locked" : "") }, React.createElement("div", { className: "co-step-head" }, React.createElement("span", { className: "co-step-num" }, done ? React.createElement(Icon, { name: "check", size: 15 }) : n), React.createElement("h3", null, title), done ? React.createElement("button", { className: "linkbtn", onClick: onEdit }, "Edit") : null), React.createElement("div", { className: "co-step-body" }, children) ); } function OrderPage({ number }) { return React.createElement("div", { className: "wrap quote-success" }, React.createElement("div", { className: "success-card" }, React.createElement("div", { className: "success-ring blue" }, React.createElement(Icon, { name: "check", size: 34 })), React.createElement("h1", null, "Order confirmed"), React.createElement("p", { className: "muted" }, "Thanks — your order ", React.createElement("b", null, number), " is in. A confirmation is on its way to your email, and our shop is pulling your parts now."), React.createElement("div", { className: "order-meta" }, React.createElement("div", null, React.createElement("span", { className: "muted" }, "Order #"), React.createElement("b", null, number)), React.createElement("div", null, React.createElement("span", { className: "muted" }, "Freight"), React.createElement("b", null, "Prepaid")), React.createElement("div", null, React.createElement("span", { className: "muted" }, "Updates"), React.createElement("b", null, "By email"))), React.createElement("div", { className: "success-actions" }, React.createElement(Link, { to: "/account", className: "btn btn-ink btn-lg" }, "Track in my account"), React.createElement(Link, { to: "/", className: "btn btn-ghost btn-lg" }, "Back home")), React.createElement("p", { className: "qsum-note", style: { marginTop: 16 } }, "Questions about this order? Call ", React.createElement("a", { href: "tel:4102358829", style: { color: "var(--blue)" } }, "410-235-8829")) ) ); } Object.assign(window, { CartPage, CheckoutPage, OrderPage });