"use client"; import { useRef, useState } from "react"; import { useRouter } from "next/navigation"; import type { CandidateSource } from "@prisma/client"; import { AdminDialog } from "@/components/ui/admin-dialog"; import { addCandidate, updateCandidate } from "./actions"; import { SOURCE_OPTIONS, SOURCE_LABEL } from "./candidate-ui"; const INPUT = "w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20"; type RankOpt = { id: string; code: string; name: string }; export type EditableCandidate = { id: string; name: string; source: CandidateSource; appliedRankId: string | null; currentRankId: string | null; experienceMonths: number; vesselTypeExperience: string | null; email: string | null; phone: string | null; notes: string | null; }; function CandidateFields({ ranks, state, set, fileRef, }: { ranks: RankOpt[]; state: FieldState; set: (k: K, v: FieldState[K]) => void; fileRef: React.RefObject; }) { return (
set("name", e.target.value)} required />
set("experienceMonths", e.target.value)} />
set("vesselTypeExperience", e.target.value)} placeholder="e.g. Dredger" />
set("email", e.target.value)} />
set("phone", e.target.value)} />
set("notes", e.target.value)} placeholder="Optional" />
); } type FieldState = { name: string; source: CandidateSource; appliedRankId: string; currentRankId: string; experienceMonths: string; vesselTypeExperience: string; email: string; phone: string; notes: string; }; function emptyState(): FieldState { return { name: "", source: "CAREERS", appliedRankId: "", currentRankId: "", experienceMonths: "0", vesselTypeExperience: "", email: "", phone: "", notes: "", }; } function stateFrom(c: EditableCandidate): FieldState { return { name: c.name, source: c.source, appliedRankId: c.appliedRankId ?? "", currentRankId: c.currentRankId ?? "", experienceMonths: String(c.experienceMonths), vesselTypeExperience: c.vesselTypeExperience ?? "", email: c.email ?? "", phone: c.phone ?? "", notes: c.notes ?? "", }; } function buildFormData(state: FieldState, file: File | undefined, id?: string): FormData { const fd = new FormData(); if (id) fd.set("id", id); fd.set("name", state.name); fd.set("source", state.source); if (state.appliedRankId) fd.set("appliedRankId", state.appliedRankId); if (state.currentRankId) fd.set("currentRankId", state.currentRankId); fd.set("experienceMonths", state.experienceMonths || "0"); if (state.vesselTypeExperience) fd.set("vesselTypeExperience", state.vesselTypeExperience); if (state.email) fd.set("email", state.email); if (state.phone) fd.set("phone", state.phone); if (state.notes) fd.set("notes", state.notes); if (file && file.size > 0) fd.set("cv", file); return fd; } export function AddCandidateButton({ ranks }: { ranks: RankOpt[] }) { const router = useRouter(); const [open, setOpen] = useState(false); const [pending, setPending] = useState(false); const [error, setError] = useState(""); const [state, setState] = useState(emptyState); const fileRef = useRef(null); const set = (k: K, v: FieldState[K]) => setState((s) => ({ ...s, [k]: v })); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setPending(true); setError(""); const result = await addCandidate(buildFormData(state, fileRef.current?.files?.[0])); setPending(false); if ("error" in result) { setError(result.error); } else { setOpen(false); setState(emptyState()); if (fileRef.current) fileRef.current.value = ""; router.refresh(); } } return ( <> setOpen(false)}>
{error &&

{error}

}
); } export function EditCandidateButton({ candidate, ranks, open, onOpenChange, }: { candidate: EditableCandidate; ranks: RankOpt[]; open: boolean; onOpenChange: (v: boolean) => void; }) { const router = useRouter(); const [pending, setPending] = useState(false); const [error, setError] = useState(""); const [state, setState] = useState(() => stateFrom(candidate)); const fileRef = useRef(null); const set = (k: K, v: FieldState[K]) => setState((s) => ({ ...s, [k]: v })); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setPending(true); setError(""); const result = await updateCandidate(buildFormData(state, fileRef.current?.files?.[0], candidate.id)); setPending(false); if ("error" in result) { setError(result.error); } else { onOpenChange(false); router.refresh(); } } return ( onOpenChange(false)}>
{error &&

{error}

}
); }