2026-08-03 05:52:02 +00:00
|
|
|
|
# T515 — fe-service-profile-tab-brands
|
|
|
|
|
|
|
|
|
|
|
|
> Status: `done`
|
|
|
|
|
|
> Milestone: `M1`
|
|
|
|
|
|
> Kind: `feat`
|
|
|
|
|
|
> Est. change: `~180 lines`
|
|
|
|
|
|
|
|
|
|
|
|
## Goal
|
|
|
|
|
|
|
2026-08-13 02:22:24 +00:00
|
|
|
|
完成後系統應:可完整編修工作區共用服務 Policy 並存檔;目前入口已依實際使用回饋拆到獨立 `/app/policy`,不再混在品牌/案例管理。
|
2026-08-03 05:52:02 +00:00
|
|
|
|
|
|
|
|
|
|
## Depends on
|
|
|
|
|
|
|
|
|
|
|
|
- T502、T511
|
|
|
|
|
|
|
|
|
|
|
|
## Inputs
|
|
|
|
|
|
|
|
|
|
|
|
- Spec:`../spec.md` §4.1、§5.3
|
|
|
|
|
|
- 既有:`apps/web/src/pages/BrandsPage.tsx`、`src/components/ui/`、`src/styles/radar.css`
|
|
|
|
|
|
|
|
|
|
|
|
## Outputs
|
|
|
|
|
|
|
|
|
|
|
|
### 程式變更(預期路徑)
|
|
|
|
|
|
|
|
|
|
|
|
| 路徑 | 動作 | 說明 |
|
|
|
|
|
|
|------|------|------|
|
2026-08-13 02:22:24 +00:00
|
|
|
|
| `apps/web/src/pages/PolicyPage.tsx` | add | 獨立 Policy 頁,掛入服務檔案面板 |
|
|
|
|
|
|
| `apps/web/src/pages/BrandsPage.tsx` | edit | 移除內嵌面板;舊查詢參數轉址 |
|
|
|
|
|
|
| `apps/web/src/lib/nav.ts` | edit | 新增「商機政策」入口 |
|
2026-08-03 05:52:02 +00:00
|
|
|
|
| `apps/web/src/components/radar/ServiceProfileForm.tsx` | add | 服務項目+價格區間、案例、不能說的內容、FAQ、服務地區+可遠端、空檔、語氣備註 |
|
|
|
|
|
|
| `apps/web/src/data/live/radarRepos.ts` | edit | service-profile GET/PUT 實作 |
|
|
|
|
|
|
| `apps/web/src/styles/radar.css` | edit | 表單樣式 |
|
|
|
|
|
|
|
|
|
|
|
|
### 行為變更
|
|
|
|
|
|
|
|
|
|
|
|
- 尚未建立時顯示引導文案與必填提示;存檔成功後顯示更新時間。
|
|
|
|
|
|
- 「不能說的內容」明示用途:會硬性過濾 AI 回覆用詞。
|
|
|
|
|
|
- 驗證錯誤就地顯示後端 message,不吞錯。
|
|
|
|
|
|
|
|
|
|
|
|
## Out of scope
|
|
|
|
|
|
|
|
|
|
|
|
- 雷達訂閱管理(T516)
|
2026-08-13 02:22:24 +00:00
|
|
|
|
- 重新設計 Policy 資料模型或改成每品牌一份
|
2026-08-03 05:52:02 +00:00
|
|
|
|
|
|
|
|
|
|
## Acceptance
|
|
|
|
|
|
|
|
|
|
|
|
- [x] 填寫→存檔→重載欄位一致(mock 與 live 皆可)
|
|
|
|
|
|
- [x] 新樣式只進 `radar.css`
|
|
|
|
|
|
- [x] 指令:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd apps/web && npm run build && npm run check:tokens && npm run test && npm run lint
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Notes
|
|
|
|
|
|
|
2026-08-13 02:22:24 +00:00
|
|
|
|
原先放在 `/app/brands`;2026-08-12 依使用回饋改為獨立 `/app/policy`。舊 `?tab=serviceProfile` 保留轉址,既有資料與 GET/PUT 契約不變。
|
2026-08-03 05:52:02 +00:00
|
|
|
|
|
|
|
|
|
|
### 實作落點
|
|
|
|
|
|
|
|
|
|
|
|
- `apps/web/src/components/radar/ServiceProfileForm.tsx`:服務項目(可增刪)+價格區間、服務區域 chip+可遠端、禁語(一行一條)、案例、FAQ、可接案時間、口吻備註。
|
|
|
|
|
|
- `apps/web/src/components/radar/serviceAreas.ts`:22 個縣市代碼表,與後端 `radar/domain/service_profile.go` 的 `serviceAreaCodes` 一致;後端會拒絕表外代碼,所以不自行擴充。
|
2026-08-13 02:22:24 +00:00
|
|
|
|
- `apps/web/src/pages/BrandsPage.tsx`:只保留品牌庫與產品;舊 `serviceProfile` 查詢參數轉到獨立 Policy 頁。
|
|
|
|
|
|
- `apps/web/src/pages/PolicyPage.tsx`:目前獨立入口;`BrandsPage` 只維護品牌/產品,舊服務檔案分頁連結自動轉址。
|
2026-08-03 05:52:02 +00:00
|
|
|
|
- `apps/web/src/styles/radar.css`:`.hb-radar-row`/`.hb-radar-area-grid`/`.hb-radar-chip.is-active`/`.hb-radar-check`/`.hb-radar-actions`。
|
|
|
|
|
|
|
|
|
|
|
|
### 決策
|
|
|
|
|
|
|
|
|
|
|
|
- **驗證錯誤顯示後端原句**:`apiErrors.ts` 把 `400100` 加進「優先顯示後端 message」的碼單。後端會回 `services[0].name required` 這種指到欄位的訊息,比通用句有用;訊息太短(<24 字元且非中文)時仍退回語言包。
|
|
|
|
|
|
- **價格留空 = 面議**:空字串轉 `undefined` 而非 `0`,否則後端會收到「免費」。
|
|
|
|
|
|
- **禁語一行一條**:禁語本身可能含逗號,用換行切比逗號安全。
|
|
|
|
|
|
- 測試 `ServiceProfileForm.test.tsx` 蓋:首次引導文案、填寫→存檔→重載一致、空價格不送 0、後端驗證訊息原樣顯示。
|