stock / src /pages /Reports.tsx
Zelyanoth's picture
Upload 101 files
24d40b9 verified
import { useState } from "react";
import {
BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer,
PieChart, Pie, Cell
} from "recharts";
import { ChevronDown } from "lucide-react";
import AppLayout from "@/components/layout/AppLayout";
import Header from "@/components/shared/Header";
import { cn } from "@/lib/utils";
// Mock data for reports
const monthlyData = [
{ name: "Jan", expenses: 1200, income: 3500 },
{ name: "Feb", expenses: 1800, income: 3500 },
{ name: "Mar", expenses: 1400, income: 3500 },
{ name: "Apr", expenses: 1300, income: 3800 },
{ name: "May", expenses: 1900, income: 3800 },
{ name: "Jun", expenses: 1700, income: 3800 },
{ name: "Jul", expenses: 1500, income: 4000 },
{ name: "Aug", expenses: 1600, income: 4000 },
{ name: "Sep", expenses: 1400, income: 4000 },
{ name: "Oct", expenses: 1800, income: 4200 },
{ name: "Nov", expenses: 2000, income: 4200 },
{ name: "Dec", expenses: 2500, income: 4200 },
];
const categoryData = [
{ name: "Food", value: 1200, color: "#FF6384" },
{ name: "Housing", value: 1800, color: "#36A2EB" },
{ name: "Transport", value: 800, color: "#FFCE56" },
{ name: "Utilities", value: 500, color: "#4BC0C0" },
{ name: "Shopping", value: 700, color: "#9966FF" },
{ name: "Healthcare", value: 300, color: "#FF9F40" },
];
const Reports = () => {
const [reportType, setReportType] = useState<"income-expense" | "categories">("income-expense");
const [timeframe, setTimeframe] = useState<"monthly" | "yearly">("monthly");
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0,
maximumFractionDigits: 0,
}).format(value);
};
return (
<AppLayout>
<div className="max-w-md mx-auto">
<Header
title="Reports"
subtitle="Analyze your financial data"
/>
<div className="px-4 pb-6 space-y-6 animate-fade-in">
<div className="flex space-x-2">
<button
onClick={() => setReportType("income-expense")}
className={cn(
"flex-1 py-2.5 text-center text-sm font-medium rounded-lg transition-colors",
reportType === "income-expense"
? "bg-primary text-white"
: "bg-secondary text-foreground hover:bg-secondary/80"
)}
>
Income & Expenses
</button>
<button
onClick={() => setReportType("categories")}
className={cn(
"flex-1 py-2.5 text-center text-sm font-medium rounded-lg transition-colors",
reportType === "categories"
? "bg-primary text-white"
: "bg-secondary text-foreground hover:bg-secondary/80"
)}
>
Categories
</button>
</div>
<div className="flex items-center justify-between">
<h3 className="font-medium">
{reportType === "income-expense" ? "Income & Expenses" : "Spending by Category"}
</h3>
{reportType === "income-expense" && (
<div className="relative inline-block text-left">
<button
className="flex items-center space-x-1 text-sm bg-secondary px-3 py-1.5 rounded-lg"
onClick={() => setTimeframe(timeframe === "monthly" ? "yearly" : "monthly")}
>
<span>{timeframe === "monthly" ? "Monthly" : "Yearly"}</span>
<ChevronDown size={14} />
</button>
</div>
)}
</div>
<div className="h-72 w-full bg-card rounded-xl border border-border p-4">
{reportType === "income-expense" ? (
<ResponsiveContainer width="100%" height="100%">
<BarChart
data={monthlyData}
margin={{ top: 10, right: 10, left: 0, bottom: 20 }}
barGap={0}
barSize={timeframe === "monthly" ? 12 : 24}
>
<CartesianGrid strokeDasharray="3 3" vertical={false} stroke="#eee" />
<XAxis
dataKey="name"
axisLine={false}
tickLine={false}
fontSize={12}
tickMargin={8}
/>
<YAxis
axisLine={false}
tickLine={false}
fontSize={12}
tickFormatter={formatCurrency}
width={60}
/>
<Tooltip
formatter={(value) => formatCurrency(value as number)}
contentStyle={{
borderRadius: '8px',
border: '1px solid #eee',
boxShadow: '0px 4px 12px rgba(0, 0, 0, 0.08)'
}}
/>
<Bar dataKey="income" fill="#4ade80" radius={[4, 4, 0, 0]} />
<Bar dataKey="expenses" fill="#f87171" radius={[4, 4, 0, 0]} />
</BarChart>
</ResponsiveContainer>
) : (
<ResponsiveContainer width="100%" height="100%">
<PieChart>
<Pie
data={categoryData}
cx="50%"
cy="50%"
innerRadius={60}
outerRadius={90}
paddingAngle={2}
dataKey="value"
label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`}
labelLine={false}
>
{categoryData.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} />
))}
</Pie>
<Tooltip
formatter={(value) => formatCurrency(value as number)}
contentStyle={{
borderRadius: '8px',
border: '1px solid #eee',
boxShadow: '0px 4px 12px rgba(0, 0, 0, 0.08)'
}}
/>
</PieChart>
</ResponsiveContainer>
)}
</div>
<div className="space-y-3">
<h3 className="font-medium">Summary</h3>
<div className="grid grid-cols-2 gap-3">
<div className="bg-card rounded-xl border border-border p-4">
<p className="text-sm text-muted-foreground">Total Income</p>
<p className="text-2xl font-semibold text-green-500">$46,000</p>
</div>
<div className="bg-card rounded-xl border border-border p-4">
<p className="text-sm text-muted-foreground">Total Expenses</p>
<p className="text-2xl font-semibold text-red-500">$19,100</p>
</div>
<div className="bg-card rounded-xl border border-border p-4 col-span-2">
<p className="text-sm text-muted-foreground">Net Savings</p>
<p className="text-2xl font-semibold text-primary">$26,900</p>
<p className="text-xs text-muted-foreground mt-1">58% of income saved</p>
</div>
</div>
</div>
</div>
</div>
</AppLayout>
);
};
export default Reports;