✨ Nouvelles fonctionnalités - Page de gestion des avenants (/staff/avenants) - Page de détail d'un avenant (/staff/avenants/[id]) - Création d'avenants (objet, durée, rémunération) - Génération automatique de PDF d'avenant - Signature électronique via DocuSeal (employeur puis salarié) - Changement manuel du statut d'un avenant - Suppression d'avenants 🔧 Routes API - POST /api/staff/amendments/create - Créer un avenant - POST /api/staff/amendments/generate-pdf - Générer le PDF - POST /api/staff/amendments/[id]/send-signature - Envoyer en signature - POST /api/staff/amendments/[id]/change-status - Changer le statut - POST /api/webhooks/docuseal-amendment - Webhook après signature employeur - GET /api/signatures-electroniques/avenants - Liste des avenants en signature 📧 Système email universel v2 - Migration vers le système universel v2 pour les emails d'avenants - Template 'signature-request-employee-amendment' pour salariés - Insertion automatique dans DynamoDB pour la Lambda - Mise à jour automatique du statut dans Supabase 🗄️ Base de données - Table 'avenants' avec tous les champs (objet, durée, rémunération) - Colonnes de notification (last_employer_notification_at, last_employee_notification_at) - Liaison avec cddu_contracts 🎨 Composants - AvenantDetailPageClient - Détail complet d'un avenant - ChangeStatusModal - Changement de statut manuel - SendSignatureModal - Envoi en signature - DeleteAvenantModal - Suppression avec confirmation - AvenantSuccessModal - Confirmation de création 📚 Documentation - AVENANT_EMAIL_SYSTEM_MIGRATION.md - Guide complet de migration 🐛 Corrections - Fix parsing défensif dans Lambda AWS - Fix récupération des données depuis DynamoDB - Fix statut MFA !== 'verified' au lieu de === 'unverified'
174 lines
7 KiB
TypeScript
174 lines
7 KiB
TypeScript
"use client";
|
|
|
|
import { X, Send, CheckCircle2 } from "lucide-react";
|
|
|
|
interface SendSignatureModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
onConfirm: () => void;
|
|
isSending: boolean;
|
|
success?: boolean;
|
|
avenantData: {
|
|
numero_avenant: string;
|
|
contractReference: string;
|
|
employeeName: string;
|
|
employeeEmail: string;
|
|
employerEmail: string;
|
|
};
|
|
}
|
|
|
|
export default function SendSignatureModal({
|
|
isOpen,
|
|
onClose,
|
|
onConfirm,
|
|
isSending,
|
|
success = false,
|
|
avenantData,
|
|
}: SendSignatureModalProps) {
|
|
if (!isOpen) return null;
|
|
|
|
return (
|
|
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
|
|
<div className="bg-white rounded-xl shadow-xl max-w-md w-full p-6 space-y-4">
|
|
{/* Header */}
|
|
<div className="flex items-start justify-between">
|
|
<div className="flex items-center gap-3">
|
|
<div className={`w-10 h-10 rounded-full flex items-center justify-center ${
|
|
success ? "bg-green-100" : "bg-orange-100"
|
|
}`}>
|
|
{success ? (
|
|
<CheckCircle2 className="h-5 w-5 text-green-600" />
|
|
) : (
|
|
<Send className="h-5 w-5 text-orange-600" />
|
|
)}
|
|
</div>
|
|
<div>
|
|
<h2 className="text-lg font-semibold text-slate-900">
|
|
{success ? "Envoi réussi !" : "Envoyer pour signature"}
|
|
</h2>
|
|
<p className="text-sm text-slate-600">
|
|
Avenant {avenantData.numero_avenant}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<button
|
|
onClick={onClose}
|
|
disabled={isSending}
|
|
className="p-1 hover:bg-slate-100 rounded transition-colors disabled:opacity-50"
|
|
>
|
|
<X className="h-5 w-5 text-slate-500" />
|
|
</button>
|
|
</div>
|
|
|
|
{success ? (
|
|
/* Message de succès */
|
|
<>
|
|
<div className="bg-green-50 border border-green-200 rounded-lg p-4">
|
|
<p className="text-sm text-slate-700 mb-3">
|
|
L'avenant a été envoyé avec succès pour signature électronique.
|
|
</p>
|
|
|
|
{/* Détails */}
|
|
<div className="space-y-2 text-xs">
|
|
<div className="flex justify-between">
|
|
<span className="text-slate-600">Email employeur :</span>
|
|
<span className="font-medium text-slate-900 truncate max-w-[200px]">{avenantData.employerEmail}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-slate-600">Statut :</span>
|
|
<span className="font-medium text-green-600">En attente signature employeur</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Actions succès */}
|
|
<div className="flex justify-end">
|
|
<button
|
|
onClick={onClose}
|
|
className="px-4 py-2 bg-slate-900 text-white rounded-lg hover:bg-slate-800 transition-colors"
|
|
>
|
|
Fermer
|
|
</button>
|
|
</div>
|
|
</>
|
|
) : (
|
|
/* Message initial */
|
|
<>
|
|
<div className="bg-orange-50 border border-orange-200 rounded-lg p-4">
|
|
<p className="text-sm text-slate-700 mb-3">
|
|
Vous êtes sur le point d'envoyer cet avenant pour signature électronique.
|
|
</p>
|
|
|
|
{/* Détails */}
|
|
<div className="space-y-2 text-xs">
|
|
<div className="flex justify-between">
|
|
<span className="text-slate-600">Contrat :</span>
|
|
<span className="font-medium text-slate-900">{avenantData.contractReference}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-slate-600">Salarié :</span>
|
|
<span className="font-medium text-slate-900">{avenantData.employeeName}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-slate-600">Email salarié :</span>
|
|
<span className="font-medium text-slate-900 truncate max-w-[200px]">{avenantData.employeeEmail}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-slate-600">Email employeur :</span>
|
|
<span className="font-medium text-slate-900 truncate max-w-[200px]">{avenantData.employerEmail}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Processus */}
|
|
<div className="bg-slate-50 border border-slate-200 rounded-lg p-4">
|
|
<h3 className="text-sm font-medium text-slate-900 mb-2">Processus de signature</h3>
|
|
<ol className="space-y-2 text-xs text-slate-600">
|
|
<li className="flex items-start gap-2">
|
|
<span className="flex-shrink-0 w-5 h-5 rounded-full bg-slate-200 flex items-center justify-center text-xs font-medium">1</span>
|
|
<span>L'employeur recevra un email avec le lien de signature</span>
|
|
</li>
|
|
<li className="flex items-start gap-2">
|
|
<span className="flex-shrink-0 w-5 h-5 rounded-full bg-slate-200 flex items-center justify-center text-xs font-medium">2</span>
|
|
<span>Après signature de l'employeur, le salarié recevra son lien</span>
|
|
</li>
|
|
<li className="flex items-start gap-2">
|
|
<span className="flex-shrink-0 w-5 h-5 rounded-full bg-slate-200 flex items-center justify-center text-xs font-medium">3</span>
|
|
<span>Vous serez notifié par email une fois toutes les signatures reçues</span>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
|
|
{/* Actions */}
|
|
<div className="flex gap-3">
|
|
<button
|
|
onClick={onClose}
|
|
disabled={isSending}
|
|
className="flex-1 px-4 py-2 border border-slate-300 text-slate-700 rounded-lg hover:bg-slate-50 transition-colors disabled:opacity-50"
|
|
>
|
|
Annuler
|
|
</button>
|
|
<button
|
|
onClick={onConfirm}
|
|
disabled={isSending}
|
|
className="flex-1 px-4 py-2 bg-orange-600 text-white rounded-lg hover:bg-orange-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center justify-center gap-2"
|
|
>
|
|
{isSending ? (
|
|
<>
|
|
<div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
|
|
Envoi en cours...
|
|
</>
|
|
) : (
|
|
<>
|
|
<Send className="h-4 w-4" />
|
|
Envoyer
|
|
</>
|
|
)}
|
|
</button>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|