Expand expense categories
This commit is contained in:
parent
fff1ba9c2e
commit
5cc918bcd9
|
|
@ -1,9 +1,13 @@
|
|||
import type { EntryType } from "@cents/domain";
|
||||
import {
|
||||
Ambulance,
|
||||
Apple,
|
||||
Banknote,
|
||||
BatteryCharging,
|
||||
Bike,
|
||||
BookOpen,
|
||||
BriefcaseBusiness,
|
||||
Building2,
|
||||
BusFront,
|
||||
CarTaxiFront,
|
||||
ChartNoAxesCombined,
|
||||
|
|
@ -11,17 +15,26 @@ import {
|
|||
Coffee,
|
||||
CookingPot,
|
||||
Cookie,
|
||||
Crown,
|
||||
CupSoda,
|
||||
Droplets,
|
||||
Dumbbell,
|
||||
FileText,
|
||||
Flame,
|
||||
Fuel,
|
||||
Gamepad2,
|
||||
Gauge,
|
||||
Gift,
|
||||
GraduationCap,
|
||||
HandCoins,
|
||||
Handshake,
|
||||
HeartPulse,
|
||||
Hospital,
|
||||
Hotel,
|
||||
House,
|
||||
Music2,
|
||||
ParkingCircle,
|
||||
Pill,
|
||||
Plane,
|
||||
ReceiptText,
|
||||
RotateCcw,
|
||||
|
|
@ -32,10 +45,15 @@ import {
|
|||
Shirt,
|
||||
Smartphone,
|
||||
Soup,
|
||||
Sparkles,
|
||||
Stethoscope,
|
||||
Syringe,
|
||||
Ticket,
|
||||
TrainFront,
|
||||
Utensils,
|
||||
WalletCards,
|
||||
Wifi,
|
||||
Zap,
|
||||
type LucideIcon,
|
||||
} from "@lucide/vue";
|
||||
|
||||
|
|
@ -75,6 +93,7 @@ export const categories: Record<EntryType, Category[]> = {
|
|||
{ id: "coffee", label: "咖啡", color: "#9b6a48", tint: "#f8eee6", icon: Coffee },
|
||||
{ id: "snacks", label: "零食", color: "#c98535", tint: "#fff4e5", icon: Cookie },
|
||||
{ id: "drinks", label: "饮品", color: "#2d8f9e", tint: "#eaf8fa", icon: CupSoda },
|
||||
{ id: "fruit", label: "水果", color: "#df6345", tint: "#fff0eb", icon: Apple },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -85,23 +104,14 @@ export const categories: Record<EntryType, Category[]> = {
|
|||
icon: BusFront,
|
||||
children: [
|
||||
{ id: "taxi", label: "打车", color: "#3478e5", tint: "#edf4ff", icon: CarTaxiFront },
|
||||
{ id: "public-transit", label: "公交地铁", color: "#2563c7", tint: "#edf4ff", icon: Ticket },
|
||||
{ id: "public-transit", label: "公交", color: "#2563c7", tint: "#edf4ff", icon: BusFront },
|
||||
{ id: "subway", label: "地铁", color: "#5368bd", tint: "#eef1fb", icon: TrainFront },
|
||||
{ id: "train", label: "火车", color: "#4869b1", tint: "#eef2fb", icon: TrainFront },
|
||||
{ id: "cycling", label: "骑行", color: "#168c87", tint: "#e8f8f6", icon: Bike },
|
||||
{ id: "fuel", label: "加油", color: "#6f6b58", tint: "#f3f2ed", icon: Fuel },
|
||||
{ id: "charging", label: "充电", color: "#2b8a74", tint: "#e8f7f2", icon: BatteryCharging },
|
||||
{ id: "parking", label: "停车", color: "#4f7190", tint: "#edf3f7", icon: ParkingCircle },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "daily",
|
||||
label: "日用",
|
||||
color: "#1a9b62",
|
||||
tint: "#eaf9f1",
|
||||
icon: ShoppingBasket,
|
||||
children: [
|
||||
{ id: "groceries", label: "杂货", color: "#1a9b62", tint: "#eaf9f1", icon: ShoppingBasket },
|
||||
{ id: "digital", label: "数码", color: "#52606f", tint: "#eff2f5", icon: Smartphone },
|
||||
{ id: "home", label: "家居", color: "#2b8a74", tint: "#e8f7f2", icon: House },
|
||||
{ id: "highway", label: "高速", color: "#697970", tint: "#f0f4f2", icon: Gauge },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -112,6 +122,9 @@ export const categories: Record<EntryType, Category[]> = {
|
|||
icon: ShoppingBag,
|
||||
children: [
|
||||
{ id: "clothing", label: "服饰", color: "#b14e79", tint: "#faeef4", icon: Shirt },
|
||||
{ id: "groceries", label: "杂货", color: "#1a9b62", tint: "#eaf9f1", icon: ShoppingBasket },
|
||||
{ id: "digital", label: "数码", color: "#52606f", tint: "#eff2f5", icon: Smartphone },
|
||||
{ id: "home", label: "家居", color: "#2b8a74", tint: "#e8f7f2", icon: House },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -124,9 +137,37 @@ export const categories: Record<EntryType, Category[]> = {
|
|||
{ id: "games", label: "游戏", color: "#7958b3", tint: "#f3effb", icon: Gamepad2 },
|
||||
{ id: "movies", label: "电影", color: "#a74d65", tint: "#faeef2", icon: Clapperboard },
|
||||
{ id: "music", label: "音乐", color: "#4f70aa", tint: "#edf2fa", icon: Music2 },
|
||||
{ id: "massage", label: "按摩", color: "#9b678f", tint: "#f8eef5", icon: Sparkles },
|
||||
{ id: "sports", label: "运动", color: "#2f8768", tint: "#eaf7f1", icon: Dumbbell },
|
||||
{ id: "tickets", label: "门票", color: "#b57a0e", tint: "#fff7dd", icon: Ticket },
|
||||
{ id: "hotel", label: "酒店", color: "#526a78", tint: "#edf2f4", icon: Hotel },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "social",
|
||||
label: "社交",
|
||||
color: "#c35f76",
|
||||
tint: "#faeef2",
|
||||
icon: Handshake,
|
||||
children: [
|
||||
{ id: "red-packet", label: "红包", color: "#d94f45", tint: "#fff0ed", icon: WalletCards },
|
||||
{ id: "gift", label: "礼物", color: "#b57a0e", tint: "#fff7dd", icon: Gift },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "health",
|
||||
label: "医疗",
|
||||
color: "#df3f5f",
|
||||
tint: "#fff0f2",
|
||||
icon: HeartPulse,
|
||||
children: [
|
||||
{ id: "pharmacy", label: "药店", color: "#2f8768", tint: "#eaf7f1", icon: Pill },
|
||||
{ id: "outpatient", label: "门诊", color: "#3478a5", tint: "#edf5f9", icon: Stethoscope },
|
||||
{ id: "emergency", label: "急诊", color: "#d94f45", tint: "#fff0ed", icon: Ambulance },
|
||||
{ id: "vaccine", label: "疫苗", color: "#7559d9", tint: "#f2efff", icon: Syringe },
|
||||
{ id: "hospitalization", label: "住院", color: "#526a78", tint: "#edf2f4", icon: Hospital },
|
||||
],
|
||||
},
|
||||
{ id: "health", label: "医疗", color: "#df3f5f", tint: "#fff0f2", icon: HeartPulse },
|
||||
{
|
||||
id: "education",
|
||||
label: "教育",
|
||||
|
|
@ -140,13 +181,19 @@ export const categories: Record<EntryType, Category[]> = {
|
|||
},
|
||||
{
|
||||
id: "bills",
|
||||
label: "账单",
|
||||
label: "缴费",
|
||||
color: "#526a78",
|
||||
tint: "#edf2f4",
|
||||
icon: FileText,
|
||||
children: [
|
||||
{ id: "mobile", label: "话费", color: "#526a78", tint: "#edf2f4", icon: Smartphone },
|
||||
{ id: "internet", label: "宽带网络", color: "#3478a5", tint: "#edf5f9", icon: Wifi },
|
||||
{ id: "water", label: "水费", color: "#2d8f9e", tint: "#eaf8fa", icon: Droplets },
|
||||
{ id: "electricity", label: "电费", color: "#b27a22", tint: "#fff7e7", icon: Zap },
|
||||
{ id: "gas", label: "燃气", color: "#d76a35", tint: "#fff1e9", icon: Flame },
|
||||
{ id: "property-fee", label: "物业", color: "#387b70", tint: "#eaf6f3", icon: Building2 },
|
||||
{ id: "parking-fee", label: "车位费", color: "#4f7190", tint: "#edf3f7", icon: ParkingCircle },
|
||||
{ id: "membership", label: "会员费", color: "#8559cf", tint: "#f4efff", icon: Crown },
|
||||
{ id: "insurance", label: "保险", color: "#477866", tint: "#edf6f2", icon: ShieldCheck },
|
||||
],
|
||||
},
|
||||
|
|
@ -162,13 +209,18 @@ export const categories: Record<EntryType, Category[]> = {
|
|||
],
|
||||
};
|
||||
|
||||
const categoryAliases: Record<string, string> = {
|
||||
daily: "shopping",
|
||||
};
|
||||
|
||||
export function findCategory(categoryId: string): Category | EntryTypeOption | undefined {
|
||||
const entryType = entryTypes.find((type) => type.id === categoryId);
|
||||
const resolvedId = categoryAliases[categoryId] ?? categoryId;
|
||||
const entryType = entryTypes.find((type) => type.id === resolvedId);
|
||||
if (entryType) return entryType;
|
||||
for (const group of Object.values(categories)) {
|
||||
for (const category of group) {
|
||||
if (category.id === categoryId) return category;
|
||||
const child = category.children?.find((item) => item.id === categoryId);
|
||||
if (category.id === resolvedId) return category;
|
||||
const child = category.children?.find((item) => item.id === resolvedId);
|
||||
if (child) return child;
|
||||
}
|
||||
}
|
||||
|
|
@ -176,9 +228,10 @@ export function findCategory(categoryId: string): Category | EntryTypeOption | u
|
|||
}
|
||||
|
||||
export function findCategoryPath(type: EntryType, categoryId: string): Category[] {
|
||||
const resolvedId = categoryAliases[categoryId] ?? categoryId;
|
||||
for (const category of categories[type]) {
|
||||
if (category.id === categoryId) return [category];
|
||||
const child = category.children?.find((item) => item.id === categoryId);
|
||||
if (category.id === resolvedId) return [category];
|
||||
const child = category.children?.find((item) => item.id === resolvedId);
|
||||
if (child) return [category, child];
|
||||
}
|
||||
return [];
|
||||
|
|
|
|||
22
docs/分类体系.md
22
docs/分类体系.md
|
|
@ -21,12 +21,12 @@
|
|||
| --- | --- | --- |
|
||||
| 1 | 餐饮 | `food` |
|
||||
| 2 | 交通 | `transport` |
|
||||
| 3 | 日用 | `daily` |
|
||||
| 4 | 购物 | `shopping` |
|
||||
| 5 | 娱乐 | `entertainment` |
|
||||
| 3 | 购物 | `shopping` |
|
||||
| 4 | 娱乐 | `entertainment` |
|
||||
| 5 | 社交 | `social` |
|
||||
| 6 | 医疗 | `health` |
|
||||
| 7 | 教育 | `education` |
|
||||
| 8 | 账单 | `bills` |
|
||||
| 8 | 缴费 | `bills` |
|
||||
| 9 | 旅行 | `travel` |
|
||||
|
||||
### 收入
|
||||
|
|
@ -50,14 +50,14 @@
|
|||
|
||||
| 二级分类 | 三级分类 |
|
||||
| --- | --- |
|
||||
| 餐饮 | 外卖 `takeout`、堂食 `restaurant`、咖啡 `coffee`、零食 `snacks`、饮品 `drinks` |
|
||||
| 交通 | 打车 `taxi`、公交地铁 `public-transit`、火车 `train`、骑行 `cycling`、加油 `fuel`、停车 `parking` |
|
||||
| 日用 | 杂货 `groceries`、数码 `digital`、家居 `home` |
|
||||
| 购物 | 服饰 `clothing` |
|
||||
| 娱乐 | 游戏 `games`、电影 `movies`、音乐 `music` |
|
||||
| 医疗 | 无 |
|
||||
| 餐饮 | 外卖 `takeout`、堂食 `restaurant`、咖啡 `coffee`、零食 `snacks`、饮品 `drinks`、水果 `fruit` |
|
||||
| 交通 | 打车 `taxi`、公交 `public-transit`、地铁 `subway`、火车 `train`、骑行 `cycling`、加油 `fuel`、充电 `charging`、停车 `parking`、高速 `highway` |
|
||||
| 购物 | 服饰 `clothing`、杂货 `groceries`、数码 `digital`、家居 `home` |
|
||||
| 娱乐 | 游戏 `games`、电影 `movies`、音乐 `music`、按摩 `massage`、运动 `sports`、门票 `tickets`、酒店 `hotel` |
|
||||
| 社交 | 红包 `red-packet`、礼物 `gift` |
|
||||
| 医疗 | 药店 `pharmacy`、门诊 `outpatient`、急诊 `emergency`、疫苗 `vaccine`、住院 `hospitalization` |
|
||||
| 教育 | 书籍 `books`、课程 `courses` |
|
||||
| 账单 | 话费 `mobile`、宽带网络 `internet`、保险 `insurance` |
|
||||
| 缴费 | 话费 `mobile`、宽带网络 `internet`、水费 `water`、电费 `electricity`、燃气 `gas`、物业 `property-fee`、车位费 `parking-fee`、会员费 `membership`、保险 `insurance` |
|
||||
| 旅行 | 无 |
|
||||
|
||||
### 收入
|
||||
|
|
|
|||
Loading…
Reference in New Issue