@@ -22,13 +22,14 @@ import {
2222 Legend ,
2323 DoughnutController
2424} from ' chart.js'
25+ import { useCategories , type CategoryKey } from ' ../../composables/useCategories'
2526
2627Chart .register (ArcElement , Title , Tooltip , Legend , DoughnutController )
2728
2829interface Expense {
2930 id: string
3031 amount: number
31- category: string
32+ category: CategoryKey
3233 date: string
3334 note? : string
3435}
@@ -41,13 +42,7 @@ const props = defineProps<Props>()
4142const chartRef = ref <HTMLCanvasElement >()
4243let chart: Chart | null = null
4344
44- const categoryNames: Record <string , string > = {
45- Food: ' 餐饮' ,
46- Transport: ' 交通' ,
47- Shopping: ' 购物' ,
48- Entertainment: ' 娱乐' ,
49- Other: ' 其他'
50- }
45+ const { getCategoryName, getCategoryChartColor } = useCategories ()
5146
5247const formatAmount = (amount : number ) => {
5348 return new Intl .NumberFormat (' zh-CN' , {
@@ -57,7 +52,7 @@ const formatAmount = (amount: number) => {
5752}
5853
5954const categoryBreakdown = computed (() => {
60- const breakdown: Record <string , { amount: number ; count: number ; percentage: number }> = {}
55+ const breakdown: Record <CategoryKey , { amount: number ; count: number ; percentage: number }> = {} as any
6156
6257 props .expenses .forEach (expense => {
6358 if (! breakdown [expense .category ]) {
@@ -69,14 +64,16 @@ const categoryBreakdown = computed(() => {
6964
7065 const total = props .expenses .reduce ((sum , exp ) => sum + exp .amount , 0 )
7166 Object .keys (breakdown ).forEach (category => {
72- breakdown [category ].percentage = total > 0 ? (breakdown [category ].amount / total ) * 100 : 0
67+ const cat = category as CategoryKey
68+ breakdown [cat ].percentage = total > 0 ? (breakdown [cat ].amount / total ) * 100 : 0
7369 })
7470
75- const sortedBreakdown: Record <string , any > = {}
71+ // Sort by amount descending
72+ const sortedBreakdown: Record <CategoryKey , any > = {} as any
7673 Object .entries (breakdown )
7774 .sort (([,a ], [,b ]) => b .amount - a .amount )
7875 .forEach (([category , data ]) => {
79- sortedBreakdown [category ] = data
76+ sortedBreakdown [category as CategoryKey ] = data
8077 })
8178
8279 return sortedBreakdown
@@ -87,18 +84,18 @@ const total = computed(() => props.expenses.reduce((sum, exp) => sum + exp.amoun
8784const createChart = () => {
8885 if (! chartRef .value ) return
8986
90- const categories = Object .keys (categoryBreakdown .value )
87+ const categories = Object .keys (categoryBreakdown .value ) as CategoryKey []
9188 const amounts = categories .map (cat => categoryBreakdown .value [cat ].amount )
92- const colors = categories .map (cat => {
93- const colorMap : Record < string , string > = {
94- Food: ' #FF9800 ' ,
95- Transport: ' #2196F3 ' ,
96- Shopping: ' #E91E63 ' ,
97- Entertainment: ' #9C27B0 ' ,
98- Other: ' #607D8B '
89+ const colors = categories .map (cat => getCategoryChartColor ( cat ))
90+
91+ // Don't create chart if no data
92+ if ( categories . length === 0 || amounts . every ( amount => amount === 0 )) {
93+ if ( chart ) {
94+ chart . destroy ()
95+ chart = null
9996 }
100- return colorMap [ cat ] || ' #607D8B '
101- })
97+ return
98+ }
10299
103100 if (chart ) {
104101 chart .destroy ()
@@ -107,7 +104,7 @@ const createChart = () => {
107104 chart = new Chart (chartRef .value , {
108105 type: ' doughnut' ,
109106 data: {
110- labels: categories .map (cat => categoryNames [ cat ] ),
107+ labels: categories .map (cat => getCategoryName ( cat ) ),
111108 datasets: [{
112109 data: amounts ,
113110 backgroundColor: colors ,
0 commit comments