traveling-around-the-world

一個以 React 為核心的單頁式應用程式SPA用來記錄自己走訪過的國家、城市與時間軸。初期資料儲存在瀏覽器 LocalStorage並預留後端 Express + MongoDB 的擴充架構,後續可平滑升級成多人同步的雲端服務。

Monorepo 結構

traveling-around-the-world/
├─ client/   # Vite + React + TS 的前端 SPA
├─ server/   # Express + MongoDB (未來) API 服務
└─ shared/   # 前後端共用的型別定義
  • client 預設採 LocalStorage 擷取資料,並透過 VisitProvider 可快速切換成 API 模式。
  • server 已放好 Express + Mongoose 架構與 RESTful routes只需接上 MongoDB 並啟動即可提供資料。
  • shared 放行程型別 VisitDto,讓前後端保持相同資料契約。

前端client

技術與工具

  • Vite + React 18 + TypeScript
  • Material UI + Emotion 建構一致的 UI 與主題
  • React Router 規劃 SPA 路由
  • Zustand 追蹤 UI 狀態(訪問表單 Modal 與初始座標)
  • React Query 統一處理資料讀寫與快取
  • React Hook Form + Zod 表單驗證
  • react-leaflet + OpenStreetMap 圖資,支援地圖點擊新增足跡
  • i18next 支援中英文切換,分類與設定等字串同步集中管理

模組切分

  • features/mapLeaflet 地圖、點擊事件、旅遊標記
  • features/visits資料型別、LocalStorage Repository、React Query hooks、統計卡片與表單元件
  • features/categories:旅程分類 CRUD、React Query 與 sidebar 管理介面
  • components/layoutMUI AppBar + Drawer 布局、語言切換等元件
  • stateZustand store 控制訪問建立/編輯的 Modal
  • components/overlay/VisitModal:以 Modal 呈現足跡表單,必須先點擊地圖右下角的 + 漂浮按鈕啟用定位,再第二次點擊地圖開啟表單
  • components/overlay/NavControlsDialogApp Bar 右上角的「更多」按鈕會開啟的快速操作 Modal語言、分類切換、相關連結

LocalStorage → API 的切換

  • 預設 VisitProvider mode="local" 會載入 localVisitRepository
  • 改為 mode="api" 並設定 apiBaseUrl 後,就會改用 VisitApiClient 透過 REST API 存取。
  • Vite proxy 已轉發 /apihttp://localhost:4000,未來後端啟動後無需改動前端呼叫。

旅程分類管理

  • 所有旅程可指定分類,未指定時會自動歸入「未分類」。
  • 側邊欄可透過 chip 快速篩選「全部 / 未分類 / 自訂分類」。
  • 在「管理分類」清單可新增、重新命名或刪除分類;刪除時相關旅程會回到「未分類」。
  • 當前分類會記錄在 LocalStorage在地圖右下角新增旅程時會自動帶入。

快速操作面板

  • App Bar 右上角改為「更多」圖示,點擊後會開啟 Modal。
  • Modal 集中展示語言切換、目前分類切換以及開發相關連結OpenStreetMap、React Leaflet
  • 便於未來擴充更多設定選項,而不把 App Bar 擠得太滿。

PWA 支援

  • 新增 Web App Manifestclient/public/manifest.webmanifest)與 service worker 註冊,可在行動裝置安裝為獨立 App。
  • 透過 vite-plugin-pwa 自動產生快取策略,支援離線瀏覽與版號自動更新。
  • 內建 icons/icon-192.svgicons/icon-512.svg,可於日後替換為專屬圖示。

多語系支援

  • 透過 react-i18next 提供繁體中文與英文,語系檔位於 client/src/locales/
  • 右上角的語言選單 (LanguageSwitcher) 可即時切換語言,並記錄在 LocalStorage 方便下次載入。

開發啟動

  1. 安裝相依套件:cd client && npm install
  2. 啟動開發伺服器:npm run dev
  3. 瀏覽器開啟 http://localhost:5173

