Cart.jsx
2.4 kB · jsx · 71 lines
1import { useSyncExternalStore } from "react";2import { checkoutUrl, clear, count, load, remove, server, setQty, subscribe, total } from "../lib/cart.ts";3import { designOf, GIFT_PREFIX, lineUrl, money } from "../lib/shop.ts";4import { Icon } from "../components/Icon.jsx";56function Line({ item }) {7 const href = lineUrl(item.key);8 return (9 <div className="line">10 <a href={href}>11 <img src={item.image} alt="" width="88" height="88" decoding="async" />12 </a>13 <div className="who">14 <a href={href}>{item.key.startsWith(GIFT_PREFIX) ? item.title : `${item.title} (${designOf(item.key)})`}</a>15 <p className="fine">{`${item.size} · ${money(item.price)}`}</p>16 <div className="qty">17 <button type="button" aria-label="One less" onClick={() => setQty(item.id, item.qty - 1)}>18 <Icon name="remove" extra="small" />19 </button>20 <b>{item.qty}</b>21 <button type="button" aria-label="One more" onClick={() => setQty(item.id, item.qty + 1)}>22 <Icon name="add" extra="small" />23 </button>24 </div>25 </div>26 <p className="price">{money(Number(item.price) * item.qty)}</p>27 <button type="button" className="remove" onClick={() => remove(item.id)}>28 Remove29 </button>30 </div>31 );32}3334export function Cart() {35 const items = useSyncExternalStore(subscribe, load, server);36 const n = count(items);37 return (38 <div className="wrap text">39 <div className="page-head">40 <h1>Bag</h1>41 </div>42 <div>43 {items.map((item) => (44 <Line key={item.id} item={item} />45 ))}46 </div>47 {items.length ? (48 <div className="sum">49 <p className="total">{`${n} item${n === 1 ? "" : "s"} · ${money(total(items))}`}</p>50 <a className="pill go" href={checkoutUrl(items) || "/cart/"}>51 Checkout52 </a>53 <button type="button" className="pill" onClick={clear}>54 Clear bag55 </button>56 <a className="back" href="/shop/">57 Continue shopping58 </a>59 </div>60 ) : (61 <div className="sum empty">62 <Icon name="shopping_bag" extra="big" />63 <p className="lead">Your bag is empty.</p>64 <a className="pill go" href="/shop/">65 Browse the shop66 </a>67 </div>68 )}69 </div>70 );71}