Files
CFDivePlatform/openspec/changes/archive/2026-05-10-member-portal-mvp/tasks.md
T
a620906209 550e2fc97a feat:實作 Member Portal MVP 前端與後端整合
後端:
- 新增 DivingOffer Model / DivingOfferController(列表+詳情 API,支援搜尋/篩選/分頁)
- 修正 Google OAuth callback 改為 redirect 至前端(SocialAuthController)
- 新增 config/cors.php 允許前端 origin
- .gitignore 新增 frontend/ 排除規則

前端(frontend/):
- Vue 3 + Vite + Tailwind CSS + Pinia + Vue Router
- 頁面:首頁、課程列表、課程詳情、登入、註冊、個人資料、OAuth callback
- 整合至 Docker(multi-stage build,nginx 靜態服務於 port 5173)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-10 01:41:28 +08:00

5.6 KiB
Raw Blame History

1. [後端] 環境與 CORS 設定

  • 1.1 在 .env 新增 FRONTEND_URL=http://localhost:5173GOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRETGOOGLE_REDIRECT_URI=http://localhost:80/api/auth/google/callback
  • 1.2 執行 php artisan config:publish cors 建立 config/cors.php,設定 allowed_origins=[FRONTEND_URL]allowed_methodsallowed_headerssupports_credentials=false(參考 design.md Contract 3
  • 1.3 確認 bootstrap/app.php(或 app/Http/Kernel.php)已啟用 HandleCors middleware

2. [後端] 修正 Google OAuth Callback

  • 2.1 修改 SocialAuthController::handleGoogleCallback():成功時改為 redirect(env('FRONTEND_URL') . '/auth/callback?token=' . $token)
  • 2.2 修改 catch 區塊:失敗時改為 redirect(env('FRONTEND_URL') . '/login?error=oauth_failed')
  • 2.3 手動測試 OAuth 流程:點擊 Google 登入後確認瀏覽器最終落在 :5173/auth/callback?token=...

3. [後端] Diving Offers API

  • 3.1 更新 DivingOffer Model:設定 $fillable$tablebadges 欄位加上 $casts = ['badges' => 'array'] 自動 JSON decode
  • 3.2 建立 DivingOfferController,實作 index() 方法(支援 q / region / tag 篩選,分頁預設 12 筆,max 50)
  • 3.3 實作 show($id) 方法:找不到時回傳 { "status": false, "message": "課程不存在" }HTTP 404
  • 3.4 在 routes/api.php 新增公開路由:GET /diving-offersGET /diving-offers/{id}
  • 3.5 用 Postman 驗證:列表(含 q / region / tag / 分頁)、詳情、404 情境,確認 response 結構符合 design.md Contract 1

4. [前端] 專案初始化

  • 4.1 在 Laravel repo 外建立新目錄 cf-dive-frontend,執行 npm create vite@latest . -- --template vue
  • 4.2 安裝依賴:npm install,再安裝 vue-router@4 pinia axios
  • 4.3 安裝並設定 Tailwind CSStailwindcss postcss autoprefixer,初始化 tailwind.config.js
  • 4.4 建立 .env 文件,設定 VITE_API_URL=http://localhost:80
  • 4.5 建立 src/api/axios.js:設定 Axios instancebase URL 讀自 import.meta.env.VITE_API_URLrequest interceptor 讀 localStorage token 並附加 Authorization: Bearer <token>
  • 4.6 建立 src/stores/auth.jsPinia store 管理 usertokenisLoggedIninit() 從 localStorage 還原狀態
  • 4.7 設定 Vue Routersrc/router/index.js):定義所有路由(含 /auth/callback),/profile 加上 beforeEach navigation guard(未登入導向 /login
  • 4.8 在 App.vue 呼叫 authStore.init(),並加入 <RouterView>
  • 4.9 執行 npm run dev,確認開發環境正常啟動無錯誤

5. [前端] Layout 與共用組件

  • 5.1 建立 src/components/NavBar.vue:顯示 logo、「探索課程」連結,已登入顯示「個人資料」和「登出」,未登入顯示「登入」和「註冊」
  • 5.2 建立 src/components/CourseCard.vue:接收 offer 資料,顯示標題、地點、價格、評分、標籤

6. [前端] 首頁

  • 6.1 建立 src/views/HomeView.vueHero section(平台名稱、簡介)+ 「探索課程」CTA 按鈕,點擊導向 /courses

7. [前端] 課程列表頁

  • 7.1 建立 src/views/CoursesView.vue,掛載時呼叫 GET /api/diving-offers,渲染 CourseCard 列表
  • 7.2 新增搜尋框:輸入後按 Enter 或點搜尋重新呼叫 API(帶 q 參數)
  • 7.3 新增地區下拉選單:選擇後以 region 參數重新呼叫 API
  • 7.4 處理無結果狀態:顯示「找不到符合的課程」提示

8. [前端] 課程詳情頁

  • 8.1 建立 src/views/CourseDetailView.vue,掛載時呼叫 GET /api/diving-offers/:id
  • 8.2 顯示課程完整資訊:標題、地點、景點、價格、評分、評論數、描述、徽章(badges 陣列)、標籤
  • 8.3 處理 404 情境:顯示「課程不存在」並提供「返回列表」按鈕

9. [前端] 認證頁面

  • 9.1 建立 src/views/LoginView.vueemail/password 表單,送出呼叫 POST /api/member/login,成功存 token + user 至 Pinia 並導向 /courses,失敗顯示錯誤訊息
  • 9.2 在 LoginView.vue 加入「以 Google 登入」按鈕:點擊執行 window.location.href = VITE_API_URL + '/api/auth/google/redirect'
  • 9.3 建立 src/views/AuthCallbackView.vue(路由 /auth/callback):讀取 ?token= query param → 存入 Pinia + localStorage → 呼叫 history.replaceState 清除 URL token → 導向 /courses;若 ?error=oauth_failed 則導向 /login 並顯示錯誤提示
  • 9.4 建立 src/views/RegisterView.vuename / email / password / password_confirmation 表單,送出呼叫 POST /api/member/register,成功導向 /login 並顯示成功提示,失敗顯示錯誤

10. [前端] 會員個人資料頁

  • 10.1 建立 src/views/ProfileView.vue,掛載時呼叫 GET /api/member/profile,顯示姓名、email、生日、性別、地址、緊急聯絡人
  • 10.2 實作編輯表單:使用者修改後點擊「儲存」呼叫 PUT /api/member/profile,成功顯示「資料已更新」提示

11. [整合測試] 端對端驗證

  • 11.1 驗證訪客流程:首頁 → 課程列表(搜尋/篩選)→ 課程詳情(無需登入)
  • 11.2 驗證 Email 認證流程:註冊 → 登入 → 個人資料 → 登出
  • 11.3 驗證 Google OAuth 流程:點擊 Google 登入 → 同意 → 回到前端 /auth/callback → 自動存 token → 導向課程列表
  • 11.4 驗證 navigation guard:未登入直接訪問 /profile 自動跳轉至 /login
  • 11.5 驗證 CORS:確認 Network tab 無 CORS 錯誤,所有 API 請求正常回應