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 };