Skip to content

Commit 07bd6fd

Browse files
committed
Add daily totals loading and display to ExpenseList
Introduces a new get_daily_totals SQL function and updates HomeView to load daily totals for displayed dates. ExpenseList now receives dailyTotals as a prop and displays the total per day using this data, ensuring accurate daily aggregation even when expenses are paginated or filtered. Types updated to reflect the new prop.
1 parent ef3a5ca commit 07bd6fd

4 files changed

Lines changed: 60 additions & 9 deletions

File tree

db/rpc.sql

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,27 @@ BEGIN
1717
END;
1818
$$ LANGUAGE plpgsql SECURITY DEFINER;
1919

20+
-- 1b. Get daily totals for a list of dates
21+
CREATE OR REPLACE FUNCTION get_daily_totals(
22+
p_user_id UUID,
23+
p_dates DATE[]
24+
) RETURNS TABLE(
25+
date DATE,
26+
total NUMERIC
27+
) AS $$
28+
BEGIN
29+
RETURN QUERY
30+
SELECT
31+
e.date,
32+
COALESCE(SUM(e.amount), 0) as total
33+
FROM expenses e
34+
WHERE e.user_id = p_user_id
35+
AND e.date = ANY(p_dates)
36+
GROUP BY e.date
37+
ORDER BY e.date DESC;
38+
END;
39+
$$ LANGUAGE plpgsql SECURITY DEFINER;
40+
2041
-- 2. Get category breakdown for a specific period
2142
CREATE OR REPLACE FUNCTION get_category_breakdown(
2243
p_user_id UUID,

src/components/ExpenseList.vue

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,9 @@
1717
<h3 class="text-subtitle-1 font-weight-medium text-medium-emphasis">
1818
{{ group.dateLabel }}
1919
</h3>
20-
<div class="d-flex align-center">
21-
<span class="text-body-2 text-medium-emphasis mr-3">
22-
{{ formatAmount(group.total) }}
23-
</span>
24-
<v-divider />
25-
</div>
20+
<span class="text-body-2 text-medium-emphasis">
21+
{{ formatAmount(group.total) }}
22+
</span>
2623
</div>
2724

2825
<!-- Expenses for this date -->
@@ -195,12 +192,11 @@ const groupedExpenses = computed(() => {
195192
date: dateKey,
196193
dateLabel: formatDateLabel(dateKey),
197194
expenses: [],
198-
total: 0
195+
total: props.dailyTotals?.[dateKey] || 0 // Use daily total from prop
199196
})
200197
}
201198
const group = groups.get(dateKey)!
202199
group.expenses.push(expense)
203-
group.total += expense.amount
204200
})
205201
206202
// Convert Map to Array and maintain date order (already sorted from database)

src/components/HomeView.vue

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
<template v-else>
99
<TodaySummary :expenses="expenses" />
10-
<ExpenseList :expenses="expenses" @edit="openFormForEdit" @delete="handleDelete" />
10+
<ExpenseList :expenses="expenses" :daily-totals="dailyTotals" @edit="openFormForEdit" @delete="handleDelete" />
1111

1212
<!-- Load More Button -->
1313
<div v-if="hasMoreExpenses" class="text-center py-4">
@@ -55,6 +55,7 @@ const { openFormForEdit } = useExpenseForm()
5555
const { showError } = useToast()
5656
5757
const expenses = ref<Expense[]>([])
58+
const dailyTotals = ref<Record<string, number>>({})
5859
const currentPage = ref(0)
5960
const pageSize = 5
6061
const hasMoreExpenses = ref(true)
@@ -109,6 +110,37 @@ const loadExpenses = async (reset = false) => {
109110
if (reset) {
110111
initialLoading.value = false
111112
}
113+
114+
// Load daily totals after loading expenses
115+
await loadDailyTotals()
116+
}
117+
118+
// Load daily totals for the dates in the current expense list
119+
const loadDailyTotals = async () => {
120+
if (!user.value || expenses.value.length === 0) return
121+
122+
// Get unique dates from loaded expenses
123+
const uniqueDates = [...new Set(expenses.value.map(e => e.date))]
124+
125+
try {
126+
const { data, error } = await supabase.rpc('get_daily_totals', {
127+
p_user_id: user.value.id,
128+
p_dates: uniqueDates
129+
})
130+
131+
if (error) {
132+
console.error('Error loading daily totals:', error)
133+
} else {
134+
// Convert array to map for easy lookup
135+
const totalsMap: Record<string, number> = {}
136+
data?.forEach((item: any) => {
137+
totalsMap[item.date] = item.total
138+
})
139+
dailyTotals.value = totalsMap
140+
}
141+
} catch (err) {
142+
console.error('Error loading daily totals:', err)
143+
}
112144
}
113145
114146
// Load more expenses
@@ -117,6 +149,7 @@ const loadMoreExpenses = async () => {
117149
118150
loadingMore.value = true
119151
await loadExpenses()
152+
await loadDailyTotals() // Refresh daily totals after loading more
120153
loadingMore.value = false
121154
}
122155

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export interface User {
3131
*/
3232
export interface ExpenseListProps {
3333
expenses: Expense[]
34+
dailyTotals?: Record<string, number> // Map of date -> total amount
3435
}
3536

3637
/**

0 commit comments

Comments
 (0)