Wave 1 of replacing the fixed-data mock adapter. The mall now selects its API adapter per domain, with catalog and currency served live while auth, cart, orders, shipments and invoices stay on fixed data. Backend: - seed the 6 x 2 x 2 category tree as reference data (migration 0005). The API exposes no category write route, so this cannot come from the seed script - filter public product listing by the category subtree with a recursive CTE, matching the mock's existing behaviour instead of exact-match - add sort=price with order=asc|desc, validated by hand so an unsupported value returns the project's ApiError 400 shape rather than axum's own rejection Mall: - replace the all-or-nothing mockApi boolean with a liveDomains list composed through a typed per-domain pick map - source home floors, the category menu, search and product detail from the catalog API; banners, promos, quick links, store card and comment/coupon content stay local display-only content - drop the brand facet and the sales/comments sorts: no backend model backs them - fix salesOf/commentCountOf, which parsed digits out of the product id and so rendered "NaN sold" for live UUID ids; they now hash the id Seed: 24 products across 4 shops, idempotent on re-run. Note: the mall defaults to a live catalog, so pnpm dev:mall now expects the API to be running; set NUXT_PUBLIC_LIVE_DOMAINS to an empty array for all-mock work. OpenSpec change: openspec/changes/replace-mock-api-wave-1
3.9 KiB
3.9 KiB
Tasks
1. Backend: catalog browse
- 1.1 Add an append-only migration seeding child and grandchild categories under the existing
electronics,fashionandhome-livingrows, matching the mock's 3-level shape; verifyGET /api/categoriesreturns more than 3 rows with populatedparent_id - 1.2 Replace the exact
p.category_id = $1filter inapps/api/src/routes/catalog.rswith aWITH RECURSIVEsubtree CTE shared by the count and page queries; verify a parent-category request returns its descendants' products - 1.3 Add optional
sort=priceandorder=asc|desctolist_products, ordering by each product's lowest active SKU price withNULLS LAST, and reject any other value with anApiError400 whose body is{"error":{"code","message"}}; verify the 400 shape with curl - 1.4 Extend
apps/api/tests/catalog.rswith cases for subtree listing, ascending/descending price order and the rejected-sort 400; verifycargo test -p vmall-apiis green and repeatable
2. Shared contract
- 2.1 Add optional
sortandordertoProductListQueryinpackages/shared/src/api.tsand pass them through increateApi.listProducts; verifypnpm --filter @vmall/mall buildstill type-checks
3. Demo data
- 3.1 Grow
scripts/seed-demo.mjsto roughly 24 bilingual products spread across the new category tree plus 4 shops, keeping the slug-lookup idempotency; verify a second run reports no duplicate creates andGET /api/products?per_page=100returns a full first page
4. Mall: per-domain adapter switch
- 4.1 Replace the
mockApiboolean inapps/mall/plugins/api.tswith aliveDomainslist defaulting to["catalog", "currency"], composing the live client over the fixed-data base through a typed per-domain pick map (noany); verify catalog requests hit:8080whilegetCartstill resolves from fixed data with the backend stopped
5. Mall: rewire browse surfaces
- 5.1
apps/mall/pages/index.vue: build floors fromlistCategoriespluslistProductsper category, leaving banners, promos, quick links and floor advert art local; verify every non-empty floor renders live products - 5.2
apps/mall/components/shell/CategoryMenu.vue: source the tree fromlistCategories, keeping the header dropdown mode and the pinned home mode intact; verify the pinned sidebar shows children from the API - 5.3
apps/mall/pages/search.vue: list throughlistProductswith the selected category's subtree and the new sort, and delete the brand facet plus thesales/commentssort options; verify filtering by a parent category lists descendant products - 5.4
apps/mall/pages/goods/[id].vue: load the product and SKUs throughgetProduct, keeping the comment, coupon and sales-rail sections on local display-only content; verify an in-stock SKU selection updates price, stock and the cart target - 5.5 Remove only the catalog helpers that lost their last consumer (
topCategories,childCategories,homeFloors,MOCK_BRANDS,brandOf,HomeFloor,MockBrand) fromapps/mall/mock/data.ts; amended from the original wording, which also removedMOCK_PRODUCTSand would have broken the rollback theMock API adapterrequirement promises, soMOCK_PRODUCTS/searchMockProducts/productByIdstay; verifypnpm --filter @vmall/mall buildpasses with no page importing a removed symbol
6. Verification
- 6.1 Run
pnpm --filter @vmall/mall build,pnpm --filter @vmall/shop-admin buildandpnpm --filter @vmall/admin build, since the shared contract changed; verify all three pass - 6.2 With the live backend and seeds running, verify in a browser that home, search, product detail and the pinned category menu render live data, and that no console errors appear
- 6.3 Stop the backend and confirm the mall still starts and the unmigrated domains (auth, cart, orders, invoices) keep working from fixed data; verify the browse pages degrade without crashing