TheBird

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}