216 lines
7.9 KiB
TypeScript
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>
|
|
);
|
|
}
|