1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
import { useSyncExternalStore } from "react";
import type { Money, Product } from "../api/client";
import { addMoney } from "../lib/money";
export type CartLine = { product: Product; quantity: number };
let lines: CartLine[] = [];
const listeners = new Set<() => void>();
function emit() {
listeners.forEach((l) => l());
}
export const cart = {
add(product: Product) {
const line = lines.find((l) => l.product.id === product.id);
lines = line
? lines.map((l) => (l === line ? { ...l, quantity: l.quantity + 1 } : l))
: [...lines, { product, quantity: 1 }];
emit();
},
remove(productID: string) {
lines = lines.filter((l) => l.product.id !== productID);
emit();
},
clear() {
lines = [];
emit();
},
total(currency: string): Money {
return addMoney(
currency,
lines.map((l) => ({ currency, minor: l.product.price.minor * l.quantity })),
);
},
};
export function useCart() {
useSyncExternalStore(
(l) => {
listeners.add(l);
return () => listeners.delete(l);
},
() => lines,
);
return { lines, ...cart };
}
|