mirror of
https://github.com/elisiariocouto/leggen.git
synced 2025-12-14 01:32:19 +00:00
- Add /transactions/monthly-stats endpoint with SQL aggregation - Replace client-side monthly processing with server-side calculations - Reduce data transfer by 99.5% (2,507 → 13 records for yearly data) - Simplify MonthlyTrends component by removing 40+ lines of aggregation logic - Clean up unused imports and interfaces 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
205 lines
6.1 KiB
TypeScript
205 lines
6.1 KiB
TypeScript
import axios from "axios";
|
|
import type {
|
|
Account,
|
|
Transaction,
|
|
AnalyticsTransaction,
|
|
Balance,
|
|
ApiResponse,
|
|
NotificationSettings,
|
|
NotificationTest,
|
|
NotificationService,
|
|
NotificationServicesResponse,
|
|
HealthData,
|
|
AccountUpdate,
|
|
TransactionStats,
|
|
} from "../types/api";
|
|
|
|
// Use VITE_API_URL for development, relative URLs for production
|
|
const API_BASE_URL = import.meta.env.VITE_API_URL || "/api/v1";
|
|
|
|
const api = axios.create({
|
|
baseURL: API_BASE_URL,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
});
|
|
|
|
export const apiClient = {
|
|
// Get all accounts
|
|
getAccounts: async (): Promise<Account[]> => {
|
|
const response = await api.get<ApiResponse<Account[]>>("/accounts");
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get account by ID
|
|
getAccount: async (id: string): Promise<Account> => {
|
|
const response = await api.get<ApiResponse<Account>>(`/accounts/${id}`);
|
|
return response.data.data;
|
|
},
|
|
|
|
// Update account details
|
|
updateAccount: async (
|
|
id: string,
|
|
updates: AccountUpdate,
|
|
): Promise<{ id: string; name?: string }> => {
|
|
const response = await api.put<ApiResponse<{ id: string; name?: string }>>(
|
|
`/accounts/${id}`,
|
|
updates,
|
|
);
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get all balances
|
|
getBalances: async (): Promise<Balance[]> => {
|
|
const response = await api.get<ApiResponse<Balance[]>>("/balances");
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get historical balances for balance progression chart
|
|
getHistoricalBalances: async (days?: number, accountId?: string): Promise<Balance[]> => {
|
|
const queryParams = new URLSearchParams();
|
|
if (days) queryParams.append("days", days.toString());
|
|
if (accountId) queryParams.append("account_id", accountId);
|
|
|
|
const response = await api.get<ApiResponse<Balance[]>>(
|
|
`/balances/history?${queryParams.toString()}`
|
|
);
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get balances for specific account
|
|
getAccountBalances: async (accountId: string): Promise<Balance[]> => {
|
|
const response = await api.get<ApiResponse<Balance[]>>(
|
|
`/accounts/${accountId}/balances`,
|
|
);
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get transactions with optional filters
|
|
getTransactions: async (params?: {
|
|
accountId?: string;
|
|
startDate?: string;
|
|
endDate?: string;
|
|
page?: number;
|
|
perPage?: number;
|
|
search?: string;
|
|
summaryOnly?: boolean;
|
|
}): Promise<ApiResponse<Transaction[]>> => {
|
|
const queryParams = new URLSearchParams();
|
|
|
|
if (params?.accountId) queryParams.append("account_id", params.accountId);
|
|
if (params?.startDate) queryParams.append("date_from", params.startDate);
|
|
if (params?.endDate) queryParams.append("date_to", params.endDate);
|
|
if (params?.page) queryParams.append("page", params.page.toString());
|
|
if (params?.perPage)
|
|
queryParams.append("per_page", params.perPage.toString());
|
|
if (params?.search) queryParams.append("search", params.search);
|
|
if (params?.summaryOnly !== undefined) {
|
|
queryParams.append("summary_only", params.summaryOnly.toString());
|
|
}
|
|
|
|
const response = await api.get<ApiResponse<Transaction[]>>(
|
|
`/transactions?${queryParams.toString()}`,
|
|
);
|
|
return response.data;
|
|
},
|
|
|
|
// Get transaction by ID
|
|
getTransaction: async (id: string): Promise<Transaction> => {
|
|
const response = await api.get<ApiResponse<Transaction>>(
|
|
`/transactions/${id}`,
|
|
);
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get notification settings
|
|
getNotificationSettings: async (): Promise<NotificationSettings> => {
|
|
const response = await api.get<ApiResponse<NotificationSettings>>(
|
|
"/notifications/settings",
|
|
);
|
|
return response.data.data;
|
|
},
|
|
|
|
// Update notification settings
|
|
updateNotificationSettings: async (
|
|
settings: NotificationSettings,
|
|
): Promise<NotificationSettings> => {
|
|
const response = await api.put<ApiResponse<NotificationSettings>>(
|
|
"/notifications/settings",
|
|
settings,
|
|
);
|
|
return response.data.data;
|
|
},
|
|
|
|
// Test notification
|
|
testNotification: async (test: NotificationTest): Promise<void> => {
|
|
await api.post("/notifications/test", test);
|
|
},
|
|
|
|
// Get notification services
|
|
getNotificationServices: async (): Promise<NotificationService[]> => {
|
|
const response = await api.get<ApiResponse<NotificationServicesResponse>>(
|
|
"/notifications/services",
|
|
);
|
|
// Convert object to array format
|
|
const servicesData = response.data.data;
|
|
return Object.values(servicesData);
|
|
},
|
|
|
|
// Delete notification service
|
|
deleteNotificationService: async (service: string): Promise<void> => {
|
|
await api.delete(`/notifications/settings/${service}`);
|
|
},
|
|
|
|
// Health check
|
|
getHealth: async (): Promise<HealthData> => {
|
|
const response = await api.get<ApiResponse<HealthData>>("/health");
|
|
return response.data.data;
|
|
},
|
|
|
|
// Analytics endpoints
|
|
getTransactionStats: async (days?: number): Promise<TransactionStats> => {
|
|
const queryParams = new URLSearchParams();
|
|
if (days) queryParams.append("days", days.toString());
|
|
|
|
const response = await api.get<ApiResponse<TransactionStats>>(
|
|
`/transactions/stats?${queryParams.toString()}`
|
|
);
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get all transactions for analytics (no pagination)
|
|
getTransactionsForAnalytics: async (days?: number): Promise<AnalyticsTransaction[]> => {
|
|
const queryParams = new URLSearchParams();
|
|
if (days) queryParams.append("days", days.toString());
|
|
|
|
const response = await api.get<ApiResponse<AnalyticsTransaction[]>>(
|
|
`/transactions/analytics?${queryParams.toString()}`
|
|
);
|
|
return response.data.data;
|
|
},
|
|
|
|
// Get monthly transaction statistics (pre-calculated)
|
|
getMonthlyTransactionStats: async (days?: number): Promise<Array<{
|
|
month: string;
|
|
income: number;
|
|
expenses: number;
|
|
net: number;
|
|
}>> => {
|
|
const queryParams = new URLSearchParams();
|
|
if (days) queryParams.append("days", days.toString());
|
|
|
|
const response = await api.get<ApiResponse<Array<{
|
|
month: string;
|
|
income: number;
|
|
expenses: number;
|
|
net: number;
|
|
}>>>(
|
|
`/transactions/monthly-stats?${queryParams.toString()}`
|
|
);
|
|
return response.data.data;
|
|
},
|
|
};
|
|
|
|
export default apiClient;
|