mirror of
https://github.com/elisiariocouto/leggen.git
synced 2025-12-13 11:22:21 +00:00
Fix MonthlyTrends dynamic title, remove Period Summary, convert BalanceChart to stacked area chart
Co-authored-by: elisiariocouto <818914+elisiariocouto@users.noreply.github.com>
This commit is contained in:
committed by
Elisiário Couto
parent
c8f0a103c6
commit
d51aa9429e
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
LineChart,
|
||||
Line,
|
||||
AreaChart,
|
||||
Area,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
@@ -111,7 +111,7 @@ export default function BalanceChart({ data, accounts, className }: BalanceChart
|
||||
</h3>
|
||||
<div className="h-80">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<LineChart data={finalData}>
|
||||
<AreaChart data={finalData}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis
|
||||
dataKey="date"
|
||||
@@ -131,25 +131,25 @@ export default function BalanceChart({ data, accounts, className }: BalanceChart
|
||||
tickFormatter={(value) => `€${value.toLocaleString()}`}
|
||||
/>
|
||||
<Tooltip
|
||||
formatter={(value: number) => [
|
||||
formatter={(value: number, name: string) => [
|
||||
`€${value.toLocaleString()}`,
|
||||
"Balance",
|
||||
getAccountDisplayName(name),
|
||||
]}
|
||||
labelFormatter={(label) => `Date: ${label}`}
|
||||
/>
|
||||
<Legend />
|
||||
{Object.keys(accountBalances).map((accountId, index) => (
|
||||
<Line
|
||||
<Area
|
||||
key={accountId}
|
||||
type="monotone"
|
||||
dataKey={accountId}
|
||||
stackId="1"
|
||||
fill={colors[index % colors.length]}
|
||||
stroke={colors[index % colors.length]}
|
||||
strokeWidth={2}
|
||||
dot={{ r: 4 }}
|
||||
name={getAccountDisplayName(accountId)}
|
||||
/>
|
||||
))}
|
||||
</LineChart>
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,7 +53,7 @@ export default function MonthlyTrends({ className, days = 365 }: MonthlyTrendsPr
|
||||
|
||||
if (!monthlyMap[monthKey]) {
|
||||
monthlyMap[monthKey] = {
|
||||
month: date.toLocaleDateString(undefined, {
|
||||
month: date.toLocaleDateString('en-GB', {
|
||||
year: 'numeric',
|
||||
month: 'short'
|
||||
}),
|
||||
@@ -77,10 +77,20 @@ export default function MonthlyTrends({ className, days = 365 }: MonthlyTrendsPr
|
||||
...Object.entries(monthlyMap)
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
.map(([, data]) => data)
|
||||
.slice(-12) // Last 12 months
|
||||
);
|
||||
}
|
||||
|
||||
// Calculate number of months to display based on days filter
|
||||
const getMonthsToDisplay = (days: number): number => {
|
||||
if (days <= 30) return 1;
|
||||
if (days <= 180) return 6;
|
||||
if (days <= 365) return 12;
|
||||
return Math.ceil(days / 30);
|
||||
};
|
||||
|
||||
const monthsToDisplay = getMonthsToDisplay(days);
|
||||
const displayData = monthlyData.slice(-monthsToDisplay);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className={className}>
|
||||
@@ -94,7 +104,7 @@ export default function MonthlyTrends({ className, days = 365 }: MonthlyTrendsPr
|
||||
);
|
||||
}
|
||||
|
||||
if (monthlyData.length === 0) {
|
||||
if (displayData.length === 0) {
|
||||
return (
|
||||
<div className={className}>
|
||||
<h3 className="text-lg font-medium text-gray-900 mb-4">
|
||||
@@ -123,14 +133,22 @@ export default function MonthlyTrends({ className, days = 365 }: MonthlyTrendsPr
|
||||
return null;
|
||||
};
|
||||
|
||||
// Generate dynamic title based on time period
|
||||
const getTitle = (days: number): string => {
|
||||
if (days <= 30) return "Monthly Spending Trends (Last 30 Days)";
|
||||
if (days <= 180) return "Monthly Spending Trends (Last 6 Months)";
|
||||
if (days <= 365) return "Monthly Spending Trends (Last 12 Months)";
|
||||
return `Monthly Spending Trends (Last ${Math.ceil(days / 30)} Months)`;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<h3 className="text-lg font-medium text-gray-900 mb-4">
|
||||
Monthly Spending Trends (Last 12 Months)
|
||||
{getTitle(days)}
|
||||
</h3>
|
||||
<div className="h-80">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={monthlyData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||||
<BarChart data={displayData} margin={{ top: 20, right: 30, left: 20, bottom: 5 }}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis
|
||||
dataKey="month"
|
||||
|
||||
@@ -144,41 +144,6 @@ function AnalyticsDashboard() {
|
||||
<div className="bg-white rounded-lg shadow p-6 border border-gray-200">
|
||||
<MonthlyTrends days={selectedPeriod.days} />
|
||||
</div>
|
||||
|
||||
{/* Summary Section */}
|
||||
{stats && (
|
||||
<div className="bg-blue-50 rounded-lg p-6 border border-blue-200">
|
||||
<h3 className="text-lg font-medium text-blue-900 mb-4">
|
||||
Period Summary ({stats.period_days} days)
|
||||
</h3>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 text-sm">
|
||||
<div>
|
||||
<p className="text-blue-700 font-medium">Booked Transactions</p>
|
||||
<p className="text-blue-900">{stats.booked_transactions}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-blue-700 font-medium">Pending Transactions</p>
|
||||
<p className="text-blue-900">{stats.pending_transactions}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-blue-700 font-medium">Transaction Ratio</p>
|
||||
<p className="text-blue-900">
|
||||
{stats.total_transactions > 0
|
||||
? `${Math.round(
|
||||
(stats.booked_transactions / stats.total_transactions) * 100
|
||||
)}% booked`
|
||||
: "No transactions"}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-blue-700 font-medium">Spend Rate</p>
|
||||
<p className="text-blue-900">
|
||||
€{((stats.total_expenses || 0) / stats.period_days).toFixed(2)}/day
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user