173 lines
6.2 KiB
TypeScript
173 lines
6.2 KiB
TypeScript
import { useState } from "react";
|
|
import {
|
|
BarChart3,
|
|
Calendar,
|
|
Clock,
|
|
Database,
|
|
FileText,
|
|
PlusCircle,
|
|
Search,
|
|
User,
|
|
Users,
|
|
} from "lucide-react";
|
|
import { Link } from "react-router-dom";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "@/components/ui/card";
|
|
import { Input } from "@/components/ui/input";
|
|
import {
|
|
Tabs,
|
|
TabsContent,
|
|
TabsList,
|
|
TabsTrigger,
|
|
} from "@/components/ui/tabs";
|
|
|
|
import Header from "../layout/Header";
|
|
import Sidebar from "../layout/Sidebar";
|
|
import RecentActivityList from "../common/RecentActivity";
|
|
import StatCard from "../common/StatCard";
|
|
|
|
export default function DashboardPage() {
|
|
const [searchQuery, setSearchQuery] = useState("");
|
|
|
|
return (
|
|
<div className="flex min-h-dvh bg-neutral-50">
|
|
<Sidebar />
|
|
<div className="flex-1">
|
|
<Header title="Dashboard" />
|
|
<main className="p-6">
|
|
<div className="mb-8">
|
|
<h1 className="text-3xl font-serif font-bold text-neutral-800 mb-2">
|
|
Welcome, Admin
|
|
</h1>
|
|
<p className="text-neutral-600">
|
|
Here's an overview of your Italian Migrants Database
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-4 mb-8">
|
|
<StatCard
|
|
title="Total Migrants"
|
|
value="1,248"
|
|
description="+12 this month"
|
|
icon={<Users className="size-5 text-green-600" />}
|
|
/>
|
|
<StatCard
|
|
title="Recent Additions"
|
|
value="24"
|
|
description="Last 30 days"
|
|
icon={<PlusCircle className="size-5 text-blue-600" />}
|
|
/>
|
|
<StatCard
|
|
title="Pending Reviews"
|
|
value="8"
|
|
description="Needs attention"
|
|
icon={<Clock className="size-5 text-amber-600" />}
|
|
/>
|
|
<StatCard
|
|
title="Total Documents"
|
|
value="3,542"
|
|
description="Photos and records"
|
|
icon={<FileText className="size-5 text-red-600" />}
|
|
/>
|
|
</div>
|
|
|
|
<div className="grid gap-6 md:grid-cols-2 mb-8">
|
|
<Card>
|
|
<CardHeader className="pb-2">
|
|
<CardTitle className="text-xl font-serif">Quick Search</CardTitle>
|
|
<CardDescription>Find migrant records quickly</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="relative">
|
|
<Search className="absolute left-3 top-2.5 size-5 text-neutral-500" />
|
|
<Input
|
|
placeholder="Search by name, birthplace, or arrival date..."
|
|
className="pl-10 border-neutral-300"
|
|
value={searchQuery}
|
|
onChange={(e) => setSearchQuery(e.target.value)}
|
|
/>
|
|
</div>
|
|
<div className="mt-4 flex flex-wrap gap-2">
|
|
<Button variant="outline" size="sm" className="text-sm">
|
|
<Calendar className="mr-1 size-4" /> By Date
|
|
</Button>
|
|
<Button variant="outline" size="sm" className="text-sm">
|
|
<User className="mr-1 size-4" /> By Name
|
|
</Button>
|
|
<Button variant="outline" size="sm" className="text-sm">
|
|
<Database className="mr-1 size-4" /> Advanced
|
|
</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader className="pb-2">
|
|
<CardTitle className="text-xl font-serif">Migration Trends</CardTitle>
|
|
<CardDescription>Yearly migration patterns</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="pt-4">
|
|
<div className="h-[180px] flex items-end justify-between gap-2">
|
|
{[35, 45, 20, 30, 75, 60, 40, 80, 90, 50].map((height, i) => (
|
|
<div key={i} className="relative group flex flex-col items-center">
|
|
<div className="absolute -top-7 opacity-0 group-hover:opacity-100 transition-opacity bg-neutral-800 text-white px-2 py-1 rounded text-xs">
|
|
{1950 + i * 5}: {height} migrants
|
|
</div>
|
|
<div
|
|
className="w-7 bg-gradient-to-t from-green-600 to-green-400 rounded-t"
|
|
style={{ height: `${height * 1.8}px` }}
|
|
></div>
|
|
<span className="text-xs mt-1 text-neutral-500">{1950 + i * 5}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
<div className="mb-8">
|
|
<Tabs defaultValue="recent">
|
|
<div className="flex justify-between items-center mb-4">
|
|
<TabsList className="bg-neutral-100">
|
|
<TabsTrigger value="recent">Recent Activity</TabsTrigger>
|
|
<TabsTrigger value="pending">Pending Reviews</TabsTrigger>
|
|
</TabsList>
|
|
<Link to="/admin/migrants">
|
|
<Button variant="outline" size="sm" className="text-sm">
|
|
View All Records
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
<TabsContent value="recent" className="m-0">
|
|
<Card>
|
|
<CardContent className="p-0">
|
|
<RecentActivityList />
|
|
</CardContent>
|
|
</Card>
|
|
</TabsContent>
|
|
<TabsContent value="pending" className="m-0">
|
|
<Card>
|
|
<CardContent className="p-6">
|
|
<div className="text-center py-8 text-neutral-500">
|
|
<BarChart3 className="mx-auto size-12 mb-4 text-neutral-400" />
|
|
<h3 className="text-lg font-medium mb-2">No Pending Reviews</h3>
|
|
<p>All migrant records have been reviewed.</p>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</TabsContent>
|
|
</Tabs>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|