main
tsx 116 lines 4.79 KB
Raw
1 import { useEffect, useState } from "react";
2 import { useNavigate } from "react-router-dom";
3 import Layout from "@/components/Layout";
4 import { Card } from "@/components/ui/card";
5 import { Badge } from "@/components/ui/badge";
6 import { ArrowUpRight, ArrowDownRight, Plus } from "lucide-react";
7 import { Button } from "@/components/ui/button";
8 import { transactionService } from "@/services/transactionService";
9 import { Transaction } from "@/types/transaction";
10 import { formatDistanceToNow } from "date-fns";
11
12 const Home = () => {
13 const navigate = useNavigate();
14 const [transactions, setTransactions] = useState<Transaction[]>([]);
15 const [loading, setLoading] = useState(true);
16 const balance = transactionService.getBalance();
17
18 useEffect(() => {
19 const loadTransactions = async () => {
20 const data = await transactionService.getTransactions();
21 setTransactions(data);
22 setLoading(false);
23 };
24 loadTransactions();
25 }, []);
26
27 return (
28 <Layout title="Expenses">
29 <div className="p-4 space-y-6">
30 {/* Balance Card */}
31 <Card className="p-8 bg-card border-0 shadow-lg">
32 <div className="space-y-2">
33 <p className="text-sm text-muted-foreground font-medium">Available Balance</p>
34 <h2 className="text-5xl font-bold tracking-tight">${balance.toFixed(2)}</h2>
35 </div>
36 <div className="mt-8">
37 <Button size="lg" className="w-full" onClick={() => navigate("/send")}>
38 <Plus className="h-5 w-5 mr-2" />
39 Send Money
40 </Button>
41 </div>
42 </Card>
43
44 {/* Stats */}
45 <div className="grid grid-cols-2 gap-4">
46 <Card className="p-6 border-0 shadow-md">
47 <div className="space-y-2">
48 <p className="text-sm text-muted-foreground font-medium">This Month</p>
49 <p className="text-3xl font-bold text-foreground">$985</p>
50 <div className="flex items-center gap-1 text-expense-negative text-sm font-medium">
51 <ArrowUpRight className="h-4 w-4" />
52 <span>Spent</span>
53 </div>
54 </div>
55 </Card>
56 <Card className="p-6 border-0 shadow-md">
57 <div className="space-y-2">
58 <p className="text-sm text-muted-foreground font-medium">Saved</p>
59 <p className="text-3xl font-bold text-foreground">$450</p>
60 <div className="flex items-center gap-1 text-expense-positive text-sm font-medium">
61 <ArrowDownRight className="h-4 w-4" />
62 <span>This month</span>
63 </div>
64 </div>
65 </Card>
66 </div>
67
68 {/* Recent Transactions */}
69 <div className="space-y-4">
70 <h3 className="text-xl font-bold">Recent Transactions</h3>
71 {loading ? (
72 <Card className="p-8 border-0 shadow-md text-center">
73 <p className="text-muted-foreground">Loading transactions...</p>
74 </Card>
75 ) : transactions.length === 0 ? (
76 <Card className="p-8 border-0 shadow-md text-center">
77 <p className="text-muted-foreground">No transactions yet</p>
78 </Card>
79 ) : (
80 <div className="space-y-3">
81 {transactions.map((transaction) => (
82 <Card key={transaction.id} className="p-5 border-0 shadow-md hover:shadow-lg transition-all cursor-pointer">
83 <div className="flex items-center justify-between">
84 <div className="flex-1">
85 <div className="flex items-center gap-3 mb-1">
86 <p className="font-semibold text-base">{transaction.recipientName}</p>
87 {transaction.status === "processing" && (
88 <Badge variant="outline" className="text-xs font-medium border-2">
89 Processing
90 </Badge>
91 )}
92 {transaction.status === "pending" && (
93 <Badge variant="outline" className="text-xs font-medium border-2 border-yellow-500">
94 Pending
95 </Badge>
96 )}
97 </div>
98 <p className="text-sm text-muted-foreground font-medium">
99 {transaction.description || "Payment"} · {formatDistanceToNow(transaction.timestamp, { addSuffix: true })}
100 </p>
101 </div>
102 <p className="text-xl font-bold text-foreground">
103 -{transaction.currency} {transaction.amount.toFixed(2)}
104 </p>
105 </div>
106 </Card>
107 ))}
108 </div>
109 )}
110 </div>
111 </div>
112 </Layout>
113 );
114 };
115
116 export default Home;