feat:實作 Coach Portal — 教練後台課程管理

後端:
- Migration:diving_offers 新增 provider_id(nullable FK)
- Migration:users.role ENUM 加入 provider 值
- Migration:diving_offers.spot 改為 nullable
- AuthController:registerProvider business_name 改為選填
- AuthController:updateProviderProfile 補上 certifications / dive_sites / services / facilities / website / social_media
- ProviderOfferController:教練課程 CRUD(index/show/store/update/destroy),實作 provider_id 所有權不變式(404 → 403 兩步驟)

前端(frontend/):
- coachAuth store、coachAxios(獨立於 member auth)
- /coach/* 路由群組 + beforeEach guard
- CoachNavBar、CoachLayout(教練頁隱藏會員 NavBar)
- LoginView、RegisterView、DashboardView(表格 + 刪除確認)
- OfferFormView(新增/編輯共用)、ProfileView

OpenSpec:
- openspec/config.yaml 補入專案 context 與 rules
- 新增 specs:coach-offers-api / coach-portal-ui / provider-auth
- 更新 spec:diving-offers-api 加入 provider_id
- 歸檔:openspec/changes/archive/2026-05-10-coach-portal

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-10 03:34:14 +08:00
parent 550e2fc97a
commit da48a3652d
31 changed files with 1890 additions and 27 deletions
+54 -17
View File
@@ -1,20 +1,57 @@
schema: spec-driven
# Project context (optional)
# This is shown to AI when creating artifacts.
# Add your tech stack, conventions, style guides, domain knowledge, etc.
# Example:
# context: |
# Tech stack: TypeScript, React, Node.js
# We use conventional commits
# Domain: e-commerce platform
context: |
## 專案:CFDivePlatform
潛水課程媒合平台,連結潛水教練(Provider)與學員(Member)。
# Per-artifact rules (optional)
# Add custom rules for specific artifacts.
# Example:
# rules:
# proposal:
# - Keep proposals under 500 words
# - Always include a "Non-goals" section
# tasks:
# - Break tasks into chunks of max 2 hours
## 架構
- 後端:Laravel 11 + SanctumBearer token+ MySQL,跑在 Dockercfdive-app / cfdive-nginx:8080
- 前端:Vue 3 + Vite + Tailwind CSS + Pinia + Vue Router 4 + Axios
- 原始碼在 `frontend/`(同一個 repo
- Docker image: cfdive-frontend,對外 port 5173
- DBMySQL 8Docker),ORM 使用 Eloquent
- 部署:docker-compose`docker-compose up --build` 即可啟動全部服務
## 使用者角色
- `member`:一般會員,瀏覽/搜尋課程,Google OAuth 登入
- `provider`:教練/業者,管理自己的課程(CRUD),使用 ProviderProfile
- `admin`:平台管理員,尚未實作
## 已完成模組
- Member Portal`/`、`/courses`、`/login`、`/register`、`/profile`
- Coach Portal`/coach/*`):登入、註冊、課程 CRUD Dashboard、個人資料
- Diving Offers 公開 API`GET /api/diving-offers`、`GET /api/diving-offers/{id}`
- Provider Auth API`/api/provider/login|register|logout|profile`
- Provider Offers API`/api/provider/offers` CRUD,含 provider_id 所有權驗證)
## 關鍵資料模型
- `users`role enummember / provider / admin),`is_active`
- `provider_profiles`:業者資料(business_name、certifications、dive_sites 等)
- `member_profiles`:會員資料(birthday、gender、emergency_contact 等)
- `diving_offers`:課程(title、location、spot、price、region、tag、badges JSON、provider_id nullable FK
- `subscriptions` / `plans`:訂閱方案(尚未實作 API)
## 前端慣例
- Member 認證:`src/stores/auth.js`localStorage key `token` / `user`
- Coach 認證:`src/stores/coachAuth.js`localStorage key `coach_token` / `coach_user`
- Member Axios`src/api/axios.js`
- Coach Axios`src/api/coachAxios.js`
- Coach 頁面包在 `src/layouts/CoachLayout.vue`(含 CoachNavBar
- 所有 `/coach/*` protected 路由:`meta: { requiresCoach: true }`
## API 回應格式
成功:`{ status: true, message?: "...", data: {...} 或 [...] }`
失敗:`{ status: false, message: "...", errors?: {...} }`
## 尚未實作
- Admin Panel
- 預約/訂單系統
- 金流整合
- 課程圖片上傳
- 教練審核流程
rules:
tasks:
- 後端任務標記 [後端],前端任務標記 [前端],整合測試標記 [整合測試]
- 每個 task 描述應包含具體的檔案路徑或方法名稱
- 手動驗證類 task 放在最後一個 group