espace-paie-odentas/components/staff/amendments/UpdateSignatureStatusModal.tsx

216 lines
7.9 KiB
TypeScript

"use client";
import { useState } from "react";
import { X, Check, Clock, AlertCircle } from "lucide-react";
interface UpdateSignatureStatusModalProps {
isOpen: boolean;
onClose: () => void;
onConfirm: (newSignatureStatus: string) => void;
currentSignatureStatus?: string;
isUpdating: boolean;
numeroAvenant: string;
}
export default function UpdateSignatureStatusModal({
isOpen,
onClose,
onConfirm,
currentSignatureStatus = "not_sent",
isUpdating,
numeroAvenant,
}: UpdateSignatureStatusModalProps) {
const [selectedStatus, setSelectedStatus] = useState<string>(currentSignatureStatus);
if (!isOpen) return null;
const statusOptions = [
{
value: "not_sent",
label: "Non envoyé",
description: "L'avenant n'a pas encore été envoyé en signature",
icon: Clock,
color: "slate",
},
{
value: "pending_employer",
label: "En attente employeur",
description: "L'avenant est en attente de signature par l'employeur",
icon: Clock,
color: "orange",
},
{
value: "pending_employee",
label: "En attente salarié",
description: "L'employeur a signé, en attente de la signature du salarié",
icon: Clock,
color: "blue",
},
{
value: "signed",
label: "Signé",
description: "L'avenant a été signé par toutes les parties",
icon: Check,
color: "green",
},
];
const getColorClasses = (color: string, isSelected: boolean) => {
const colors: Record<string, { border: string; bg: string; text: string }> = {
slate: {
border: isSelected ? "border-slate-500" : "border-slate-200",
bg: isSelected ? "bg-slate-50" : "bg-white",
text: "text-slate-700",
},
orange: {
border: isSelected ? "border-orange-500" : "border-orange-200",
bg: isSelected ? "bg-orange-50" : "bg-white",
text: "text-orange-700",
},
blue: {
border: isSelected ? "border-blue-500" : "border-blue-200",
bg: isSelected ? "bg-blue-50" : "bg-white",
text: "text-blue-700",
},
green: {
border: isSelected ? "border-green-500" : "border-green-200",
bg: isSelected ? "bg-green-50" : "bg-white",
text: "text-green-700",
},
};
return colors[color] || colors.slate;
};
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
<div className="bg-white rounded-xl shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
{/* Header */}
<div className="flex items-center justify-between p-6 border-b">
<div>
<h2 className="text-xl font-bold text-slate-900">
Mettre à jour le statut de signature
</h2>
<p className="text-sm text-slate-600 mt-1">
Avenant {numeroAvenant}
</p>
</div>
<button
onClick={onClose}
disabled={isUpdating}
className="p-2 hover:bg-slate-100 rounded-lg transition-colors disabled:opacity-50"
>
<X className="h-5 w-5 text-slate-400" />
</button>
</div>
{/* Content */}
<div className="p-6 space-y-4">
{/* Avertissement */}
<div className="flex gap-3 p-4 bg-amber-50 border border-amber-200 rounded-lg">
<AlertCircle className="h-5 w-5 text-amber-600 flex-shrink-0 mt-0.5" />
<div className="text-sm text-amber-900">
<div className="font-semibold mb-1">Action manuelle</div>
<div>
Cette action permet de forcer manuellement le statut de signature de l'avenant.
Utilisez cette fonction uniquement si nécessaire (par exemple, en cas de signature
papier ou de problème technique).
</div>
</div>
</div>
{/* Statut actuel */}
<div className="p-4 bg-slate-50 border border-slate-200 rounded-lg">
<div className="text-sm font-medium text-slate-900 mb-1">
Statut actuel
</div>
<div className="text-sm text-slate-600">
{statusOptions.find((s) => s.value === currentSignatureStatus)?.label || currentSignatureStatus}
</div>
</div>
{/* Options de statut */}
<div>
<div className="text-sm font-medium text-slate-900 mb-3">
Nouveau statut
</div>
<div className="space-y-3">
{statusOptions.map((status) => {
const isSelected = selectedStatus === status.value;
const colors = getColorClasses(status.color, isSelected);
const Icon = status.icon;
return (
<button
key={status.value}
onClick={() => setSelectedStatus(status.value)}
disabled={isUpdating}
className={`w-full text-left p-4 border-2 rounded-lg transition-all disabled:opacity-50 disabled:cursor-not-allowed ${colors.border} ${colors.bg} hover:shadow-md`}
>
<div className="flex items-start gap-3">
<div className={`flex-shrink-0 w-10 h-10 rounded-lg flex items-center justify-center ${colors.bg} border ${colors.border}`}>
<Icon className={`h-5 w-5 ${colors.text}`} />
</div>
<div className="flex-1 min-w-0">
<div className={`font-medium ${colors.text} flex items-center gap-2`}>
{status.label}
{isSelected && (
<Check className="h-4 w-4 text-indigo-600" />
)}
</div>
<div className="text-sm text-slate-600 mt-1">
{status.description}
</div>
</div>
</div>
</button>
);
})}
</div>
</div>
{/* Explication des statuts */}
<div className="p-4 bg-blue-50 border border-blue-200 rounded-lg">
<div className="text-sm text-blue-900">
<div className="font-semibold mb-2">Flux normal de signature :</div>
<ol className="list-decimal list-inside space-y-1 text-xs">
<li>L'avenant est créé (statut : Non envoyé)</li>
<li>L'avenant est envoyé à l'employeur (statut : En attente employeur)</li>
<li>L'employeur signe (statut : En attente salarié)</li>
<li>Le salarié signe (statut : Signé)</li>
</ol>
</div>
</div>
</div>
{/* Footer */}
<div className="flex items-center justify-between gap-3 p-6 border-t bg-slate-50">
<div className="text-sm text-slate-600">
{selectedStatus !== currentSignatureStatus ? (
<span className="font-medium text-slate-900">
Le statut sera modifié
</span>
) : (
<span>Aucun changement</span>
)}
</div>
<div className="flex gap-3">
<button
onClick={onClose}
disabled={isUpdating}
className="px-4 py-2 text-slate-700 hover:bg-slate-200 rounded-lg transition-colors font-medium disabled:opacity-50"
>
Annuler
</button>
<button
onClick={() => onConfirm(selectedStatus)}
disabled={isUpdating || selectedStatus === currentSignatureStatus}
className="px-6 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors font-medium disabled:opacity-50 disabled:cursor-not-allowed"
>
{isUpdating ? "Mise à jour..." : "Confirmer"}
</button>
</div>
</div>
</div>
</div>
);
}