diff --git a/app/(protected)/capa-owner/page.tsx b/app/(protected)/capa-owner/page.tsx index 3e88711..7b9f2f0 100644 --- a/app/(protected)/capa-owner/page.tsx +++ b/app/(protected)/capa-owner/page.tsx @@ -1,9 +1,121 @@ -// app/(protected)/capa-owner/page.tsx -export default function CapaOwnerHome() { +export const dynamic = 'force-dynamic' + +import Link from 'next/link' +import { createClient } from '@/lib/supabase/server' +import { redirect } from 'next/navigation' +import { StatCard } from '@/components/dashboard/stat-card' + +const STATUS_LABELS: Record = { + open: 'Open', + in_progress: 'In Progress', + overdue: 'Overdue', + pending_verification: 'Pending Verification', + verified: 'Verified', + reopened: 'Reopened', + closed: 'Closed', +} + +const STATUS_COLORS: Record = { + open: 'bg-gray-100 text-gray-700', + in_progress: 'bg-blue-100 text-blue-700', + overdue: 'bg-red-100 text-red-700', + pending_verification: 'bg-purple-100 text-purple-700', + verified: 'bg-green-100 text-green-700', + reopened: 'bg-orange-100 text-orange-700', + closed: 'bg-gray-100 text-gray-500', +} + +export default async function CapaOwnerPage() { + const supabase = await createClient() + const { data: { user } } = await supabase.auth.getUser() + if (!user) redirect('/login') + + const { data: profile } = await supabase.from('users').select('name, role').eq('id', user.id).single() + if (!profile || !['capa_owner', 'admin', 'hse', 'supervisor'].includes(profile.role)) redirect('/') + + const { data: capas } = await supabase + .from('capa_actions') + .select('id, description, due_date, priority, status, incident_id, incidents (reference_no)') + .eq('owner_user_id', user.id) + .order('due_date', { ascending: true }) + + const rows = capas ?? [] + const openCount = rows.filter(c => ['open', 'in_progress', 'reopened'].includes(c.status)).length + const overdueCount = rows.filter(c => c.status === 'overdue').length + const doneCount = rows.filter(c => ['verified', 'closed'].includes(c.status)).length + + const PRIORITY_COLORS: Record = { + high: 'text-red-600 font-semibold', + med: 'text-orange-500 font-medium', + low: 'text-gray-400', + } + + const activeRows = rows.filter(c => !['verified', 'closed'].includes(c.status)) + const doneRows = rows.filter(c => ['verified', 'closed'].includes(c.status)) + return ( -
-

CAPA Owner Dashboard

-

Phase 2: CAPA board coming here.

+
+

My CAPAs

+ +
+ 0 ? 'yellow' : 'green'} /> + 0 ? 'red' : 'green'} /> + +
+ + {activeRows.length === 0 ? ( +
+

No active CAPAs assigned to you.

+
+ ) : ( +
+ {activeRows.map(capa => { + const incRef = (capa.incidents as unknown as { reference_no: string | null } | null)?.reference_no + const isOverdue = capa.status === 'overdue' + return ( +
+
+
+

{capa.description}

+ {incRef && ( + + {incRef} + + )} +
+
+ + {STATUS_LABELS[capa.status] ?? capa.status} + +

+ {capa.due_date ? `Due ${new Date(capa.due_date as string).toLocaleDateString('en-MY')}` : 'No due date'} +

+

+ {(capa.priority as string)?.toUpperCase()} priority +

+
+
+
+ ) + })} +
+ )} + + {doneRows.length > 0 && ( +
+

Completed ({doneCount})

+
+ {doneRows.map(capa => ( +
+

{capa.description}

+ + {STATUS_LABELS[capa.status] ?? capa.status} + +
+ ))} +
+
+ )}
) }