diff --git a/resources/js/components/dashboard/account-balance-card.tsx b/resources/js/components/dashboard/account-balance-card.tsx
index b87268a9..6c112d7f 100644
--- a/resources/js/components/dashboard/account-balance-card.tsx
+++ b/resources/js/components/dashboard/account-balance-card.tsx
@@ -1,8 +1,9 @@
import { EncryptedText } from '@/components/encrypted-text';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Account } from '@/types/account';
-import { ArrowDownIcon, ArrowUpIcon } from 'lucide-react';
-import { Line, LineChart, ResponsiveContainer } from 'recharts';
+import { AmountTrendIndicator } from './amount-trend-indicator';
+import { AccountTypeIcon } from './account-type-icon';
+import { Line, LineChart, ResponsiveContainer, Tooltip } from 'recharts';
interface AccountBalanceCardProps {
account: Account & {
@@ -46,43 +47,55 @@ export function AccountBalanceCard({
-
-
-
+
+
+
{formatter.format(account.currentBalance / 100)}
-
-
- {isPositive ? (
-
- ) : (
-
- )}
- {formatter.format(Math.abs(account.diff) / 100)}
-
- vs last month
-
+
-
+
+ {
+ if (!active || !payload?.length)
+ return null;
+ const data = payload[0].payload as {
+ date: string;
+ value: number;
+ };
+ return (
+
+
+ {data.date}
+
+
+ {formatter.format(
+ data.value / 100,
+ )}
+
+
+ );
+ }}
+ />
diff --git a/resources/js/components/dashboard/account-type-icon.tsx b/resources/js/components/dashboard/account-type-icon.tsx
new file mode 100644
index 00000000..78070aa8
--- /dev/null
+++ b/resources/js/components/dashboard/account-type-icon.tsx
@@ -0,0 +1,20 @@
+import { cn } from "@/lib/utils";
+import { AccountType } from "@/types/account";
+import { BadgeQuestionMarkIcon, Building2, CreditCard, FolderKanban, Landmark, LucideIcon, PiggyBank } from "lucide-react";
+
+export function AccountTypeIcon({ type, className }: { type: AccountType, className?: string }) {
+ const typeMap: Record = {
+ checking: Building2, // 🏦 - bank / institution
+ credit_card: CreditCard, // 💳 - card
+ loan: Landmark, // 🏠 - "institution/loan", or use Home if it's a mortgage
+ savings: PiggyBank, // 💰 - savings
+ others: FolderKanban, // 📁 - miscellaneous/other
+ };
+
+ const Icon = typeMap[type] || BadgeQuestionMarkIcon;
+
+ return ;
+}
diff --git a/resources/js/components/dashboard/amount-trend-indicator.tsx b/resources/js/components/dashboard/amount-trend-indicator.tsx
new file mode 100644
index 00000000..e288a6c3
--- /dev/null
+++ b/resources/js/components/dashboard/amount-trend-indicator.tsx
@@ -0,0 +1,38 @@
+import { cn } from "@/lib/utils";
+import { TrendingUp, TrendingDown } from "lucide-react";
+
+export function AmountTrendIndicator({
+ trend,
+ isPositive,
+ label,
+ className = '',
+}: {
+ trend: string | null;
+ isPositive: boolean;
+ label: string;
+ className?: string;
+}) {
+ if (trend === null) return null;
+
+ const Icon = isPositive ? TrendingUp : TrendingDown;
+ const iconColorClass = isPositive
+ ? 'text-green-600/70 dark:text-green-400/70'
+ : 'text-red-600/70 dark:text-red-400/70';
+
+ return (
+
+
+ {trend}
+
+ {label}
+
+
+ );
+}
diff --git a/resources/js/components/dashboard/net-worth-chart.tsx b/resources/js/components/dashboard/net-worth-chart.tsx
index 8b24a8e0..ed20dcc2 100644
--- a/resources/js/components/dashboard/net-worth-chart.tsx
+++ b/resources/js/components/dashboard/net-worth-chart.tsx
@@ -12,8 +12,8 @@ import {
StackedBarChart,
} from '@/components/ui/stacked-bar-chart';
import { NetWorthEvolutionData } from '@/hooks/use-dashboard-data';
-import { TrendingDown, TrendingUp } from 'lucide-react';
import { useMemo } from 'react';
+import { PercentageTrendIndicator } from './percentage-trend-indicator';
interface NetWorthChartProps {
data: NetWorthEvolutionData;
@@ -71,37 +71,6 @@ function calculateTrend(
return ((currentTotal - previousTotal) / Math.abs(previousTotal)) * 100;
}
-function TrendIndicator({
- trend,
- label,
-}: {
- trend: number | null;
- label: string;
-}) {
- if (trend === null) return null;
-
- const isPositive = trend >= 0;
- const Icon = isPositive ? TrendingUp : TrendingDown;
- const iconColorClass = isPositive
- ? 'text-green-600/70 dark:text-green-400/70'
- : 'text-red-600/70 dark:text-red-400/70';
-
- return (
-
-
- {isPositive ? '+' : ''}
- {trend.toFixed(1)}%
-
- {label}
-
-
- );
-}
-
interface EncryptedLabelProps {
account: { name: string; name_iv: string };
}
@@ -261,11 +230,11 @@ export function NetWorthChart({
Net Worth Evolution
-
-
diff --git a/resources/js/components/dashboard/percentage-trend-indicator.tsx b/resources/js/components/dashboard/percentage-trend-indicator.tsx
new file mode 100644
index 00000000..b3bae525
--- /dev/null
+++ b/resources/js/components/dashboard/percentage-trend-indicator.tsx
@@ -0,0 +1,32 @@
+import { TrendingUp, TrendingDown } from "lucide-react";
+
+export function PercentageTrendIndicator({
+ trend,
+ label,
+}: {
+ trend: number | null;
+ label: string;
+}) {
+ if (trend === null) return null;
+
+ const isPositive = trend >= 0;
+ const Icon = isPositive ? TrendingUp : TrendingDown;
+ const iconColorClass = isPositive
+ ? 'text-green-600/70 dark:text-green-400/70'
+ : 'text-red-600/70 dark:text-red-400/70';
+
+ return (
+
+
+ {isPositive ? '+' : ''}
+ {trend.toFixed(1)}%
+
+ {label}
+
+
+ );
+}