espace-paie-odentas/app/(app)/contrats/[id]/edit/formulaire/page.tsx
2025-10-12 17:05:46 +02:00

155 lines
5.8 KiB
TypeScript

"use client";
import { useParams, useRouter } from "next/navigation";
import { useQuery } from "@tanstack/react-query";
import { useMemo } from "react";
import { Loader2 } from "lucide-react";
import { NouveauCDDUForm } from "@/components/contrats/NouveauCDDUForm";
// shape minimal du contrat retourné par /api/contrats/[id]
type ContratDetail = {
id: string;
numero?: string;
regime?: "CDDU_MONO" | "CDDU_MULTI" | string;
production?: string;
objet?: string | null;
numero_objet?: string | null;
salarie?: { nom?: string[] | string };
salarie_matricule?: string[] | string;
profession?: string | null;
categorie_prof?: "Technicien" | "Artiste" | string | null;
type_salaire?: "Brut" | "Net avant PAS" | "Coût total employeur" | "Minimum conventionnel" | string;
salaire_demande?: string | number | null;
date_debut?: string;
date_fin?: string;
nb_representations?: number;
nb_services_repetition?: number;
jours_travailles?: string | null;
// etc. -> complète si besoin
};
export default function EditFormulairePage() {
const { id } = useParams<{ id: string }>();
const router = useRouter();
const { data, isLoading, isError, error } = useQuery({
queryKey: ["contrat-detail", id],
queryFn: async (): Promise<ContratDetail> => {
const resp = await fetch(`/api/contrats/${id}`, {
credentials: "include",
headers: { Accept: "application/json" },
cache: "no-store",
});
if (resp.status === 401) throw new Error("access_denied");
if (resp.status === 404) throw new Error("not_found");
if (!resp.ok) throw new Error(`http_${resp.status}`);
return resp.json();
},
staleTime: 10_000,
});
const prefill = useMemo(() => {
if (!data) return undefined;
// normalise salarie.nom (tableau -> string)
const salarieNom =
Array.isArray(data.salarie?.nom) ? data.salarie?.nom.join(", ") : (data.salarie?.nom as string | undefined);
// normalise matricule (tableau -> string)
const salarieMatricule =
Array.isArray(data.salarie_matricule) ? data.salarie_matricule[0] : (data.salarie_matricule as string | undefined);
return {
spectacle: data.production || "",
numero_objet: data.numero_objet || (data as any).objet || null,
salarie: salarieMatricule && salarieNom ? { matricule: salarieMatricule, nom: salarieNom } : null,
categorie: (data.categorie_prof as any) === "Technicien" ? "Technicien" : "Artiste",
profession: data.profession ? { label: data.profession, code: undefined } : null,
date_debut: data.date_debut || "",
date_fin: data.date_fin || "",
nb_representations: (data as any).nb_representations ?? "",
nb_services_repetition: (data as any).nb_services_repetition ?? "",
jours_travail: (data as any).jours_travailles || "",
nb_heures_annexes: (data as any).nb_heures_annexes ?? (data as any).nb_heures_aem ?? undefined,
type_salaire:
(data.type_salaire as any) === "Net avant PAS" ||
(data.type_salaire as any) === "Coût total employeur" ||
(data.type_salaire as any) === "Minimum conventionnel"
? (data.type_salaire as any)
: "Brut",
montant: data.salaire_demande ? Number(data.salaire_demande) : "",
reference: data.numero || undefined,
multi_mois: data.regime === "CDDU_MULTI",
} as const;
}, [data]);
async function patchContrat(payload: any) {
// tu peux ici restreindre aux champs modifiables
const res = await fetch(`/api/contrats/${id}`, {
method: "PATCH",
credentials: "include",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify({
// envoie un PATCH “propre” (ne mets que ce qui est utile côté Lambda)
regime: payload.regime,
multi_mois: payload.multi_mois,
production: payload.spectacle,
numero_objet: payload.numero_objet,
salarie_matricule: payload.salarie.matricule,
salarie_nom: payload.salarie.nom,
categorie_prof: payload.categorie_professionnelle,
profession: payload.profession,
profession_code: payload.profession_code,
date_debut: payload.date_debut,
date_fin: payload.date_fin,
nb_representations: payload.nb_representations,
nb_services_repetition: payload.nb_services_repetition,
dates_representations: payload.dates_representations,
dates_repetitions: payload.dates_repetitions,
heures_travail: payload.heures_travail,
minutes_travail: payload.minutes_travail,
jours_travail: payload.jours_travail,
type_salaire: payload.type_salaire,
montant: payload.montant,
panier_repas: payload.panier_repas,
reference: payload.reference,
notes: payload.notes,
// Optionnel : valider_direct si tu veux déclencher un statut
// valider_direct: payload.valider_direct,
}),
});
if (res.status === 404) throw new Error("not_found");
if (!res.ok) throw new Error(`http_${res.status}: ${await res.text()}`);
// succès → retour à la fiche
router.push(`/contrats/${id}`);
}
if (isLoading) {
return (
<div className="p-6">
<Loader2 className="w-5 h-5 animate-spin inline mr-2" />
Chargement du contrat
</div>
);
}
if (isError || !data) {
return <div className="p-6 text-rose-600">Impossible de charger le contrat.</div>;
}
return (
<div className="p-4">
<div className="mb-4 rounded-xl border p-4">
<div className="text-lg font-semibold">Modifier la demande</div>
<div className="text-sm text-slate-600">
Contrat <strong>{data.numero || data.id}</strong>
</div>
</div>
<NouveauCDDUForm
prefill={prefill}
onSubmitOverride={patchContrat}
contractIdForNotes={id}
/>
</div>
);
}