diff --git a/src/features/budget-tracker/components/budget-tracker-list.tsx b/src/features/budget-tracker/components/budget-tracker-list.tsx index a8ed137..df7ed99 100644 --- a/src/features/budget-tracker/components/budget-tracker-list.tsx +++ b/src/features/budget-tracker/components/budget-tracker-list.tsx @@ -44,17 +44,56 @@ export function BudgetTrackerList() { name: string } | null>(null) + // Selected items for filtering summary calculations + const [selectedItemIds, setSelectedItemIds] = useState>(new Set()) + if (isLoading) { return
Loading budget tracker...
} const currentBalance = balance ? parseFloat(balance.amount) : 0 - // Calculate total amount and total paid based on stored values - const totalAmount = items.reduce((sum, item) => sum + parseFloat(item.amount), 0) - const totalPaid = items.reduce((sum, item) => sum + parseFloat(item.amountPaid), 0) + // Filter items based on selection (if any items are selected, only show those) + const filteredItems = selectedItemIds.size > 0 ? items.filter((item) => selectedItemIds.has(item.id)) : items + + // Calculate total amount and total paid using effective amounts (includes sub-items) + const totalAmount = filteredItems.reduce((sum, item) => { + const itemWithEffect = item as typeof item & { _effectiveAmount?: number } + return sum + (itemWithEffect._effectiveAmount || parseFloat(item.amount)) + }, 0) + + const totalPaid = filteredItems.reduce((sum, item) => { + const itemWithSubs = item as typeof item & { subItems?: Array<{ amountPaid: string }> } + const subItemsPaidTotal = (itemWithSubs.subItems || []).reduce( + (subSum, subItem) => subSum + parseFloat(subItem.amountPaid), + 0 + ) + return sum + parseFloat(item.amountPaid) + subItemsPaidTotal + }, 0) + const remainingToPay = totalAmount - totalPaid + // Handlers for item selection + const handleToggleSelectItem = (itemId: string) => { + setSelectedItemIds((prev) => { + const newSet = new Set(prev) + if (newSet.has(itemId)) { + newSet.delete(itemId) + } else { + newSet.add(itemId) + } + return newSet + }) + } + + const handleSelectAll = () => { + if (selectedItemIds.size === items.length) { + setSelectedItemIds(new Set()) + } else { + setSelectedItemIds(new Set(items.map((item) => item.id))) + } + } + const handleEditItem = (item: BudgetItem) => { setEditingItem(item) } @@ -120,7 +159,16 @@ export function BudgetTrackerList() { {/* Summary Section */}
-

Summary

+
+

+ Summary {selectedItemIds.size > 0 && `(${selectedItemIds.size} selected)`} +

+ {items.length > 0 && ( + + )} +

Total Budget

@@ -150,6 +198,8 @@ export function BudgetTrackerList() { + onToggleSelectItem: (itemId: string) => void onEditItem: (item: BudgetItem) => void onDeleteItem: (item: BudgetItem) => void onAddSubItem: (itemId: string) => void @@ -23,6 +25,8 @@ interface BudgetTrackerTableProps { export function BudgetTrackerTable({ data, balance, + selectedItemIds, + onToggleSelectItem, onEditItem, onDeleteItem, onAddSubItem, @@ -69,6 +73,7 @@ export function BudgetTrackerTable({ + Item Amount @@ -81,7 +86,7 @@ export function BudgetTrackerTable({ {sortedData.length === 0 ? ( - + No budget items yet. @@ -94,11 +99,8 @@ export function BudgetTrackerTable({ ) function BudgetItemRow({ item }: { item: BudgetItem }) { - // Use pre-loaded sub-items if available (from API), otherwise fetch them - const itemWithSubItems = item as BudgetItem & { subItems?: BudgetSubItem[] } - const preLoadedSubItems = itemWithSubItems.subItems - const { data: fetchedSubItems = [] } = useBudgetSubItems(item.id) - const subItems = preLoadedSubItems || fetchedSubItems + // Always use the hook data to ensure real-time updates + const { data: subItems = [] } = useBudgetSubItems(item.id) const hasSubItems = subItems.length > 0 const isExpanded = expandedItems.has(item.id) @@ -126,9 +128,18 @@ export function BudgetTrackerTable({ return a.paid ? 1 : -1 }) + const isSelected = selectedItemIds.has(item.id) + return ( <> + + onToggleSelectItem(item.id)} + aria-label={`Select ${item.name}`} + /> + {hasSubItems && (