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.
107 lines
6.3 KiB
TypeScript
107 lines
6.3 KiB
TypeScript
import { auth } from "@/auth";
|
|
import { prisma } from "@/lib/prisma";
|
|
import { submitReimbursement } from "@/app/lib/actions";
|
|
import { ReimbursementForm } from "./reimbursement-form";
|
|
import {
|
|
CheckCircle2,
|
|
Clock,
|
|
Tag,
|
|
Calendar,
|
|
Search,
|
|
Filter
|
|
} from "lucide-react";
|
|
import { Card } from "@/components/ui/card";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Button } from "@/components/ui/button";
|
|
import { formatCurrency } from "@/lib/utils";
|
|
|
|
export default async function ReimbursementsPage() {
|
|
const session = await auth();
|
|
const userId = (session?.user as any)?.id;
|
|
|
|
const reimbursements = await prisma.reimbursement.findMany({
|
|
where: { userId },
|
|
orderBy: { createdAt: 'desc' }
|
|
});
|
|
|
|
return (
|
|
<div className="space-y-8 animate-in fade-in slide-in-from-bottom-2 duration-500">
|
|
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
|
<div>
|
|
<h2 className="text-3xl font-bold tracking-tight">Reimbursements</h2>
|
|
<p className="text-neutral-500 mt-1">Manage and track your business expense claims.</p>
|
|
</div>
|
|
<ReimbursementForm />
|
|
</div>
|
|
|
|
<Card className="border-none shadow-2xl shadow-black/5 bg-white dark:bg-neutral-900 rounded-3xl overflow-hidden">
|
|
<div className="p-8 flex flex-col md:flex-row md:items-center justify-between gap-4 border-b border-neutral-100 dark:border-neutral-800">
|
|
<div className="relative flex-1 max-w-md">
|
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-neutral-400" />
|
|
<Input placeholder="Search claims..." className="pl-10 rounded-xl bg-neutral-50 dark:bg-neutral-800 border-none shadow-none" />
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<Button variant="outline" className="rounded-xl border-neutral-200 flex items-center gap-2">
|
|
<Filter className="w-4 h-4" />
|
|
Filter
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full text-left border-collapse">
|
|
<thead>
|
|
<tr className="bg-neutral-50/50 dark:bg-neutral-800/50">
|
|
<th className="p-4 px-8 text-xs font-bold uppercase tracking-wider text-neutral-500">Status</th>
|
|
<th className="p-4 text-xs font-bold uppercase tracking-wider text-neutral-500">Details</th>
|
|
<th className="p-4 text-xs font-bold uppercase tracking-wider text-neutral-500">Category</th>
|
|
<th className="p-4 text-xs font-bold uppercase tracking-wider text-neutral-500">Date</th>
|
|
<th className="p-4 px-8 text-xs font-bold uppercase tracking-wider text-neutral-500 text-right">Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-neutral-100 dark:divide-neutral-800">
|
|
{reimbursements.map((item) => (
|
|
<tr key={item.id} className="hover:bg-neutral-50 dark:hover:bg-neutral-800 transition-colors group cursor-pointer">
|
|
<td className="p-4 px-8">
|
|
<div className="flex items-center gap-2">
|
|
{item.status === 'PAID' && <CheckCircle2 className="w-4 h-4 text-emerald-500" />}
|
|
{item.status === 'APPROVED' && <div className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse" />}
|
|
{item.status === 'PENDING' && <Clock className="w-4 h-4 text-amber-500" />}
|
|
<span className={`text-[10px] font-bold uppercase px-2 py-1 rounded-full ${item.status === 'PAID' ? 'bg-emerald-100 text-emerald-700' :
|
|
item.status === 'APPROVED' ? 'bg-indigo-100 text-indigo-700' :
|
|
'bg-amber-100 text-amber-700'
|
|
}`}>
|
|
{item.status}
|
|
</span>
|
|
</div>
|
|
</td>
|
|
<td className="p-4">
|
|
<p className="font-semibold text-neutral-900 dark:text-neutral-100">{item.description}</p>
|
|
<p className="text-[10px] text-neutral-400 uppercase tracking-tight">Ref: #{item.id.slice(-8)}</p>
|
|
</td>
|
|
<td className="p-4 border-none">
|
|
<span className="inline-flex items-center gap-1 text-sm text-neutral-500">
|
|
<Tag className="w-3 h-3" />
|
|
{item.category}
|
|
</span>
|
|
</td>
|
|
<td className="p-4 border-none">
|
|
<span className="inline-flex items-center gap-1 text-sm text-neutral-500">
|
|
<Calendar className="w-3 h-3" />
|
|
{new Date(item.createdAt).toLocaleDateString()}
|
|
</span>
|
|
</td>
|
|
<td className="p-4 px-8 border-none text-right">
|
|
<span className="font-bold text-lg text-neutral-900 dark:text-neutral-100">
|
|
{formatCurrency(item.amount.toString())}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|