Skip to content

About

112-2 智慧雲端商務專題_期末專案

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

38 Commits

Folders and files

Repository files navigation

耐人尋味 FoodSelector · 美食選擇困難救星

一個解決「今天到底吃什麼」的美食探索平台:比 Google Map 更豐富的商品資訊、更好查的篩選,再用隨機挑選店家/菜色幫你戰勝選擇困難。

60 秒看懂: 這是一個 React + Vite 前端 + Lumen (PHP) JWT API 後端 的全端專案。後端來自課堂專案,本次重構補上了完整前端,並修掉後端的權限繞過與壞掉的路由。前端內建 demo 模式(種子資料),npm install && npm run dev 就能完整操作,不需要 PHP、不需要資料庫。

首頁:今天吃什麼?交給命運決定


🖼 產品畫面

探索/篩選 店家頁
探索頁:關鍵字搜尋、分類與價格篩選 店家頁:介紹、營業資訊、菜單
隨機挑選 登入(展示帳號) 手機版
隨機挑選頁 登入頁,附一鍵填入的展示帳號 手機版首頁與底部導覽

🔗 線上展示(GitHub Pages)

https://namecallbob.github.io/FoodSelector/

需先在 repo Settings → Pages → Source 選擇「GitHub Actions」,推送到 main 後由 .github/workflows/deploy-pages.yml 自動建置並發佈。

展示為 demo 模式:使用內建種子資料,不需要 PHP 後端即可完整操作。

展示帳號(登入頁可一鍵填入):

帳號 密碼 角色
binbin binbin 買家
teststore1 teststore1 賣家

上述帳密與 frontend/src/data/seed.js、backend/database/seeders/UserSeeder.php 中的資料皆為公開的示範資料,不是真實憑證。

💡 為什麼做這個

「等一下」「隨便」「都可以」是聚餐時最沒有效率的三句話。Google Map 適合找地點,卻不容易一次看到菜色層級的資訊(單品、價格、人氣)。耐人尋味把資料拉到菜色層級,再加上一個「幫我決定」的隨機轉盤,讓選擇困難有一個出口。

🧱 技術棧

層 技術
前端 React 18、Vite 6、React Router 6、Tailwind CSS v4、shadcn 風格自製元件、lucide-react
後端 PHP 8.1+、Lumen 10、Eloquent、tymon/jwt-auth 2(JWT)、MySQL
測試 Vitest + jsdom(前端)、PHPUnit 10(後端)
CI / 部署 GitHub Actions → GitHub Pages(前端 demo 建置)

🏗 架構

.
├── backend/                 # Lumen (PHP) JWT API
│   ├── app/Http/Controllers # 商品、店家、收藏、隨機、認證
│   ├── app/Http/Middleware  # CorsMiddleware / AuthMiddleware(JWT + RBAC)
│   ├── app/Models           # Eloquent 模型(private / store / product / collect …)
│   ├── database/            # migrations + seeders(含 RBAC 權限種子)
│   ├── routes/web.php       # 路由;受保護路由掛 check.permission:<action>
│   └── tests/               # PHPUnit
├── frontend/                # React + Vite SPA
│   ├── src/lib/api.js       # ★ 資料轉接層:demo(種子)/ live(Lumen API)
│   ├── src/data/seed.js     # demo 模式的種子資料
│   ├── src/pages/           # 首頁 / 探索 / 店家 / 隨機 / 口袋名單 / 登入
│   └── src/components/      # UI kit、卡片、版面
└── .github/workflows/       # GitHub Pages 部署

關鍵設計 — 單一資料轉接層: frontend/src/lib/api.js 是唯一知道「資料從哪來」的檔案。 VITE_API_MODE=demo 時直接讀取種子資料(可離線、可上 GitHub Pages);VITE_API_MODE=live 時改打 Lumen API。 兩條分支回傳相同的資料形狀(連後端「單一商品回傳一元素陣列」這種怪癖也一併模擬),所以頁面元件完全不需要知道目前是哪個模式。

請求流程(live 模式):

Browser ──JWT──> CorsMiddleware ─> AuthMiddleware ─> Controller ─> Eloquent ─> MySQL
                                     │
                                     ├─ token 無效 → 401
                                     └─ 角色缺少該權限 → 403