注意Leaflet 需要載入 CSS已在 TravelMap 中引入 leaflet/dist/leaflet.css)。

專案建置

  • 推薦將 client/package.jsonbuild 指令改為 "build": "tsc --noEmit && vite build",避免 tsconfig.node.jsonnoEmit 限制造成錯誤。
  • 調整後可執行 npm run build,產出靜態檔案於 client/dist
  • 首次啟用 PWA 時記得在 client 目錄重新執行 npm install,以安裝 vite-plugin-pwa 相依套件。

部署到 Vercel

  1. 先在本地確認 npm run build 可成功(參考上節的建置指令變更)。
  2. 將整個專案推送至 GitHub / GitLab / Bitbucket。
  3. 在 Vercel 建立新專案時:
    • Project Rootclient
    • Build Commandnpm run build
    • Output Directorydist
  4. 連續部署Vercel 會在每次 push default branch、自動建立 preview 的 PR 觸發建置並更新站台。
  5. 若後續要加上環境變數,可在 Vercel 專案設定內補上即可。

Docker Compose 啟動

若想直接以容器方式啟動整個堆疊MongoDB + Node API + Nginx 前端):

  1. 建立映像:docker compose build
  2. 啟動服務:docker compose up -d
  3. 前端:http://localhost:3000
  4. APIhttp://localhost:4000

預設前端仍採 LocalStorage。如果要改用 API 資料來源,請在 client/src/app/App.tsxVisitProvider mode="local" 改成 mode="api"

後端server

技術堆疊

  • Express 4
  • Mongoose 8 + MongoDB內建 visit schema資料結構與前端共用
  • Zod 驗證 API 請求 payload
  • Helmet、CORS、Morgan 提供基礎安全與紀錄

架構亮點

  • src/app.ts 建立 Express App、共用中介層、/health 健康檢查
  • src/modules/visits模型、Service、Controller、Router 切分清晰
  • visit.mapper.ts 將 Mongoose Doc 轉成 shared/visit.ts 的 DTO
  • infra/db/mongo.ts 佈建 Mongo 連線抽象

啟動指令

  1. 安裝套件:cd server && npm install
  2. 建立 .env(可複製 .env.example)並設定 MONGODB_URI
  3. 開發模式:npm run dev
  4. 編譯產出:npm run build -> dist/

RESTful 端點:

  • GET /api/visits:取得全部足跡
  • POST /api/visits:新增足跡
  • GET /api/visits/:id
  • PUT /api/visits/:id
  • DELETE /api/visits/:id

共享型別shared

  • shared/visit.ts 定義 Visit DTO前端 Visit 及後端回傳皆採相同結構。
  • Vite 透過 @shared/* alias 匯入,後端則直接使用相對路徑,確保型別同步。

開發流程建議

  1. LocalStorage MVP:僅啟動前端即可使用,點擊地圖開啟表單、資料存在瀏覽器。
  2. 串接 API:建立 MongoDB啟動 npm run dev 後將前端 VisitProvider 切換到 API 模式。
  3. Geocoding:前端已透過 Nominatim 反向地理編碼在點擊地圖時預填國家 / 城市;若需更高配額可在後端建立 Proxy。
  4. 照片/檔案:後端可擴增 S3/Cloudinary 上傳,再於前端 VisitCreateInput 增加檔案欄位。

待辦與下一步

  • 實作 geocoding proxy於點擊地圖後自動填入國家 / 城市
  • 加入使用者認證(如 Auth0 或自建 JWT以支援多人服務
  • 將訪問紀錄導出成時間線或統計圖表D3 / Recharts
  • 建立 Vitest / Jest 單元測試與 React Testing Library 元件測試
  • 規劃 CIGitHub Actions自動執行 linttest
  • 自動化部署流程模板Vercel / GitHub Actions

授權

本專案採用 MIT License詳見 LICENSE

Description
No description provided
Readme MIT 401 KiB
Languages
TypeScript 98.1%
Dockerfile 0.8%
HTML 0.7%
CSS 0.3%
JavaScript 0.1%