migrants-nt-web/src/components/admin/AdminDashboard.tsx

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