Planning only: proposal, delta specs, design and tasks for replacing the store surfaces. No code yet. The batch adds a public shop read (profile + products) so the store directory, store home and product-page store card stop reading MOCK_STORES, and so the cart, payment and order surfaces can name a shop instead of printing "Shop". Decisions recorded in the design: - a `shop_profiles` table beside `shops`, so the existing admin and shop-admin contracts are untouched - the four store scores stay stored profile values, because there is no review model and deriving them would dress fabricated numbers as computed ones - `distanceKm` is dropped rather than faked: there is no geo model behind it - profiles are filled by seed-demo.mjs, since they hang off shops that script creates - order surfaces resolve names from one cached shop read rather than growing a denormalised shop name on every order payload openspec validate --strict passes and the change is ready to apply.
33 lines
2.8 KiB
Markdown
33 lines
2.8 KiB
Markdown
# Tasks
|
|
|
|
## 1. Schema
|
|
|
|
- [ ] 1.1 Add a migration creating `shop_profiles` keyed 1:1 to `shops` (`shop_id` primary key, `logo`, `banner`, `company`, `region`, `address` JSONB, `notice` JSONB, `after_sale` JSONB, four score columns, `updated_at`); verify the table exists after `cargo run -p vmall-api`
|
|
|
|
## 2. Shared contract
|
|
|
|
- [ ] 2.1 Add `ShopProfile` (shop identity plus the optional profile fields) and a `ShopProfileInput` to `packages/shared/src/types.ts`; verify all three frontends build
|
|
- [ ] 2.2 Add `listShops()` / `getShop(slug)` to the `ApiClient` and `createApi`, plus `admin.setShopProfile(id, body)`; give the fixed-data adapter matching implementations built from `MOCK_STORES` so the rollback path still renders; verify the mall build
|
|
|
|
## 3. Public shop read
|
|
|
|
- [ ] 3.1 Add `GET /api/shops` returning active shops with their profile, and `GET /api/shops/{slug}` returning one, both unauthenticated and both tolerating a missing profile row; verify a suspended shop is absent from the list and an unknown slug is a 404
|
|
- [ ] 3.2 Add `PUT /api/admin/shops/{id}/profile` upserting the profile, validating non-empty `en`/`zh` on bilingual fields and gated to `platform_admin`; verify a bad payload is refused without changing the stored row
|
|
|
|
## 4. Demo profiles
|
|
|
|
- [ ] 4.1 Teach `scripts/seed-demo.mjs` to set a profile for each demo shop using the existing `/mock/store-N.svg` assets and bilingual copy; verify a re-run is idempotent and `GET /api/shops` returns a profile for every shop
|
|
|
|
## 5. Mall store surfaces
|
|
|
|
- [ ] 5.1 `pages/stores/index.vue`: list from `GET /api/shops` and drop the distance column and its sort; verify the directory renders every active shop and no "km" text remains
|
|
- [ ] 5.2 `pages/stores/[id].vue`: load the shop by slug and its products from the catalog API by `shop_id`, drop the mock sales ranking in favour of the same shop-scoped product call; verify a store page renders its profile and products
|
|
- [ ] 5.3 `pages/goods/[id].vue`: read the store card from the shop API instead of `storeById`, keeping the existing guards for a missing profile
|
|
- [ ] 5.4 `pages/checkout/pay.vue` and `pages/user/orders/index.vue`: resolve shop names from the cached shop read, removing the generic "Shop" placeholder
|
|
|
|
## 6. Verification
|
|
|
|
- [ ] 6.1 Run the mall, shop-admin and admin builds, since the shared contract changed; verify all three pass and `cargo test -p vmall-api` stays green
|
|
- [ ] 6.2 With the backend seeded, verify in a browser that the store directory lists the demo shops, a store home renders its profile and products, the product page's store card shows a real name, and the cart/payment/order surfaces name the shop; confirm no console errors beyond deliberate failed responses
|
|
- [ ] 6.3 Verify the rollback: with every domain on fixed data and the backend stopped, the store directory and store home still render
|