187 lines
7.1 KiB
TypeScript
187 lines
7.1 KiB
TypeScript
// components/staff/BulkESignConfirmModal.tsx
|
|
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import { X, FileSignature, AlertTriangle, Mail } from "lucide-react";
|
|
|
|
type Contract = {
|
|
id: string;
|
|
contract_number?: string | null;
|
|
employee_name?: string | null;
|
|
employee_id?: string | null;
|
|
org_id?: string | null;
|
|
structure?: string | null;
|
|
salaries?: {
|
|
salarie?: string | null;
|
|
nom?: string | null;
|
|
prenom?: string | null;
|
|
adresse_mail?: string | null;
|
|
} | null;
|
|
};
|
|
|
|
type BulkESignConfirmModalProps = {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
onConfirm: (sendNotification: boolean) => void;
|
|
contractCount: number;
|
|
selectedContracts?: Contract[];
|
|
};
|
|
|
|
export default function BulkESignConfirmModal({
|
|
isOpen,
|
|
onClose,
|
|
onConfirm,
|
|
contractCount,
|
|
selectedContracts = []
|
|
}: BulkESignConfirmModalProps) {
|
|
const [sendNotification, setSendNotification] = useState(true);
|
|
const [employerEmails, setEmployerEmails] = useState<Record<string, string>>({});
|
|
|
|
// Charger les emails au montage
|
|
useEffect(() => {
|
|
if (!isOpen || selectedContracts.length === 0) return;
|
|
|
|
const fetchEmails = async () => {
|
|
const orgIds = [...new Set(selectedContracts.map(c => c.org_id).filter(Boolean))];
|
|
const emails: Record<string, string> = {};
|
|
|
|
try {
|
|
const response = await fetch('/api/staff/organizations/emails', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ org_ids: orgIds }),
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
// data est un array de { org_id, email_signature }
|
|
data.forEach((org: any) => {
|
|
if (org.org_id && org.email_signature) {
|
|
emails[org.org_id] = org.email_signature;
|
|
}
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error('Erreur lors de la récupération des emails de signature:', error);
|
|
}
|
|
|
|
setEmployerEmails(emails);
|
|
};
|
|
|
|
fetchEmails();
|
|
}, [isOpen, selectedContracts]);
|
|
|
|
if (!isOpen) return null;
|
|
|
|
return (
|
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
|
<div className="bg-white rounded-lg p-6 w-full max-w-2xl max-h-[90vh] overflow-y-auto">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div className="flex items-center gap-2">
|
|
<FileSignature className="size-5 text-indigo-600" />
|
|
<h2 className="text-lg font-semibold">Confirmer l'envoi des signatures</h2>
|
|
</div>
|
|
<button
|
|
onClick={onClose}
|
|
className="p-1 hover:bg-gray-100 rounded"
|
|
>
|
|
<X className="size-5" />
|
|
</button>
|
|
</div>
|
|
|
|
{/* Warning Message */}
|
|
<div className="mb-4 p-3 bg-amber-50 border border-amber-200 rounded-lg flex gap-3">
|
|
<AlertTriangle className="size-5 text-amber-600 flex-shrink-0 mt-0.5" />
|
|
<div className="text-sm text-amber-800">
|
|
<p className="font-medium mb-1">Attention</p>
|
|
<p>
|
|
Vous êtes sur le point de créer les signatures électroniques pour{" "}
|
|
<strong>{contractCount}</strong> contrat{contractCount > 1 ? 's' : ''}.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Info */}
|
|
<div className="mb-4 text-sm text-gray-600 space-y-2">
|
|
<p className="font-medium">Cette action va :</p>
|
|
<ul className="list-disc list-inside space-y-1 ml-2">
|
|
<li>Créer une demande de signature électronique pour chaque contrat</li>
|
|
{sendNotification && <li className="text-indigo-600 font-medium">Envoyer un email récapitulatif au client</li>}
|
|
</ul>
|
|
<p className="mt-3 font-medium text-gray-700">
|
|
Assurez-vous que tous les contrats ont un PDF généré et que les salariés ont un email renseigné.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Contracts Summary with Emails */}
|
|
{selectedContracts.length > 0 && (
|
|
<div className="mb-6 p-4 bg-indigo-50 border border-indigo-200 rounded-lg">
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Mail className="size-4 text-indigo-600" />
|
|
<p className="text-sm font-medium text-indigo-900">Récapitulatif des destinataires</p>
|
|
</div>
|
|
|
|
{/* Contracts List */}
|
|
<div className="space-y-2 max-h-48 overflow-y-auto">
|
|
{selectedContracts.map((contract) => {
|
|
const employeeEmail = contract.salaries?.adresse_mail;
|
|
const employerEmail = employerEmails[contract.org_id as string];
|
|
|
|
return (
|
|
<div key={contract.id} className="p-2 bg-white rounded border border-indigo-100 text-xs">
|
|
<p className="font-medium text-gray-900">
|
|
{contract.contract_number && `[${contract.contract_number}]`} {contract.employee_name || contract.salaries?.salarie || '—'}
|
|
</p>
|
|
<p className="text-gray-600 mt-1">
|
|
Salarié : <span className={employeeEmail ? "text-indigo-600 font-mono" : "text-orange-600"}>{employeeEmail || "Email non renseigné"}</span>
|
|
</p>
|
|
<p className="text-gray-600">
|
|
Employeur (signature) : <span className={employerEmail ? "text-indigo-600 font-mono" : "text-orange-600"}>{employerEmail || "Email signature non renseigné"}</span>
|
|
</p>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Option: Envoyer notification */}
|
|
<div className="mb-6 p-3 bg-gray-50 border border-gray-200 rounded-lg">
|
|
<label className="flex items-start gap-3 cursor-pointer">
|
|
<input
|
|
type="checkbox"
|
|
checked={sendNotification}
|
|
onChange={(e) => setSendNotification(e.target.checked)}
|
|
className="mt-0.5 size-4 text-indigo-600 rounded focus:ring-indigo-500"
|
|
/>
|
|
<div className="flex-1">
|
|
<span className="text-sm font-medium text-gray-900">
|
|
Envoyer un email récapitulatif au client
|
|
</span>
|
|
<p className="text-xs text-gray-500 mt-1">
|
|
Si décoché, les signatures seront créées dans DocuSeal mais aucun email de notification groupée ne sera envoyé à l'employeur.
|
|
</p>
|
|
</div>
|
|
</label>
|
|
</div>
|
|
|
|
{/* Actions */}
|
|
<div className="flex justify-end gap-2">
|
|
<button
|
|
onClick={onClose}
|
|
className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded hover:bg-gray-50"
|
|
>
|
|
Annuler
|
|
</button>
|
|
<button
|
|
onClick={() => onConfirm(sendNotification)}
|
|
className="px-4 py-2 text-sm bg-indigo-600 text-white rounded hover:bg-indigo-700"
|
|
>
|
|
Confirmer et envoyer
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|