"use client"; import { useState, useEffect, useCallback } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { ArrowLeft, Printer, Download, Loader2 } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { fetchPayslip } from "@/lib/supabase/payroll-actions"; import { STATUS_LABELS, STATUS_COLORS, formatDateShort, type PayslipWithEmployee, } from "@/lib/supabase/payroll-types"; import PageSkeleton from "./PageSkeleton"; function formatDateLong(dateStr: string): string { return new Date(dateStr + "T00:00:00").toLocaleDateString("en-AU", { weekday: "long", day: "numeric", month: "long", year: "numeric", }); } export default function PayslipDetailPage() { const router = useRouter(); const searchParams = useSearchParams(); const runId = searchParams.get("run"); const employeeId = searchParams.get("emp"); const periodStart = searchParams.get("ps"); const periodEnd = searchParams.get("pe"); const [payslip, setPayslip] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { if (!runId || !employeeId) { setError("Missing payslip parameters"); setLoading(false); return; } let cancelled = false; fetchPayslip(runId, employeeId) .then((p) => { if (!cancelled) { if (p) setPayslip(p); else setError("Payslip not found"); } }) .catch(() => { if (!cancelled) setError("Failed to load payslip"); }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, [runId, employeeId]); const handlePrint = useCallback(() => { window.print(); }, []); if (loading) return ; if (!payslip || error) { return (

Payslip

{error || "Payslip not found"}
); } const employeeName = `${payslip.employee?.first_name || ""} ${payslip.employee?.last_name || ""}`.trim(); return (
{/* Header - hidden when printing */}

Payslip

{employeeName}

{/* Payslip Content - print-optimised */}
{/* Payslip Header */}

Vela

Payslip

{employeeName}

{payslip.employee?.job_title || ""}

{/* Pay Period & Status */}

Pay Period

{periodStart && periodEnd ? `${formatDateLong(periodStart)} — ${formatDateLong(periodEnd)}` : `Payslip #${payslip.id.slice(0, 8)}`}

Processed
{/* Earnings */}

Earnings

Gross Pay {payslip.hours_worked && ` (${payslip.hours_worked} hours`}{payslip.hourly_rate ? ` @ ${payslip.hourly_rate.toFixed(2)}/hr)` : ")"} {payslip.gross_pay.toFixed(2)}
{/* Deductions */} {payslip.deduction_lines && payslip.deduction_lines.length > 0 && (

Deductions

{payslip.deduction_lines.map((line, i) => (
{line.name} {line.description && (

{line.description}

)}
-{line.amount.toFixed(2)}
))}
Total Deductions -{payslip.total_deductions.toFixed(2)}
)} {/* Net Pay */}
Net Pay {payslip.net_pay.toFixed(2)}
{/* Employer Contributions */} {payslip.employer_contribution_lines && payslip.employer_contribution_lines.length > 0 && (

Employer Contributions (not deducted from pay)

{payslip.employer_contribution_lines.map((line, i) => (
{line.name} {line.description && (

{line.description}

)}
{line.amount.toFixed(2)}
))}
Total Employer {payslip.employer_contributions.toFixed(2)}
)} {/* Footer */}

Generated on {new Date().toLocaleDateString("en-AU", { day: "numeric", month: "long", year: "numeric" })} · Vela Payroll

); }