import { prisma } from "@/lib/db"; import Link from "next/link"; export const dynamic = "force-dynamic"; const STATUSES = ["prospect", "reviewing", "tailoring", "ready", "applied", "interviewing", "offer", "rejected", "dead"]; const STAGE_CONFIG: Record< string, { label: string; description: string; color: string; badge: string; border: string; bgActive: string } > = { prospect: { label: "Prospect", description: "Saved positions", color: "bg-zinc-400 dark:bg-zinc-500", badge: "bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-300", border: "border-zinc-200 dark:border-zinc-800 hover:border-zinc-400 dark:hover:border-zinc-600", bgActive: "bg-zinc-50 dark:bg-zinc-800/40", }, reviewing: { label: "Reviewing", description: "Evaluating fit", color: "bg-amber-500", badge: "bg-amber-100 text-amber-800 dark:bg-amber-950/80 dark:text-amber-300", border: "border-amber-200/80 dark:border-amber-900/60 hover:border-amber-400 dark:hover:border-amber-600", bgActive: "bg-amber-50/50 dark:bg-amber-950/20", }, tailoring: { label: "Tailoring", description: "Customizing resume", color: "bg-purple-500", badge: "bg-purple-100 text-purple-800 dark:bg-purple-950/80 dark:text-purple-300", border: "border-purple-200/80 dark:border-purple-900/60 hover:border-purple-400 dark:hover:border-purple-600", bgActive: "bg-purple-50/50 dark:bg-purple-950/20", }, ready: { label: "Ready", description: "Ready to submit", color: "bg-blue-500", badge: "bg-blue-100 text-blue-800 dark:bg-blue-950/80 dark:text-blue-300", border: "border-blue-200/80 dark:border-blue-900/60 hover:border-blue-400 dark:hover:border-blue-600", bgActive: "bg-blue-50/50 dark:bg-blue-950/20", }, applied: { label: "Applied", description: "Application sent", color: "bg-indigo-500", badge: "bg-indigo-100 text-indigo-800 dark:bg-indigo-950/80 dark:text-indigo-300", border: "border-indigo-200/80 dark:border-indigo-900/60 hover:border-indigo-400 dark:hover:border-indigo-600", bgActive: "bg-indigo-50/50 dark:bg-indigo-950/20", }, interviewing: { label: "Interviewing", description: "In discussions", color: "bg-teal-500", badge: "bg-teal-100 text-teal-800 dark:bg-teal-950/80 dark:text-teal-300", border: "border-teal-200/80 dark:border-teal-900/60 hover:border-teal-400 dark:hover:border-teal-600", bgActive: "bg-teal-50/50 dark:bg-teal-950/20", }, offer: { label: "Offer", description: "Offer received", color: "bg-emerald-500", badge: "bg-emerald-100 text-emerald-800 dark:bg-emerald-950/80 dark:text-emerald-300", border: "border-emerald-200/80 dark:border-emerald-900/60 hover:border-emerald-400 dark:hover:border-emerald-600", bgActive: "bg-emerald-50/50 dark:bg-emerald-950/20", }, rejected: { label: "Rejected", description: "Not selected", color: "bg-rose-500", badge: "bg-rose-100 text-rose-800 dark:bg-rose-950/80 dark:text-rose-300", border: "border-rose-200/80 dark:border-rose-900/60 hover:border-rose-400 dark:hover:border-rose-600", bgActive: "bg-rose-50/50 dark:bg-rose-950/20", }, dead: { label: "Dead", description: "Closed / Inactive", color: "bg-zinc-400", badge: "bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400", border: "border-zinc-200/80 dark:border-zinc-800 hover:border-zinc-400 dark:hover:border-zinc-600", bgActive: "bg-zinc-50 dark:bg-zinc-800/30", }, }; export default async function Dashboard() { const jobs = await prisma.job.findMany({ orderBy: { updatedAt: "desc" }, take: 5, }); const totalJobsCount = await prisma.job.count(); const allJobs = await prisma.job.findMany({ select: { status: true, phEligibility: true } }); const apps = await prisma.application.count(); const resumes = await prisma.resume.count(); const byStatus = Object.fromEntries(STATUSES.map((s) => [s, allJobs.filter((j) => j.status === s).length])); const phYes = allJobs.filter((j) => j.phEligibility === "yes").length; const statCards = [ { label: "Total Jobs Tracked", value: totalJobsCount, sub: "All pipeline opportunities", icon: ( ), iconBg: "bg-indigo-50 dark:bg-indigo-950/60 border-indigo-100 dark:border-indigo-900/50", }, { label: "PH-Eligible Roles", value: phYes, sub: `${totalJobsCount > 0 ? Math.round((phYes / totalJobsCount) * 100) : 0}% of all positions`, icon: ( ), iconBg: "bg-emerald-50 dark:bg-emerald-950/60 border-emerald-100 dark:border-emerald-900/50", }, { label: "Tailored Resumes", value: resumes, sub: "AI-customized versions", icon: ( ), iconBg: "bg-purple-50 dark:bg-purple-950/60 border-purple-100 dark:border-purple-900/50", }, { label: "Applications Sent", value: apps, sub: "Active submissions", icon: ( ), iconBg: "bg-blue-50 dark:bg-blue-950/60 border-blue-100 dark:border-blue-900/50", }, ]; return (
{/* Header & Quick Action */}

Dashboard

Track applications, monitor your hiring pipeline, and tailor resumes with AI.

View all jobs Add Job (AI parse)
{/* Stat Cards Grid */}
{statCards.map((card) => (
{card.label}
{card.icon}
{card.value}

{card.sub}

))}
{/* Visual Pipeline Section */}

Application Pipeline

Click any stage to filter jobs by status

{totalJobsCount} total opportunities
{/* Pipeline Stage Cards */}
{STATUSES.map((s) => { const count = byStatus[s] ?? 0; const config = STAGE_CONFIG[s] || { label: s, description: "", color: "bg-zinc-400", badge: "bg-zinc-100 text-zinc-700", border: "border-zinc-200", bgActive: "bg-zinc-50", }; const hasItems = count > 0; return (
{count}
{config.label}
{config.description}
); })}
{/* Recent Jobs Preview */} {jobs.length > 0 && (

Recently Updated Jobs

View all ({totalJobsCount}) →
{jobs.map((j) => (
{j.title}

{j.company} · {j.location ?? "Remote"}

{j.status}
))}
)}
); }