diff --git a/src/services/budgetService.ts b/src/services/budgetService.ts index 69be8d6..2bcb48b 100644 --- a/src/services/budgetService.ts +++ b/src/services/budgetService.ts @@ -5,6 +5,47 @@ import api from './api'; import type { Budget, ApiResponse, BudgetPeriodType } from '../types'; +/** + * Backend Budget API response (snake_case) + */ +interface ApiBudget { + id: number; + name: string; + amount: number; + period_type: BudgetPeriodType; + category_id?: number; + account_id?: number; + is_rolling: boolean; + start_date: string; + end_date?: string; + spent?: number; + progress?: number; + created_at: string; + // Nested objects from Preload + category?: { id: number; name: string; icon?: string }; + account?: { id: number; name: string }; +} + +/** + * Convert backend API response to frontend Budget model + */ +function mapApiBudgetToBudget(apiBudget: ApiBudget): Budget { + return { + id: apiBudget.id, + name: apiBudget.name, + amount: apiBudget.amount, + periodType: apiBudget.period_type, + categoryId: apiBudget.category_id, + accountId: apiBudget.account_id, + isRolling: apiBudget.is_rolling, + startDate: apiBudget.start_date, + endDate: apiBudget.end_date, + spent: apiBudget.spent ?? 0, + progress: apiBudget.progress ?? 0, + createdAt: apiBudget.created_at, + }; +} + /** * Budget form input interface */ @@ -35,19 +76,20 @@ export interface BudgetProgress { * Get all budgets */ export async function getBudgets(): Promise { - const response = await api.get>('/budgets'); - return response.data || []; + const response = await api.get>('/budgets'); + const apiBudgets = response.data || []; + return apiBudgets.map(mapApiBudgetToBudget); } /** * Get a single budget by ID */ export async function getBudget(id: number): Promise { - const response = await api.get>(`/budgets/${id}`); + const response = await api.get>(`/budgets/${id}`); if (!response.data) { throw new Error('Budget not found'); } - return response.data; + return mapApiBudgetToBudget(response.data); } /** @@ -77,11 +119,11 @@ export async function createBudget(data: BudgetFormInput): Promise { start_date: data.startDate ? `${data.startDate}T00:00:00Z` : undefined, end_date: data.endDate ? `${data.endDate}T23:59:59Z` : undefined, }; - const response = await api.post>('/budgets', payload); + const response = await api.post>('/budgets', payload); if (!response.data) { throw new Error(response.error || 'Failed to create budget'); } - return response.data; + return mapApiBudgetToBudget(response.data); } /** @@ -99,12 +141,12 @@ export async function updateBudget(id: number, data: Partial): if (data.isRolling !== undefined) payload.is_rolling = data.isRolling; if (data.startDate !== undefined) payload.start_date = `${data.startDate}T00:00:00Z`; if (data.endDate !== undefined) payload.end_date = data.endDate ? `${data.endDate}T23:59:59Z` : null; - - const response = await api.put>(`/budgets/${id}`, payload); + + const response = await api.put>(`/budgets/${id}`, payload); if (!response.data) { throw new Error(response.error || 'Failed to update budget'); } - return response.data; + return mapApiBudgetToBudget(response.data); } /**