✨ 功能

  • 首頁:招牌 Hero、美食分類、今日推薦店家、人氣必吃。
  • 探索:關鍵字搜尋、分類與價格篩選,可切換「菜色 / 店家」。
  • 店家頁:介紹、地址/營業時間、標籤、菜單、食客評論,並可「幫我從這家挑一道」。
  • 隨機挑選:轉盤式動畫,隨機抽一家店或一道菜,戰勝選擇困難。
  • 口袋名單:以 localStorage 收藏喜歡的菜色。
  • 響應式(手機底部導覽)、鍵盤可操作、prefers-reduced-motion 友善。

🎨 設計

以 UI/UX 設計系統評估後採「Vibrant & Block-based」風格:開胃紅 #DC2626 + 珊瑚 #F87171 + 暖金 #A16207;字體 Playfair Display(標題)/ Karla(內文),營造餐飲質感。

🚀 本地開發

前端(示範模式,無需後端)

需求:Node.js 20+

cd frontend
npm install
npm run dev          # http://localhost:5173

若要串接真實後端:

cp .env.example .env
# 編輯 frontend/.env
#   VITE_API_MODE=live
#   VITE_API_BASE=http://localhost:8000

後端(Lumen)

需求:PHP 8.1+、Composer、MySQL

cd backend
composer install
cp .env.example .env      # 填入 DB 連線資訊
php artisan jwt:secret    # 產生 JWT_SECRET(不要提交 .env)
php artisan migrate --seed
php -S localhost:8000 -t public

種子資料會建立示範帳號、店家、商品與 RBAC 權限(buyer / seller 角色)。

🧪 測試

前端(Vitest)

cd frontend
npm install
npm test             # vitest run,39 個測試

涵蓋:資料轉接層 demo 分支(搜尋/分類/價格篩選、下架商品不外流、後端形狀模擬、隨機挑選)、 demo 登入流程(錯誤憑證回 401、token 與使用者持久化、登出清除)、種子資料完整性(id 不重複、 外鍵都指得到、每家店都有上架商品)、以及 cn() / formatTWD() 工具函式。

後端(PHPUnit)

cd backend
composer install
./vendor/bin/phpunit

tests/RoutesTest.php 檢查路由表:公開路由都有註冊(包含曾經壞掉的 /token/verify/、/store/search), 每個特權路由都掛上正確的 check.permission:<action> middleware,而公開路由不會誤掛權限。

👀 怎麼看到 UI

三種方式,任選其一:

  1. 直接看截圖 — 上方「產品畫面」區塊。
  2. 本機跑 demo — cd frontend && npm install && npm run dev(不需要後端)。
  3. 本機跑正式建置 — npm run build && npm run preview -- --base /FoodSelector/ (正式建置的 base 是 /FoodSelector/,預覽時要帶上同樣的 base)。

🛠 後端修補(本次)

老框架僅做「優化與補漏」,重點修正:

  • 修補權限中介層的驗證繞過(無效 token 曾被當成通過),正確回傳 401 / 403。
  • 修正壞掉的路由(/token/verify/、/store/search)。
  • 補上缺少的 collect 資料表 migration 與 config/jwt.php。
  • 修正 CollectController@read 未回傳、ProductController 硬編分類/狀態、帳號鎖定字串比對等邏輯漏洞。
  • 重寫種子讓 RBAC 真正可用(原本每個受權限保護的路由都會 403)。
  • 修正前端 live 模式登入時少了斜線的 API 路徑(login → /login)。

🔐 設定與機密

  • backend/.env 與 frontend/.env 皆已列入 .gitignore,不會被提交。
  • 兩邊都提供 .env.example 作為範本;JWT_SECRET 請用 php artisan jwt:secret 自行產生。
  • repo 內出現的帳密(binbin/binbin 等)全部來自種子/示範資料,不是真實憑證。

部署

推送到 main 後由 .github/workflows/deploy-pages.yml 自動建置 frontend/(demo 模式)並發佈到 GitHub Pages。首次需於 repo Settings → Pages → Source 選擇「GitHub Actions」。

授權

後端衍生自 Laravel Lumen 骨架,該骨架採 MIT 授權(見 backend/composer.json)。本 repo 目前尚未附上 LICENSE 檔案。

About

112-2 智慧雲端商務專題_期末專案

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages