Files
vmall/openspec/changes/archive/2026-09-17-frontend-apps/agent-admin.md
T

2.4 KiB
Raw Blame History

Task: build apps/admin (platform console) — READ openspec/changes/frontend-apps/agent-conventions.md FIRST and follow it exactly. Your app = @vmall/admin, port 3002. Allowed roles: platform_admin.

Replace the placeholder pages. app.vue (sidebar layout) exists — keep it.

Pages to implement (apps/admin/pages/)

  1. login.vue — per conventions; only platform_admin may proceed. (Seed account: admin@vmall.local / admin1234 — display this hint on the login page in a muted line for the dev MVP.)
  2. index.vue (auth) — dashboard: stat cards (total users, shops, orders, enabled currencies) from $api.admin.listUsers(), $api.admin.listShops(), $api.admin.listOrders(), $api.admin.listCurrencies().
  3. users.vue (auth) — $api.admin.listUsers(page) table: email, display_name, role badge, assigned shop (resolve shop_id → shop name via $api.admin.listShops(), localized), created. Role editor per row: role select (platform_admin/shop_owner/shop_staff/customer) + shop select shown ONLY for shop roles + save button → $api.admin.setUserRole(id, role, shopId|null); on validation error (e.g. shop role without shop → 400) show message. Paging.
  4. shops.vue (auth) — $api.admin.listShops() table: localized name, slug, status badge, created; actions suspend/activate → $api.admin.setShopStatus. Create-shop card: name EN, name ZH, slug → $api.admin.createShop({en, zh}, slug); refetch; show conflict error (duplicate slug → 409).
  5. orders.vue (auth) — $api.admin.listOrders(page): table (order_no, shop (resolve id→name), user_id short, total formatted in order.currency, status badge, created). Paging.
  6. currencies.vue (auth) — $api.admin.listCurrencies() table: code, localized name, symbol, exponent, rate_to_base, base badge, enabled badge. Per-row rate editor (number input + save → $api.admin.setRate(code, rate)). New-currency card: code (3 letters), name EN + ZH, symbol, exponent (06), rate_to_base, enabled checkbox → $api.admin.upsertCurrency({...}) with CurrencyUpsertBody (rate_to_base is a STRING). Toggle enabled via upsert with the row's other fields preserved.

Middleware

middleware/auth.ts per conventions; apply to everything except /login.

Verify

pnpm --filter @vmall/admin build MUST pass. Fix type errors properly (no any, no @ts-ignore).

Report back

Pages built, deviations, contract gaps found.