(!!getToken());
@@ -69,12 +72,14 @@ export function Navbar() {
to={item.href}
className={
active
- ? 'rounded-full bg-secondary px-4 py-2 text-xs font-semibold text-secondary-foreground shadow-sm'
- : 'rounded-full px-4 py-2 text-xs font-semibold text-muted-foreground transition hover:bg-muted hover:text-foreground'
+ ? 'rounded-full bg-secondary px-4 py-2 text-xs font-semibold text-secondary-foreground shadow-sm flex items-center'
+ : 'rounded-full px-4 py-2 text-xs font-semibold text-muted-foreground transition hover:bg-muted hover:text-foreground flex items-center'
}
>
+ {item.icon && }
{item.name}
+
);
})}
@@ -124,12 +129,14 @@ export function Navbar() {
onClick={() => setIsOpen(false)}
className={
active
- ? 'block rounded-lg bg-secondary px-3 py-2 text-sm font-medium text-secondary-foreground'
- : 'block rounded-lg px-3 py-2 text-sm font-medium text-foreground hover:bg-muted'
+ ? 'flex items-center rounded-lg bg-secondary px-3 py-2 text-sm font-medium text-secondary-foreground'
+ : 'flex items-center rounded-lg px-3 py-2 text-sm font-medium text-foreground hover:bg-muted'
}
>
+ {item.icon && }
{item.name}
+
);
})}
diff --git a/app/src/pages/Dashboard.tsx b/app/src/pages/Dashboard.tsx
index b2d4e7aa8..e38a8171d 100644
--- a/app/src/pages/Dashboard.tsx
+++ b/app/src/pages/Dashboard.tsx
@@ -18,7 +18,9 @@ import {
AlertTriangle,
Calendar,
Plus,
+ Target,
} from 'lucide-react';
+
import { getDashboardSummary, type DashboardSummary } from '@/api/dashboard';
import { useNavigate } from 'react-router-dom';
import { formatMoney } from '@/lib/currency';
@@ -95,8 +97,17 @@ export function Dashboard() {
icon: CreditCard,
description: 'Due soon',
},
+ {
+ title: 'Savings Progress',
+ amount: currency(13100),
+ change: '65%',
+ trend: 'up',
+ icon: Target,
+ description: 'Goal: $20,000',
+ },
] as const;
+
const transactions = data?.recent_transactions ?? [];
const upcomingBills = data?.upcoming_bills ?? [];
const categoryBreakdown = data?.category_breakdown ?? [];
@@ -141,7 +152,8 @@ export function Dashboard() {
)}
-
+
+
{summaryCards.map((card, index) => (
diff --git a/app/src/pages/Savings.tsx b/app/src/pages/Savings.tsx
new file mode 100644
index 000000000..9181d38ba
--- /dev/null
+++ b/app/src/pages/Savings.tsx
@@ -0,0 +1,113 @@
+import { useState } from 'react';
+import { FinancialCard, FinancialCardContent, FinancialCardDescription, FinancialCardHeader, FinancialCardTitle } from '@/components/ui/financial-card';
+import { Button } from '@/components/ui/button';
+import { Target, Plus, Award, Clock } from 'lucide-react';
+import { formatMoney } from '@/lib/currency';
+
+const mockGoals = [
+ {
+ id: 1,
+ title: 'Emergency Fund',
+ target: 10000,
+ current: 8500,
+ deadline: 'Dec 2025',
+ },
+ {
+ id: 2,
+ title: 'New Laptop',
+ target: 2000,
+ current: 400,
+ deadline: 'Aug 2025',
+ },
+ {
+ id: 3,
+ title: 'Travel Fund',
+ target: 5000,
+ current: 4200,
+ deadline: 'Oct 2025',
+ }
+];
+
+export function Savings() {
+ const [goals] = useState(mockGoals);
+
+ const getProgressClass = (percentage: number) => {
+ return percentage >= 80 ? 'chart-fill-success' : 'chart-fill-primary';
+ };
+
+ return (
+
+
+
+
+
Savings Goals
+
+ Plan your future and track your progress towards financial freedom
+
+
+
+
+
+
+
+ {goals.map((goal) => {
+ const percentage = (goal.current / goal.target) * 100;
+ const isHighProgress = percentage >= 80;
+
+ return (
+
+
+
+
+
+ {goal.title}
+
+ {isHighProgress && (
+
+ )}
+
+
+ Target date: {goal.deadline}
+
+
+
+
+
+
+
+ {formatMoney(goal.current)}
+
+
+ of {formatMoney(goal.target)}
+
+
+
+ {percentage.toFixed(0)}%
+
+
+
+
+
+
+
+ {isHighProgress ? 'Almost there!' : 'On your way'}
+
+
+
+
+ );
+ })}
+
+
+ );
+}
diff --git a/app/vite.config.ts b/app/vite.config.ts
index 329b7953f..d648f8794 100644
--- a/app/vite.config.ts
+++ b/app/vite.config.ts
@@ -6,7 +6,7 @@ import path from "path";
export default defineConfig(({ mode }) => ({
server: {
host: "::",
- port: 5173,
+ port: 3000,
},
plugins: [
react(),