mirror of
https://github.com/elisiariocouto/leggen.git
synced 2025-12-13 21:52:40 +00:00
feat(analytics): Fix transaction limits and improve chart legends
Co-authored-by: elisiariocouto <818914+elisiariocouto@users.noreply.github.com>
This commit is contained in:
committed by
Elisiário Couto
parent
692bee574e
commit
e136fc4b75
@@ -8,10 +8,11 @@ import {
|
||||
ResponsiveContainer,
|
||||
Legend,
|
||||
} from "recharts";
|
||||
import type { Balance } from "../../types/api";
|
||||
import type { Balance, Account } from "../../types/api";
|
||||
|
||||
interface BalanceChartProps {
|
||||
data: Balance[];
|
||||
accounts: Account[];
|
||||
className?: string;
|
||||
}
|
||||
|
||||
@@ -26,7 +27,34 @@ interface AggregatedDataPoint {
|
||||
[key: string]: string | number;
|
||||
}
|
||||
|
||||
export default function BalanceChart({ data, className }: BalanceChartProps) {
|
||||
export default function BalanceChart({ data, accounts, className }: BalanceChartProps) {
|
||||
// Create a lookup map for account info
|
||||
const accountMap = accounts.reduce((map, account) => {
|
||||
map[account.id] = account;
|
||||
return map;
|
||||
}, {} as Record<string, Account>);
|
||||
|
||||
// Helper function to get bank name from institution_id
|
||||
const getBankName = (institutionId: string): string => {
|
||||
const bankMapping: Record<string, string> = {
|
||||
'REVOLUT_REVOLT21': 'Revolut',
|
||||
'NUBANK_NUPBBR25': 'Nu Pagamentos',
|
||||
'BANCOBPI_BBPIPTPL': 'Banco BPI',
|
||||
// Add more mappings as needed
|
||||
};
|
||||
return bankMapping[institutionId] || institutionId.split('_')[0];
|
||||
};
|
||||
|
||||
// Helper function to create display name for account
|
||||
const getAccountDisplayName = (accountId: string): string => {
|
||||
const account = accountMap[accountId];
|
||||
if (account) {
|
||||
const bankName = getBankName(account.institution_id);
|
||||
const accountName = account.name || `Account ${accountId.split('-')[1]}`;
|
||||
return `${bankName} - ${accountName}`;
|
||||
}
|
||||
return `Account ${accountId.split('-')[1]}`;
|
||||
};
|
||||
// Process balance data for the chart
|
||||
const chartData = data
|
||||
.filter((balance) => balance.balance_type === "closingBooked")
|
||||
@@ -116,7 +144,7 @@ export default function BalanceChart({ data, className }: BalanceChartProps) {
|
||||
stroke={colors[index % colors.length]}
|
||||
strokeWidth={2}
|
||||
dot={{ r: 4 }}
|
||||
name={`Account ${accountId.split('-')[1]}`}
|
||||
name={getAccountDisplayName(accountId)}
|
||||
/>
|
||||
))}
|
||||
</LineChart>
|
||||
|
||||
@@ -32,18 +32,12 @@ interface TooltipProps {
|
||||
}
|
||||
|
||||
export default function MonthlyTrends({ className }: MonthlyTrendsProps) {
|
||||
// Get transactions for the last 12 months
|
||||
// Get transactions for the last 12 months using analytics endpoint
|
||||
const { data: transactions, isLoading } = useQuery({
|
||||
queryKey: ["transactions", "monthly-trends"],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.getTransactions({
|
||||
startDate: new Date(
|
||||
Date.now() - 365 * 24 * 60 * 60 * 1000
|
||||
).toISOString().split("T")[0],
|
||||
endDate: new Date().toISOString().split("T")[0],
|
||||
perPage: 1000,
|
||||
});
|
||||
return response.data;
|
||||
// Get last 365 days of transactions for monthly trends
|
||||
return await apiClient.getTransactionsForAnalytics(365);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -54,7 +48,7 @@ export default function MonthlyTrends({ className }: MonthlyTrendsProps) {
|
||||
const monthlyMap: { [key: string]: MonthlyData } = {};
|
||||
|
||||
transactions.forEach((transaction) => {
|
||||
const date = new Date(transaction.transaction_date);
|
||||
const date = new Date(transaction.date);
|
||||
const monthKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
|
||||
|
||||
if (!monthlyMap[monthKey]) {
|
||||
@@ -69,10 +63,10 @@ export default function MonthlyTrends({ className }: MonthlyTrendsProps) {
|
||||
};
|
||||
}
|
||||
|
||||
if (transaction.transaction_value > 0) {
|
||||
monthlyMap[monthKey].income += transaction.transaction_value;
|
||||
if (transaction.amount > 0) {
|
||||
monthlyMap[monthKey].income += transaction.amount;
|
||||
} else {
|
||||
monthlyMap[monthKey].expenses += Math.abs(transaction.transaction_value);
|
||||
monthlyMap[monthKey].expenses += Math.abs(transaction.amount);
|
||||
}
|
||||
|
||||
monthlyMap[monthKey].net = monthlyMap[monthKey].income - monthlyMap[monthKey].expenses;
|
||||
|
||||
@@ -30,6 +30,24 @@ export default function TransactionDistribution({
|
||||
accounts,
|
||||
className,
|
||||
}: TransactionDistributionProps) {
|
||||
// Helper function to get bank name from institution_id
|
||||
const getBankName = (institutionId: string): string => {
|
||||
const bankMapping: Record<string, string> = {
|
||||
'REVOLUT_REVOLT21': 'Revolut',
|
||||
'NUBANK_NUPBBR25': 'Nu Pagamentos',
|
||||
'BANCOBPI_BBPIPTPL': 'Banco BPI',
|
||||
// Add more mappings as needed
|
||||
};
|
||||
return bankMapping[institutionId] || institutionId.split('_')[0];
|
||||
};
|
||||
|
||||
// Helper function to create display name for account
|
||||
const getAccountDisplayName = (account: Account): string => {
|
||||
const bankName = getBankName(account.institution_id);
|
||||
const accountName = account.name || `Account ${account.id.split('-')[1]}`;
|
||||
return `${bankName} - ${accountName}`;
|
||||
};
|
||||
|
||||
// Create pie chart data from account balances
|
||||
const pieData: PieDataPoint[] = accounts.map((account, index) => {
|
||||
const closingBalance = account.balances.find(
|
||||
@@ -39,7 +57,7 @@ export default function TransactionDistribution({
|
||||
const colors = ["#3B82F6", "#10B981", "#F59E0B", "#EF4444", "#8B5CF6"];
|
||||
|
||||
return {
|
||||
name: account.name || `Account ${account.id.split('-')[1]}`,
|
||||
name: getAccountDisplayName(account),
|
||||
value: closingBalance?.amount || 0,
|
||||
color: colors[index % colors.length],
|
||||
};
|
||||
|
||||
@@ -154,6 +154,17 @@ export const apiClient = {
|
||||
);
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
// Get all transactions for analytics (no pagination)
|
||||
getTransactionsForAnalytics: async (days?: number): Promise<Transaction[]> => {
|
||||
const queryParams = new URLSearchParams();
|
||||
if (days) queryParams.append("days", days.toString());
|
||||
|
||||
const response = await api.get<ApiResponse<Transaction[]>>(
|
||||
`/transactions/analytics?${queryParams.toString()}`
|
||||
);
|
||||
return response.data.data;
|
||||
},
|
||||
};
|
||||
|
||||
export default apiClient;
|
||||
|
||||
@@ -126,7 +126,7 @@ function AnalyticsDashboard() {
|
||||
{/* Charts */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
<div className="bg-white rounded-lg shadow p-6 border border-gray-200">
|
||||
<BalanceChart data={balances || []} />
|
||||
<BalanceChart data={balances || []} accounts={accounts || []} />
|
||||
</div>
|
||||
<div className="bg-white rounded-lg shadow p-6 border border-gray-200">
|
||||
<TransactionDistribution accounts={accounts || []} />
|
||||
|
||||
Reference in New Issue
Block a user