import { auth } from "@/auth"; import { db } from "@/lib/db"; import { hasPermission } from "@/lib/permissions"; import { CREWING_ENABLED } from "@/lib/feature-flags"; import { canViewSalary, bankEpfValue, documentNumberValue } from "@/lib/crew-pii"; import { redirect, notFound } from "next/navigation"; import { CrewProfile } from "./crew-profile"; import type { Metadata } from "next"; export const metadata: Metadata = { title: "Crew profile" }; export default async function CrewProfilePage({ params }: { params: Promise<{ id: string }> }) { if (!CREWING_ENABLED) notFound(); const session = await auth(); if (!session?.user) redirect("/login"); const role = session.user.role; if (!hasPermission(role, "view_crew_records")) redirect("/dashboard"); const { id } = await params; const c = await db.crewMember.findUnique({ where: { id }, include: { currentRank: { select: { name: true } }, documents: { orderBy: { createdAt: "desc" } }, bankDetail: true, epfDetail: true, nextOfKin: { orderBy: { createdAt: "asc" } }, ppeIssues: { orderBy: { issuedDate: "desc" } }, experienceRecords: { orderBy: { fromDate: "desc" }, include: { rank: { select: { name: true } } } }, assignments: { where: { status: { not: "SIGNED_OFF" } }, orderBy: { signOnDate: "desc" }, take: 1, include: { vessel: { select: { name: true } }, site: { select: { name: true } }, salaryStructures: { orderBy: { effectiveFrom: "desc" } }, }, }, }, }); if (!c) notFound(); if (c.status !== "EMPLOYEE") notFound(); // the Candidates page handles non-crew const assignment = c.assignments[0] ?? null; const showSalary = canViewSalary(role); const currentSalary = assignment?.salaryStructures.find((s) => s.approvedById) ?? assignment?.salaryStructures[0] ?? null; const ranks = await db.rank.findMany({ where: { isActive: true }, orderBy: { name: "asc" }, select: { id: true, name: true } }); const appraisals = await db.appraisal.findMany({ where: { assignment: { crewMemberId: c.id } }, orderBy: { createdAt: "desc" }, select: { id: true, period: true, status: true, comments: true, ratings: true }, }); return ( ({ id: d.id, docType: d.docType, number: documentNumberValue(d.number, d.docType, role), issueDate: d.issueDate?.toISOString() ?? null, expiryDate: d.expiryDate?.toISOString() ?? null, verificationStatus: d.verificationStatus, hasFile: Boolean(d.fileKey), }))} bank={{ accountName: c.bankDetail?.accountName ?? null, accountNumber: bankEpfValue(c.bankDetail?.accountNumber, role), ifsc: c.bankDetail?.ifsc ?? null, bankName: c.bankDetail?.bankName ?? null, }} epf={{ uan: c.epfDetail?.uan ?? null, aadhaar: bankEpfValue(c.epfDetail?.aadhaarLast4, role), pfNumber: c.epfDetail?.pfNumber ?? null, }} nextOfKin={c.nextOfKin.map((n) => ({ id: n.id, name: n.name, relationship: n.relationship, phone: n.phone, address: n.address, isEmergency: n.isEmergency }))} ppe={c.ppeIssues.map((p) => ({ id: p.id, item: p.item, size: p.size, quantity: p.quantity, issuedDate: p.issuedDate.toISOString(), returnedDate: p.returnedDate?.toISOString() ?? null }))} experience={c.experienceRecords.map((e) => ({ id: e.id, vesselType: e.vesselType, rank: e.rank?.name ?? null, fromDate: e.fromDate?.toISOString() ?? null, toDate: e.toDate?.toISOString() ?? null, durationMonths: e.durationMonths, source: e.source }))} paystatus={{ showSalary, salary: showSalary && currentSalary ? { basic: Number(currentSalary.basic), rateBasis: currentSalary.rateBasis, victualingPerDay: Number(currentSalary.victualingPerDay), currency: currentSalary.currency } : null, }} ranks={ranks} perms={{ editRecords: hasPermission(role, "upload_crew_records"), issuePpe: hasPermission(role, "issue_ppe"), }} signOff={{ assignmentId: assignment?.id ?? null, canSignOff: hasPermission(role, "sign_off_crew") && Boolean(assignment) }} appraisals={appraisals.map((a) => ({ id: a.id, period: a.period, status: a.status, comments: a.comments, ratings: (a.ratings ?? null) as { competence: number | null; conduct: number | null; safety: number | null } | null, }))} appraisalCtx={{ assignmentId: assignment?.id ?? null, canRaise: hasPermission(role, "raise_appraisal") && Boolean(assignment) }} /> ); }