昨天我們把記帳 App 搬到雲端,資料全丟進 Firestore 了,今天要解決一個更基礎的需求 → 支出的分類與標籤管理,只有單純輸入金額沒辦法分析錢到底花在哪,所以今天要做一個系統化的「分類功能」
請在既有的 SwiftUI 記帳 App(已整合 Firebase Auth/Firestore)加入「分類與標籤管理」。
=== 資料結構(每位使用者底下)===
- users/{uid}/categories/{categoryId}
fields: id(String), name(String), createdAt(Timestamp)
- users/{uid}/expenses/{expenseId}
fields: id(String), amount(Double), date(Timestamp),
categoryId(String), categoryName(String) // 去正規化,顯示用
=== 功能 ===
1) 類別 CRUD
- 類別頁面:列表 + 新增(輸入 name)+ 重新命名 + 刪除
- 寫入路徑一律包含目前登入者 uid:users/{uid}/categories
- 刪除保護:若此類別被任何 expense 使用,禁止刪除並提示(可先以查詢 count > 0 判斷)
2) 新增支出(ContentView)
- 顯示 Picker 載入使用者的所有 categories,必選一個
- 新增時同時寫入 categoryId 與 categoryName(從選單當下的 name 帶入)
- 列表顯示:日期 | $金額 | 類別名稱(直接用 categoryName 欄位)
3) 監聽/狀態
- categories 與 expenses 皆用 onSnapshot 監聽,保持即時
- 類別改名時,同步批次更新該使用者底下所有對應 expenses 的 categoryName(用 batched write)
4) UI/體驗
- 新增類別彈出視窗(TextField + 確認/取消)
- 類別列表支援 swipe actions(Rename / Delete)
- 新增支出時,若沒有任何類別→顯示引導「先新增一個類別」
5) 錯誤處理
- 無登入(無 uid)→ 不讀不寫,顯示登入提示
- Firestore 錯誤以 Alert 呈現
6) 型別/服務
- struct Category: Identifiable, Codable { id, name, createdAt }
- CategoryStore:observeCategories(), add(name), rename(id,newName), delete(id), isInUse(id) -> Bool
- 既有 ExpenseStore:add(...) 需接受 category 物件,寫入 categoryId & categoryName
7) 測試與遷移
- 若已有舊 expenses 但沒有 categoryId/categoryName,第一次載入時顯示導引,禁止新增直到使用者至少建立 1 個類別
我的程式碼放在這裡:2025ithome-ExpenseTracker
Day 6 要繼續加強這個統計功能:加上「日期篩選」→ 只看本月 or 上個月支出,讓圖表可以切換顯示不同時間範圍,這樣就能變成一個真正的「財務報告」小工具,不只是流水帳