Changes
gpt-engineer-app[bot] committed
Nov 27, 2025 at 14:09 UTC
d2550c5f3e5d25cf35c15d5fea48e52b4431ed7c
1 file changed
+267
-11
src/pages/CFOOverview.tsx
+267
-11
@@ -1,19 +1,275 @@
1
import { Button } from "@/components/ui/button";
2
-import { ArrowLeft } from "lucide-react";
2
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
3
+import { ArrowLeft, TrendingUp, TrendingDown, DollarSign, Users, CreditCard, AlertCircle, ArrowUpRight, ArrowDownRight } from "lucide-react";
4
import { Link } from "react-router-dom";
5
+import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, BarChart, Bar, PieChart, Pie, Cell } from "recharts";
6
+
7
+const monthlySpendData = [
8
+ { month: "Jan", spend: 125000, budget: 150000 },
9
+ { month: "Feb", spend: 142000, budget: 150000 },
10
+ { month: "Mar", spend: 138000, budget: 150000 },
11
+ { month: "Apr", spend: 156000, budget: 160000 },
12
+ { month: "May", spend: 149000, budget: 160000 },
13
+ { month: "Jun", spend: 167000, budget: 170000 },
14
+];
15
+
16
+const departmentSpend = [
17
+ { name: "Engineering", spend: 85000, color: "hsl(93, 72%, 67%)" },
18
+ { name: "Marketing", spend: 45000, color: "hsl(220, 26%, 14%)" },
19
+ { name: "Sales", spend: 38000, color: "hsl(220, 20%, 40%)" },
20
+ { name: "Operations", spend: 29000, color: "hsl(93, 60%, 55%)" },
21
+ { name: "HR", spend: 18000, color: "hsl(220, 13%, 65%)" },
22
+];
23
+
24
+const recentTransactions = [
25
+ { id: 1, vendor: "AWS Cloud Services", amount: 12450, category: "Infrastructure", date: "Nov 26, 2025", status: "completed" },
26
+ { id: 2, vendor: "Figma Enterprise", amount: 2400, category: "Software", date: "Nov 25, 2025", status: "completed" },
27
+ { id: 3, vendor: "Delta Airlines", amount: 3200, category: "Travel", date: "Nov 24, 2025", status: "pending" },
28
+ { id: 4, vendor: "WeWork Office Space", amount: 8500, category: "Facilities", date: "Nov 23, 2025", status: "completed" },
29
+ { id: 5, vendor: "HubSpot CRM", amount: 1800, category: "Software", date: "Nov 22, 2025", status: "completed" },
30
+];
31
32
const CFOOverview = () => {
33
+ const totalSpend = 167000;
34
+ const budgetTotal = 200000;
35
+ const budgetUsedPercent = (totalSpend / budgetTotal) * 100;
36
+
37
return (
7
- <div className="min-h-screen bg-background">
8
- <div className="container py-12">
9
- <Link to="/">
10
- <Button variant="ghost" className="mb-8">
11
- <ArrowLeft className="w-4 h-4 mr-2" />
12
- Back to Home
13
- </Button>
14
- </Link>
15
- <h1 className="text-4xl font-bold text-foreground">CFO Overview</h1>
16
- </div>
38
+ <div className="min-h-screen bg-muted/30">
39
+ {/* Header */}
40
+ <header className="bg-card border-b border-border sticky top-0 z-50">
41
+ <div className="container flex items-center justify-between h-16">
42
+ <div className="flex items-center gap-4">
43
+ <Link to="/">
44
+ <Button variant="ghost" size="sm" className="gap-2">
45
+ <ArrowLeft className="w-4 h-4" />
46
+ Back
47
+ </Button>
48
+ </Link>
49
+ <div className="h-6 w-px bg-border" />
50
+ <h1 className="text-xl font-semibold text-foreground">CFO Dashboard</h1>
51
+ </div>
52
+ <div className="flex items-center gap-3">
53
+ <Button variant="outline" size="sm">Export Report</Button>
54
+ <Button variant="default" size="sm" className="bg-primary text-primary-foreground">
55
+ Add Expense
56
+ </Button>
57
+ </div>
58
+ </div>
59
+ </header>
60
+
61
+ <main className="container py-8">
62
+ {/* Key Metrics */}
63
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
64
+ <Card className="animate-fade-up">
65
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
66
+ <CardTitle className="text-sm font-medium text-muted-foreground">Total Spend (Nov)</CardTitle>
67
+ <DollarSign className="w-4 h-4 text-muted-foreground" />
68
+ </CardHeader>
69
+ <CardContent>
70
+ <div className="text-2xl font-bold text-foreground">${totalSpend.toLocaleString()}</div>
71
+ <div className="flex items-center gap-1 mt-1">
72
+ <TrendingUp className="w-3 h-3 text-destructive" />
73
+ <span className="text-xs text-destructive">+12.5% from last month</span>
74
+ </div>
75
+ </CardContent>
76
+ </Card>
77
+
78
+ <Card className="animate-fade-up animation-delay-100">
79
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
80
+ <CardTitle className="text-sm font-medium text-muted-foreground">Budget Remaining</CardTitle>
81
+ <CreditCard className="w-4 h-4 text-muted-foreground" />
82
+ </CardHeader>
83
+ <CardContent>
84
+ <div className="text-2xl font-bold text-foreground">${(budgetTotal - totalSpend).toLocaleString()}</div>
85
+ <div className="w-full bg-muted rounded-full h-2 mt-2">
86
+ <div
87
+ className="bg-primary h-2 rounded-full transition-all"
88
+ style={{ width: `${budgetUsedPercent}%` }}
89
+ />
90
+ </div>
91
+ <span className="text-xs text-muted-foreground">{budgetUsedPercent.toFixed(0)}% of budget used</span>
92
+ </CardContent>
93
+ </Card>
94
+
95
+ <Card className="animate-fade-up animation-delay-200">
96
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
97
+ <CardTitle className="text-sm font-medium text-muted-foreground">Pending Approvals</CardTitle>
98
+ <AlertCircle className="w-4 h-4 text-muted-foreground" />
99
+ </CardHeader>
100
+ <CardContent>
101
+ <div className="text-2xl font-bold text-foreground">8</div>
102
+ <div className="flex items-center gap-1 mt-1">
103
+ <span className="text-xs text-muted-foreground">$24,500 awaiting review</span>
104
+ </div>
105
+ </CardContent>
106
+ </Card>
107
+
108
+ <Card className="animate-fade-up animation-delay-300">
109
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
110
+ <CardTitle className="text-sm font-medium text-muted-foreground">Active Cardholders</CardTitle>
111
+ <Users className="w-4 h-4 text-muted-foreground" />
112
+ </CardHeader>
113
+ <CardContent>
114
+ <div className="text-2xl font-bold text-foreground">47</div>
115
+ <div className="flex items-center gap-1 mt-1">
116
+ <TrendingUp className="w-3 h-3 text-primary" />
117
+ <span className="text-xs text-primary">+3 this month</span>
118
+ </div>
119
+ </CardContent>
120
+ </Card>
121
+ </div>
122
+
123
+ {/* Charts Row */}
124
+ <div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
125
+ {/* Monthly Spend Trend */}
126
+ <Card className="lg:col-span-2 animate-fade-up animation-delay-200">
127
+ <CardHeader>
128
+ <CardTitle className="text-lg">Monthly Spend vs Budget</CardTitle>
129
+ <CardDescription>Track your spending against monthly budgets</CardDescription>
130
+ </CardHeader>
131
+ <CardContent>
132
+ <div className="h-[300px]">
133
+ <ResponsiveContainer width="100%" height="100%">
134
+ <AreaChart data={monthlySpendData}>
135
+ <defs>
136
+ <linearGradient id="spendGradient" x1="0" y1="0" x2="0" y2="1">
137
+ <stop offset="5%" stopColor="hsl(93, 72%, 67%)" stopOpacity={0.3} />
138
+ <stop offset="95%" stopColor="hsl(93, 72%, 67%)" stopOpacity={0} />
139
+ </linearGradient>
140
+ </defs>
141
+ <CartesianGrid strokeDasharray="3 3" stroke="hsl(220, 13%, 91%)" />
142
+ <XAxis dataKey="month" stroke="hsl(220, 13%, 46%)" fontSize={12} />
143
+ <YAxis stroke="hsl(220, 13%, 46%)" fontSize={12} tickFormatter={(value) => `$${value / 1000}k`} />
144
+ <Tooltip
145
+ contentStyle={{
146
+ backgroundColor: "hsl(0, 0%, 100%)",
147
+ border: "1px solid hsl(220, 13%, 91%)",
148
+ borderRadius: "8px"
149
+ }}
150
+ formatter={(value: number) => [`$${value.toLocaleString()}`, '']}
151
+ />
152
+ <Area
153
+ type="monotone"
154
+ dataKey="spend"
155
+ stroke="hsl(93, 72%, 67%)"
156
+ strokeWidth={2}
157
+ fill="url(#spendGradient)"
158
+ name="Spend"
159
+ />
160
+ <Area
161
+ type="monotone"
162
+ dataKey="budget"
163
+ stroke="hsl(220, 26%, 14%)"
164
+ strokeWidth={2}
165
+ strokeDasharray="5 5"
166
+ fill="transparent"
167
+ name="Budget"
168
+ />
169
+ </AreaChart>
170
+ </ResponsiveContainer>
171
+ </div>
172
+ </CardContent>
173
+ </Card>
174
+
175
+ {/* Department Breakdown */}
176
+ <Card className="animate-fade-up animation-delay-300">
177
+ <CardHeader>
178
+ <CardTitle className="text-lg">Spend by Department</CardTitle>
179
+ <CardDescription>November breakdown</CardDescription>
180
+ </CardHeader>
181
+ <CardContent>
182
+ <div className="h-[180px] mb-4">
183
+ <ResponsiveContainer width="100%" height="100%">
184
+ <PieChart>
185
+ <Pie
186
+ data={departmentSpend}
187
+ cx="50%"
188
+ cy="50%"
189
+ innerRadius={50}
190
+ outerRadius={80}
191
+ paddingAngle={2}
192
+ dataKey="spend"
193
+ >
194
+ {departmentSpend.map((entry, index) => (
195
+ <Cell key={`cell-${index}`} fill={entry.color} />
196
+ ))}
197
+ </Pie>
198
+ <Tooltip formatter={(value: number) => `$${value.toLocaleString()}`} />
199
+ </PieChart>
200
+ </ResponsiveContainer>
201
+ </div>
202
+ <div className="space-y-2">
203
+ {departmentSpend.map((dept) => (
204
+ <div key={dept.name} className="flex items-center justify-between text-sm">
205
+ <div className="flex items-center gap-2">
206
+ <div className="w-3 h-3 rounded-full" style={{ backgroundColor: dept.color }} />
207
+ <span className="text-muted-foreground">{dept.name}</span>
208
+ </div>
209
+ <span className="font-medium text-foreground">${dept.spend.toLocaleString()}</span>
210
+ </div>
211
+ ))}
212
+ </div>
213
+ </CardContent>
214
+ </Card>
215
+ </div>
216
+
217
+ {/* Recent Transactions */}
218
+ <Card className="animate-fade-up animation-delay-400">
219
+ <CardHeader className="flex flex-row items-center justify-between">
220
+ <div>
221
+ <CardTitle className="text-lg">Recent Transactions</CardTitle>
222
+ <CardDescription>Latest company expenses</CardDescription>
223
+ </div>
224
+ <Button variant="ghost" size="sm" className="text-primary">
225
+ View All
226
+ <ArrowUpRight className="w-4 h-4 ml-1" />
227
+ </Button>
228
+ </CardHeader>
229
+ <CardContent>
230
+ <div className="overflow-x-auto">
231
+ <table className="w-full">
232
+ <thead>
233
+ <tr className="border-b border-border">
234
+ <th className="text-left py-3 px-4 text-sm font-medium text-muted-foreground">Vendor</th>
235
+ <th className="text-left py-3 px-4 text-sm font-medium text-muted-foreground">Category</th>
236
+ <th className="text-left py-3 px-4 text-sm font-medium text-muted-foreground">Date</th>
237
+ <th className="text-left py-3 px-4 text-sm font-medium text-muted-foreground">Status</th>
238
+ <th className="text-right py-3 px-4 text-sm font-medium text-muted-foreground">Amount</th>
239
+ </tr>
240
+ </thead>
241
+ <tbody>
242
+ {recentTransactions.map((tx) => (
243
+ <tr key={tx.id} className="border-b border-border last:border-0 hover:bg-muted/50 transition-colors">
244
+ <td className="py-4 px-4">
245
+ <span className="font-medium text-foreground">{tx.vendor}</span>
246
+ </td>
247
+ <td className="py-4 px-4">
248
+ <span className="text-sm text-muted-foreground">{tx.category}</span>
249
+ </td>
250
+ <td className="py-4 px-4">
251
+ <span className="text-sm text-muted-foreground">{tx.date}</span>
252
+ </td>
253
+ <td className="py-4 px-4">
254
+ <span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
255
+ tx.status === "completed"
256
+ ? "bg-primary/10 text-primary"
257
+ : "bg-secondary/10 text-secondary"
258
+ }`}>
259
+ {tx.status}
260
+ </span>
261
+ </td>
262
+ <td className="py-4 px-4 text-right">
263
+ <span className="font-semibold text-foreground">${tx.amount.toLocaleString()}</span>
264
+ </td>
265
+ </tr>
266
+ ))}
267
+ </tbody>
268
+ </table>
269
+ </div>
270
+ </CardContent>
271
+ </Card>
272
+ </main>
273
</div>
274
);
275
};