ad2c05779d
後端: - AdminStatsController:總會員/教練/課程數統計 API - AdminUserController:會員與教練列表、詳情、啟用/停用、教練驗證(toggle 反轉語意) - AdminOfferController:全平台課程列表與刪除 - routes/api.php:新增 /api/admin/stats、members、providers、offers 等路由 前端(frontend/): - adminAuth store、adminAxios(第三套獨立認證) - /admin/* 路由群組 + requiresAdmin guard - AdminNavBar、AdminLayout - App.vue:isCoachPage → isBackofficePage(/coach/* 和 /admin/* 皆隱藏會員 NavBar) - LoginView、DashboardView(統計卡片) - MembersView、ProvidersView(含驗證操作)、OffersView(含刪除確認) OpenSpec: - 新增 specs:admin-auth / admin-user-management / admin-offer-management / admin-stats / admin-panel-ui - 歸檔:openspec/changes/archive/2026-05-10-admin-panel Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
81 lines
5.5 KiB
Markdown
81 lines
5.5 KiB
Markdown
## 1. [後端] Admin Auth — 確認現有方法可用
|
||
|
||
- [x] 1.1 `loginAdmin()` ✅ 直接可用,確認 role=admin 驗證邏輯正確
|
||
- [x] 1.2 `logoutAdmin()` ✅ 直接可用,不需改動
|
||
- [x] 1.3 `adminProfile()` ✅ 直接可用,不需改動
|
||
- [x] 1.4 用 Postman 建立測試用 admin 帳號:`docker exec cfdive-app php artisan tinker`,建立 role=admin 的 User + AdminProfile,測試 login → profile → logout
|
||
|
||
## 2. [後端] AdminStatsController
|
||
|
||
- [x] 2.1 建立 `AdminStatsController`,實作 `index()`:驗證 role=admin,查詢 `User::where('role','member')->count()`、`User::where('role','provider')->count()`、`DivingOffer::count()`,回傳統計數據
|
||
- [x] 2.2 在 `routes/api.php` 的 admin middleware group 新增 `GET /stats` 路由
|
||
|
||
## 3. [後端] AdminUserController
|
||
|
||
- [x] 3.1 建立 `AdminUserController`,宣告 private `checkAdmin()` helper(驗證 role=admin,不符回傳 403)
|
||
- [x] 3.2 實作 `members(Request $request)`:搜尋 role=member 用戶(q 參數 LIKE name/email),load memberProfile,分頁 15 筆
|
||
- [x] 3.3 實作 `member(int $id)`:find role=member 用戶,不存在回 404,load memberProfile 後回傳
|
||
- [x] 3.4 實作 `toggleMemberActive(int $id)`:find → 404,反轉 is_active,回傳新狀態與對應訊息
|
||
- [x] 3.5 實作 `providers(Request $request)`:同 members,查 role=provider,load providerProfile
|
||
- [x] 3.6 實作 `provider(int $id)`:同 member,查 role=provider,load providerProfile
|
||
- [x] 3.7 實作 `toggleProviderActive(int $id)`:同 toggleMemberActive,查 role=provider
|
||
- [x] 3.8 實作 `toggleProviderVerified(int $id)`:find role=provider → 404,取得 providerProfile,反轉 is_verified,儲存,回傳新狀態
|
||
- [x] 3.9 在 `routes/api.php` admin group 新增路由:
|
||
- `GET /members`、`GET /members/{id}`、`PUT /members/{id}/toggle-active`
|
||
- `GET /providers`、`GET /providers/{id}`、`PUT /providers/{id}/toggle-active`、`PUT /providers/{id}/toggle-verified`
|
||
|
||
## 4. [後端] AdminOfferController
|
||
|
||
- [x] 4.1 建立 `AdminOfferController`,實作 `index()`:驗證 admin,搜尋所有課程(q 參數 LIKE title/location),分頁 15 筆
|
||
- [x] 4.2 實作 `destroy(int $id)`:find → 404,刪除,回傳 200
|
||
- [x] 4.3 在 routes 新增 `GET /offers`、`DELETE /offers/{id}`
|
||
|
||
## 5. [前端] Admin 基礎設施
|
||
|
||
- [x] 5.1 建立 `frontend/src/stores/adminAuth.js`:管理 `admin_token` / `admin_user`,實作 `init()` / `setAuth()` / `logout()`
|
||
- [x] 5.2 建立 `frontend/src/api/adminAxios.js`:獨立 Axios instance,request interceptor 讀 `admin_token`
|
||
- [x] 5.3 在 `frontend/src/router/index.js` 新增 `/admin/*` 路由:login(public)+ dashboard / members / providers / offers / profile(requiresAdmin)
|
||
- [x] 5.4 router `beforeEach` 加入 `requiresAdmin` guard,未登入導向 `/admin/login`
|
||
- [x] 5.5 在 `App.vue` 的 `onMounted` 加入 `adminAuth.init()`,並擴充 `isCoachPage` → `isBackofficePage`(涵蓋 `/coach/*` 和 `/admin/*`),會員 NavBar 在這兩個路徑下都不顯示
|
||
|
||
## 6. [前端] Admin Layout 與導覽
|
||
|
||
- [x] 6.1 建立 `frontend/src/components/AdminNavBar.vue`:顯示管理員姓名、「儀表板」、「會員管理」、「教練管理」、「課程管理」連結與登出按鈕
|
||
- [x] 6.2 建立 `frontend/src/layouts/AdminLayout.vue`:包含 AdminNavBar + `<RouterView>`
|
||
|
||
## 7. [前端] 管理員登入頁
|
||
|
||
- [x] 7.1 建立 `frontend/src/views/admin/LoginView.vue`:email/password 表單,送出呼叫 `POST /api/admin/login`,成功存 token 至 adminAuth store 並導向 `/admin/dashboard`,失敗顯示錯誤
|
||
|
||
## 8. [前端] 儀表板
|
||
|
||
- [x] 8.1 建立 `frontend/src/views/admin/DashboardView.vue`:掛載時呼叫 `GET /api/admin/stats`,以三個數字卡片顯示總會員數、總教練數、總課程數
|
||
|
||
## 9. [前端] 會員管理頁
|
||
|
||
- [x] 9.1 建立 `frontend/src/views/admin/MembersView.vue`:掛載時呼叫 `GET /api/admin/members`,以表格顯示姓名、email、帳號狀態(啟用/停用 badge)
|
||
- [x] 9.2 新增搜尋框,輸入後按 Enter 重新呼叫 API(帶 q 參數)
|
||
- [x] 9.3 每列新增啟用/停用按鈕,呼叫 `PUT /api/admin/members/{id}/toggle-active`,成功後更新該列狀態
|
||
|
||
## 10. [前端] 教練管理頁
|
||
|
||
- [x] 10.1 建立 `frontend/src/views/admin/ProvidersView.vue`:掛載時呼叫 `GET /api/admin/providers`,顯示姓名、email、工作室名稱、驗證狀態、帳號狀態
|
||
- [x] 10.2 新增搜尋框
|
||
- [x] 10.3 每列新增啟用/停用按鈕(呼叫 toggle-active)與驗證/取消驗證按鈕(呼叫 toggle-verified),成功後更新對應欄位
|
||
|
||
## 11. [前端] 課程管理頁
|
||
|
||
- [x] 11.1 建立 `frontend/src/views/admin/OffersView.vue`:掛載時呼叫 `GET /api/admin/offers`,顯示課程標題、地點、地區、價格、provider_id
|
||
- [x] 11.2 新增搜尋框
|
||
- [x] 11.3 每列新增刪除按鈕:顯示確認 dialog,確認後呼叫 `DELETE /api/admin/offers/{id}`,成功後重新載入列表
|
||
|
||
## 12. [整合測試] 端對端驗證
|
||
|
||
- [x] 12.1 驗證管理員登入流程:tinker 建立 admin 帳號 → 登入 → 顯示 AdminNavBar → 登出
|
||
- [x] 12.2 驗證 Dashboard 統計數據正確顯示
|
||
- [x] 12.3 驗證會員管理:搜尋 → 停用 → 確認帳號無法登入 → 重新啟用
|
||
- [x] 12.4 驗證教練驗證:切換 is_verified → 確認 /coach/profile 顯示狀態更新
|
||
- [x] 12.5 驗證課程刪除:Admin 刪除課程 → 確認 /courses 列表消失
|
||
- [x] 12.6 驗證 route guard:未登入訪問 `/admin/dashboard` 自動跳轉 `/admin/login`
|
||
- [x] 12.7 驗證 `/admin/*` 路由不顯示會員 NavBar
|