Seed: dashboard template (24 files)

This commit is contained in:
2026-07-23 22:10:33 +00:00
parent cb7b7162d4
commit ad9e4d06f4
+226
View File
@@ -0,0 +1,226 @@
import { useState } from "react";
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from "recharts";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Separator } from "@/components/ui/separator";
import {
DollarSign, Users, ShoppingCart, TrendingUp, TrendingDown,
ArrowUpRight, ArrowDownRight, MoreHorizontal, Eye,
FileText, UserPlus, BarChart3, Download
} from "lucide-react";
import Sidebar from "@/components/Sidebar";
import Header from "@/components/Header";
const kpiCards = [
{
title: "Total Revenue",
value: "$48.5K",
change: "+12.5%",
trend: "up" as const,
icon: DollarSign,
color: "text-sky-600 bg-sky-100",
},
{
title: "Active Users",
value: "2,438",
change: "+8.2%",
trend: "up" as const,
icon: Users,
color: "text-orange-600 bg-orange-100",
},
{
title: "Total Orders",
value: "1,256",
change: "+23.1%",
trend: "up" as const,
icon: ShoppingCart,
color: "text-emerald-600 bg-emerald-100",
},
{
title: "Conversion Rate",
value: "3.2%",
change: "+0.5%",
trend: "up" as const,
icon: TrendingUp,
color: "text-violet-600 bg-violet-100",
},
];
const recentOrders = [
{ id: "#ORD-7291", customer: "Sarah Mitchell", amount: "$234.50", status: "Completed", statusColor: "bg-emerald-100 text-emerald-700", date: "Apr 10, 2026" },
{ id: "#ORD-7290", customer: "James Cooper", amount: "$891.00", status: "Processing", statusColor: "bg-sky-100 text-sky-700", date: "Apr 10, 2026" },
{ id: "#ORD-7289", customer: "Emily Zhang", amount: "$156.25", status: "Completed", statusColor: "bg-emerald-100 text-emerald-700", date: "Apr 9, 2026" },
{ id: "#ORD-7288", customer: "Michael Brown", amount: "$432.80", status: "Pending", statusColor: "bg-amber-100 text-amber-700", date: "Apr 9, 2026" },
{ id: "#ORD-7287", customer: "Lisa Anderson", amount: "$67.90", status: "Cancelled", statusColor: "bg-red-100 text-red-700", date: "Apr 8, 2026" },
];
const activityFeed = [
{ user: "SM", name: "Sarah Mitchell", action: "placed a new order for $234.50", time: "2 minutes ago" },
{ user: "JC", name: "James Cooper", action: "upgraded to the Pro plan", time: "15 minutes ago" },
{ user: "EZ", name: "Emily Zhang", action: "submitted a support ticket", time: "1 hour ago" },
{ user: "MB", name: "Michael Brown", action: "updated their billing information", time: "3 hours ago" },
{ user: "LA", name: "Lisa Anderson", action: "cancelled order #ORD-7287", time: "5 hours ago" },
];
const revenueData = [
{ month: "Jan", revenue: 4200 }, { month: "Feb", revenue: 5400 }, { month: "Mar", revenue: 4800 },
{ month: "Apr", revenue: 6200 }, { month: "May", revenue: 5800 }, { month: "Jun", revenue: 7500 },
{ month: "Jul", revenue: 6800 }, { month: "Aug", revenue: 8200 }, { month: "Sep", revenue: 7600 },
{ month: "Oct", revenue: 9500 }, { month: "Nov", revenue: 8800 }, { month: "Dec", revenue: 10200 },
];
export default function IndexPage() {
return (
<div className="flex min-h-screen bg-slate-50">
<Sidebar activePath="/" />
<div className="flex-1 lg:ml-64">
<Header />
<main className="p-6 space-y-8">
{/* ── Quick Actions ── */}
<div className="flex flex-wrap gap-3">
<Button variant="outline" size="sm" className="active:scale-[0.98] transition-all">
<FileText className="mr-2 h-4 w-4 text-sky-600" /> Create Report
</Button>
<Button variant="outline" size="sm" className="active:scale-[0.98] transition-all">
<UserPlus className="mr-2 h-4 w-4 text-emerald-600" /> Add User
</Button>
<Button variant="outline" size="sm" className="active:scale-[0.98] transition-all">
<BarChart3 className="mr-2 h-4 w-4 text-orange-600" /> View Analytics
</Button>
<Button variant="outline" size="sm" className="active:scale-[0.98] transition-all">
<Download className="mr-2 h-4 w-4 text-violet-600" /> Export Data
</Button>
</div>
{/* ── KPI Cards ── */}
<div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-6 stagger">
{kpiCards.map((kpi) => (
<Card key={kpi.title} className="border-0 shadow-sm hover:shadow-lg hover:-translate-y-0.5 transition-all duration-300 backdrop-blur-sm bg-card/80">
<CardContent className="p-6">
<div className="flex items-center justify-between">
<div className={`flex items-center justify-center h-12 w-12 rounded-xl \${kpi.color}`}>
<kpi.icon className="h-6 w-6" />
</div>
<div className={`flex items-center gap-1 text-sm font-medium \${kpi.trend === "up" ? "text-emerald-600" : "text-red-600"}`}>
{kpi.trend === "up" ? <TrendingUp className="h-3.5 w-3.5" /> : <TrendingDown className="h-3.5 w-3.5" />}
{kpi.change}
</div>
</div>
<div className="mt-4">
<p className="text-2xl font-bold text-slate-900">{kpi.value}</p>
<p className="text-sm text-slate-500 mt-1">{kpi.title}</p>
<div className="mt-2 h-8 bg-gradient-to-r from-primary/5 to-primary/20 rounded" />
</div>
</CardContent>
</Card>
))}
</div>
{/* ── Revenue Chart ── */}
<Card className="border-0 shadow-sm animate-scale-in">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<div>
<CardTitle className="text-lg font-semibold text-slate-900">Revenue Overview</CardTitle>
<CardDescription>Monthly revenue performance for the current year</CardDescription>
</div>
<div className="flex items-center gap-2">
<Button variant="outline" size="sm" className="text-xs active:scale-[0.98]">7D</Button>
<Button variant="outline" size="sm" className="text-xs bg-sky-50 text-sky-700 border-sky-200 active:scale-[0.98]">30D</Button>
<Button variant="outline" size="sm" className="text-xs active:scale-[0.98]">90D</Button>
</div>
</CardHeader>
<CardContent className="pt-4">
<ResponsiveContainer width="100%" height={300}>
<BarChart data={revenueData}>
<defs>
<linearGradient id="barGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="hsl(var(--primary))" stopOpacity={0.8} />
<stop offset="100%" stopColor="hsl(var(--primary))" stopOpacity={0.2} />
</linearGradient>
</defs>
<CartesianGrid strokeDasharray="3 3" stroke="hsl(var(--border))" opacity={0.3} />
<XAxis dataKey="month" stroke="hsl(var(--muted-foreground))" fontSize={12} />
<YAxis stroke="hsl(var(--muted-foreground))" fontSize={12} />
<Tooltip />
<Bar dataKey="revenue" fill="url(#barGrad)" radius={[4,4,0,0]} />
</BarChart>
</ResponsiveContainer>
</CardContent>
</Card>
{/* ── Orders + Activity ── */}
<div className="grid grid-cols-1 xl:grid-cols-3 gap-6">
{/* Recent Orders */}
<Card className="xl:col-span-2 border-0 shadow-sm">
<CardHeader className="flex flex-row items-center justify-between">
<div>
<CardTitle className="text-lg font-semibold text-slate-900">Recent Orders</CardTitle>
<CardDescription>Latest customer orders and their status</CardDescription>
</div>
<Button variant="outline" size="sm" className="text-xs active:scale-[0.98]">
View All <ArrowUpRight className="ml-1 h-3 w-3" />
</Button>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow className="border-slate-100">
<TableHead className="text-slate-500 font-medium">Order</TableHead>
<TableHead className="text-slate-500 font-medium">Customer</TableHead>
<TableHead className="text-slate-500 font-medium">Amount</TableHead>
<TableHead className="text-slate-500 font-medium">Status</TableHead>
<TableHead className="text-slate-500 font-medium">Date</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{recentOrders.map((order) => (
<TableRow key={order.id} className="border-slate-100 hover:bg-muted/50 transition-colors">
<TableCell className="font-medium text-slate-900">{order.id}</TableCell>
<TableCell className="text-slate-600">{order.customer}</TableCell>
<TableCell className="font-medium text-slate-900">{order.amount}</TableCell>
<TableCell>
<Badge variant="secondary" className={`\${order.statusColor} border-0 font-medium`}>
{order.status}
</Badge>
</TableCell>
<TableCell className="text-slate-500">{order.date}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
</Card>
{/* Activity Feed */}
<Card className="border-0 shadow-sm">
<CardHeader>
<CardTitle className="text-lg font-semibold text-slate-900">Recent Activity</CardTitle>
<CardDescription>Latest actions across your workspace</CardDescription>
</CardHeader>
<CardContent className="space-y-5 stagger">
{activityFeed.map((item, i) => (
<div key={i} className="flex items-start gap-3">
<Avatar className="h-9 w-9 bg-sky-100 text-sky-700">
<AvatarFallback className="text-xs font-semibold bg-sky-100 text-sky-700">{item.user}</AvatarFallback>
</Avatar>
<div className="flex-1 min-w-0">
<p className="text-sm text-slate-700">
<span className="font-medium text-slate-900">{item.name}</span>{" "}
{item.action}
</p>
<p className="text-xs text-slate-400 mt-0.5">{item.time}</p>
</div>
</div>
))}
</CardContent>
</Card>
</div>
</main>
</div>
</div>
);
}