diff --git a/src/components/dashboard/UnsealDashboard.tsx b/src/components/dashboard/UnsealDashboard.tsx
index 3427f00..a9f33d6 100644
--- a/src/components/dashboard/UnsealDashboard.tsx
+++ b/src/components/dashboard/UnsealDashboard.tsx
@@ -1,231 +1,375 @@
-'use client';
+"use client";
-import React, { useState } from 'react';
-import { User } from 'firebase/auth';
-import { Transaction } from '@/types/schema';
-import { format } from 'date-fns';
-import Link from 'next/link';
-import UnsealDock from './UnsealDock';
-import UserAvatar from '@/components/ui/UserAvatar';
+import { format } from "date-fns";
+import type { User } from "firebase/auth";
+import UserAvatar from "@/components/ui/UserAvatar";
+import { DEFAULT_MONTHLY_BURN } from "@/lib/constants";
+import type { Transaction } from "@/types/schema";
+import UnsealDock from "./UnsealDock";
interface UnsealDashboardProps {
- user: User | null;
- balance: number;
- transactions: Transaction[];
- stats: {
- income: number;
- expense: number;
- };
+ user: User | null;
+ balance: number;
+ transactions: Transaction[];
+ stats: {
+ income: number;
+ expense: number;
+ };
}
-export default function UnsealDashboard({ user, balance, transactions, stats }: UnsealDashboardProps) {
- const firstName = user?.displayName?.split(' ')[0] || 'User';
- const recentTx = transactions.slice(0, 5);
- // Calculate Runway: Balance / fixed 15k for now (as per HTML reference)
- // In a real app, this would be: balance / average_monthly_expense
- const monthlyBurn = 15000;
- const runwayMonths = (balance / 100 / monthlyBurn).toFixed(1);
+export default function UnsealDashboard({
+ user,
+ balance,
+ transactions,
+}: UnsealDashboardProps) {
+ const firstName = user?.displayName?.split(" ")[0] || "User";
+ const recentTx = transactions.slice(0, 5);
+ // Calculate Runway: Balance / fixed 15k for now (as per HTML reference)
+ // In a real app, this would be: balance / average_monthly_expense
+ const monthlyBurn = DEFAULT_MONTHLY_BURN;
+ const runwayMonths = (balance / 100 / monthlyBurn).toFixed(1);
- return (
-
+ return (
+
+ {/* Header */}
+
+
+
+
+ lock_open
+
+
+
+ UNSEAL
+
+
+
+
+
+
+
+
+
+ Secure
+
+
+ shield
+
+
+
+
+
+
+
+ {/* Main Content Layout */}
+
+
+
+ Good evening, {firstName}.
+
+ Your financial fortress is active.
+
+
+
- {/* Header */}
-
-
-
- lock_open
-
-
UNSEAL
-
-
-
-
-
-
-
-
Secure
-
shield
-
-
-
-
-
-
-
- {/* Main Content Layout */}
-
-
-
- Good evening, {firstName}.
- Your financial fortress is active.
-
-
-
-
- {/* Financial Runway */}
-
-
-
Financial Runway
-
- {/* Gauge */}
-
-
+ {/* CFO Intelligence */}
+
+ {/* Shimmer Border/Effect */}
+
+
- {/* Net Wealth Stream */}
-
-
-
-
Net Wealth Stream
-
-
- ₹{(balance / 100).toLocaleString('en-IN')}
-
-
- trending_up
- +8.4%
-
-
-
-
-
-
-
-
-
- {/* Chart */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Jan
- Feb
- Mar
- Apr
- May
- Jun
-
-
+
+
+
+
+ psychology
+
+ CFO Intelligence
+
+
+ Ask your personal CFO
+
+
+ Get instant insights on your spending, investments, and wealth
+ leaks.
+
+
+ {/* Input */}
+
+
+
+
+ colors_spark
+
+
+
+
+
+
+
- {/* Recent Activity (Added to keep functionality matching new aesthetic) */}
-
-
Recent Activity
-
- {recentTx.length === 0 ? (
-
No recent activity.
- ) : (
- recentTx.map((tx) => (
-
-
-
- {tx.type === 'income' ? (
- arrow_downward
- ) : (
- swap_horiz
- )}
-
-
-
{tx.description}
-
{format(new Date(tx.date), 'MMM d, h:mm a')}
-
-
-
- {tx.type === 'income' ? '+' : '-'}₹{(tx.amount / 100).toLocaleString('en-IN')}
-
-
- ))
- )}
-
-
-
+ {/* Net Wealth Stream */}
+
+
+
+
+ Net Wealth Stream
+
+
+
+ ₹{(balance / 100).toLocaleString("en-IN")}
+
+
+
+ trending_up
+
+
+ +8.4%
+
+
+
+
+
+
+
+
+
+
+ {/* Chart */}
+
+
+ Net Wealth Chart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Jan
+ Feb
+ Mar
+ Apr
+ May
+ Jun
+
+
-
+ {/* Recent Activity (Added to keep functionality matching new aesthetic) */}
+
+
+ Recent Activity
+
+
+ {recentTx.length === 0 ? (
+
No recent activity.
+ ) : (
+ recentTx.map((tx) => (
+
+
+
+ {tx.type === "income" ? (
+
+ arrow_downward
+
+ ) : (
+
+ swap_horiz
+
+ )}
+
+
+
+ {tx.description}
+
+
+ {format(new Date(tx.date), "MMM d, h:mm a")}
+
+
+
+
+ {tx.type === "income" ? "+" : "-"}₹
+ {(tx.amount / 100).toLocaleString("en-IN")}
+
+
+ ))
+ )}
+
+
+
+
- {/* Floating Dock Navigation */}
-
-
- );
+ {/* Floating Dock Navigation */}
+
+
+ );
}
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
new file mode 100644
index 0000000..dd302f3
--- /dev/null
+++ b/src/lib/constants.ts
@@ -0,0 +1,4 @@
+// Constants for financial calculations and defaults
+
+// Default monthly burn rate in INR (Rupees), used for runway calculation when actual data is unavailable.
+export const DEFAULT_MONTHLY_BURN = 15000;
diff --git a/src/lib/parsers/sbi.ts b/src/lib/parsers/sbi.ts
index b6c73c3..7148b38 100644
--- a/src/lib/parsers/sbi.ts
+++ b/src/lib/parsers/sbi.ts
@@ -1,3 +1,4 @@
+import { parse } from 'date-fns';
import { type Transaction, toPaise } from '../../types/schema.ts';
// We omit 'id' and 'userId' because the parser doesn't know about them.
@@ -137,12 +138,18 @@ function parseDate(dateStr: string): Date | null {
const normalized = dateStr.replace(/\//g, '-');
const parts = normalized.split('-');
- if (parts.length === 3) {
- const [day, month] = parts;
- let year = parts[2];
+ if (parts.length !== 3) return null;
- const date = parse(normalized, formatString, new Date());
- return isNaN(date.getTime()) ? null : date;
+ const yearPart = parts[2];
+
+ let date: Date;
+
+ if (yearPart.length === 4) {
+ date = parse(normalized, 'd-M-yyyy', new Date());
+ } else {
+ // Assume 2 digits
+ date = parse(normalized, 'd-M-yy', new Date());
}
- return null;
+
+ return isNaN(date.getTime()) ? null : date;
}