You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
8.9 KiB
TypeScript

import { prisma } from "@/lib/prisma";
import {
Users,
BarChart3,
Wallet,
Clock,
ArrowUpRight,
} from "lucide-react";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { formatCurrency } from "@/lib/utils";
import Link from "next/link";
export default async function AdminDashboard() {
const [pendingReimbursements, pendingOvertime, totalBudget, recentTransactions] = await Promise.all([
prisma.reimbursement.count({ where: { status: 'PENDING' } }),
prisma.overtime.count({ where: { status: 'PENDING' } }),
prisma.budget.aggregate({ _sum: { amount: true } }),
prisma.companyTransaction.findMany({
orderBy: { date: 'desc' },
take: 5
})
]);
const totalPending = pendingReimbursements + pendingOvertime;
return (
<div className="space-y-10 animate-in fade-in slide-in-from-bottom-4 duration-700">
<div className="flex flex-col md:flex-row md:items-center justify-between gap-6">
<div>
<h2 className="text-4xl font-extrabold tracking-tight text-neutral-900 dark:text-white">Admin Console</h2>
<p className="text-neutral-500 mt-2 font-medium text-lg">Real-time overview of company finances and worker requests.</p>
</div>
<Link href="/admin/approvals">
<Button className="bg-emerald-600 hover:bg-emerald-700 text-white rounded-2xl h-14 px-8 font-black shadow-2xl shadow-emerald-200 dark:shadow-none transition-all active:scale-95 flex items-center gap-2">
<Users className="w-5 h-5" />
Review Requests ({totalPending})
</Button>
</Link>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{[
{ label: 'Total Budget Allocated', value: formatCurrency(totalBudget._sum.amount?.toString() || '0'), icon: Wallet, color: 'emerald', trend: '+5.2% vs last month' },
{ label: 'Pending Approvals', value: totalPending.toString(), icon: Clock, color: 'amber', trend: `${pendingReimbursements} claims, ${pendingOvertime} OT` },
{ label: 'Monthly Revenue', value: formatCurrency(245000), icon: BarChart3, color: 'indigo', trend: 'On track for Q1' },
{ label: 'Active Personnel', value: '142', icon: Users, color: 'violet', trend: '+3 new this week' },
].map((stat, i) => (
<Card key={i} className="group border-none shadow-2xl shadow-black/5 bg-white dark:bg-neutral-900 rounded-[2.5rem] p-8 hover:-translate-y-2 transition-all duration-500 overflow-hidden relative">
<div className="relative z-10">
<div className={`w-14 h-14 rounded-2xl bg-neutral-50 dark:bg-neutral-800 flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-500`}>
<stat.icon className={`w-7 h-7 text-neutral-900 dark:text-neutral-100`} />
</div>
<p className="text-xs font-black text-neutral-400 uppercase tracking-widest mb-1">{stat.label}</p>
<div className="flex items-baseline gap-2">
<h3 className="text-3xl font-black text-neutral-900 dark:text-neutral-100">{stat.value}</h3>
</div>
<p className="mt-4 text-[10px] font-bold text-neutral-500 flex items-center gap-1">
{stat.trend}
</p>
</div>
</Card>
))}
</div>
<div className="grid grid-cols-1 xl:grid-cols-3 gap-8">
<Card className="xl:col-span-2 border-none shadow-2xl shadow-black/5 bg-white dark:bg-neutral-900 rounded-[3rem] p-10 overflow-hidden">
<div className="flex items-center justify-between mb-10">
<h3 className="text-2xl font-black tracking-tight">Financial Ledger</h3>
<Link href="/admin/ledger">
<Button variant="ghost" className="text-emerald-600 font-bold hover:bg-emerald-50 rounded-xl px-4 py-2">View Full Ledger</Button>
</Link>
</div>
<div className="space-y-6">
{(recentTransactions as any[]).map((tx) => (
<div key={tx.id} className="flex items-center justify-between p-6 rounded-[2rem] hover:bg-neutral-50 dark:hover:bg-neutral-800/50 transition-all group border border-transparent hover:border-neutral-100 dark:hover:border-neutral-800">
<div className="flex items-center gap-6">
<div className={`w-14 h-14 rounded-2xl ${tx.type === 'DEBIT' ? 'bg-rose-50 text-rose-600' : 'bg-emerald-50 text-emerald-600'} flex items-center justify-center font-black shadow-sm`}>
{tx.type === 'DEBIT' ? '-' : '+'}
</div>
<div>
<p className="font-bold text-lg text-neutral-900 dark:text-neutral-100">{tx.description}</p>
<p className="text-xs text-neutral-400 font-medium">{new Date(tx.date).toLocaleDateString()}</p>
</div>
</div>
<div className="text-right">
<p className={`font-black text-xl ${tx.type === 'DEBIT' ? 'text-rose-600' : 'text-emerald-600'}`}>
{tx.type === 'DEBIT' ? '-' : '+'}{formatCurrency(tx.amount.toString())}
</p>
<span className="text-[10px] font-black uppercase text-neutral-400">Success</span>
</div>
</div>
))}
</div>
</Card>
<div className="space-y-8">
<Card className="border-none shadow-2xl shadow-emerald-500/10 bg-gradient-to-br from-emerald-600 to-teal-700 rounded-[3rem] p-10 text-white relative overflow-hidden group">
<div className="relative z-10">
<h3 className="text-xl font-bold mb-6 flex items-center gap-2">
<BarChart3 className="w-5 h-5" />
Budget Health
</h3>
<p className="text-emerald-100 font-medium leading-relaxed mb-8 text-sm">
Total budget utilization is at <span className="text-white font-bold text-lg">68%</span>. Marketing and Sales are nearing their monthly limits.
</p>
<Link href="/admin/budgeting">
<Button className="w-full bg-white text-emerald-700 hover:bg-emerald-50 rounded-2xl h-14 font-black shadow-xl transition-all active:scale-95">
Manage Budgets
</Button>
</Link>
</div>
</Card>
<Card className="border-none shadow-2xl shadow-black/5 bg-white dark:bg-neutral-900 rounded-[3rem] p-10">
<h3 className="text-xl font-black mb-8">Departmental Spend</h3>
<div className="space-y-6">
{[
{ label: 'Marketing', value: 85, color: 'bg-emerald-500' },
{ label: 'Engineering', value: 62, color: 'bg-indigo-500' },
{ label: 'Operations', value: 48, color: 'bg-violet-500' },
].map((item) => (
<div key={item.label} className="space-y-2">
<div className="flex justify-between text-sm font-bold">
<span className="text-neutral-500">{item.label}</span>
<span className={item.value > 80 ? 'text-rose-500' : ''}>{item.value}%</span>
</div>
<div className="w-full h-2 bg-neutral-100 dark:bg-neutral-800 rounded-full overflow-hidden">
<div className={`h-full ${item.color} rounded-full transition-all duration-1000`} style={{ width: `${item.value}%` }} />
</div>
</div>
))}
</div>
</Card>
</div>
</div>
</div>
);
}