feat: persist customer product and shop favorites through the live API

Replace mall fixture favorites with customer-scoped endpoints, and send signed-out shoppers back to the page they left after sign-in.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Chengdong Zhang
2026-09-21 18:51:45 +08:00
co-authored by Cursor
parent 94a64ec712
commit 6c1357ec4d
34 changed files with 1783 additions and 119 deletions
+19
View File
@@ -342,6 +342,25 @@ for (const p of products) {
}
console.log(`products ready: ${products.length} across ${SHOPS.length} shops`);
// 5c. deterministic customer favorites (idempotent PUTs).
{
r = await call("POST", "/auth/login", {
body: { email: "customer@vmall.local", password: "customer123" },
});
if (r.status !== 200) fail("customer login for favorites", r);
const customerToken = r.data.token;
const listed = await call("GET", `/products?shop_id=${demoShopId}&per_page=100`);
const headphones = Array.isArray(listed.data?.items)
? listed.data.items.find((p) => p.slug === "wireless-headphones")
: null;
if (!headphones?.id) fail("lookup wireless-headphones", listed);
r = await call("PUT", `/favorites/products/${headphones.id}`, { token: customerToken });
if (r.status !== 200) fail("seed product favorite", r);
r = await call("PUT", `/favorites/shops/${demoShopId}`, { token: customerToken });
if (r.status !== 200) fail("seed shop favorite", r);
console.log("favorites ready: wireless-headphones + demo-store");
}
// 6. points mall products (idempotent by English name). The demo customer's
// spendable points are credited by the API through the account ledger.
const POINTS_PRODUCTS = [