163 lines
5.9 KiB
TypeScript
163 lines
5.9 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { Calendar, Shield, AlertCircle, Loader2 } from "lucide-react";
|
|
|
|
interface BirthdateVerificationModalProps {
|
|
docuseal_id: string;
|
|
onVerified: () => void;
|
|
}
|
|
|
|
export default function BirthdateVerificationModal({
|
|
docuseal_id,
|
|
onVerified
|
|
}: BirthdateVerificationModalProps) {
|
|
const [birthdate, setBirthdate] = useState("");
|
|
const [isVerifying, setIsVerifying] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [attempts, setAttempts] = useState(0);
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setError(null);
|
|
setIsVerifying(true);
|
|
|
|
try {
|
|
const response = await fetch('/api/signature-salarie/verify-birthdate', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
docuseal_id,
|
|
birthdate
|
|
}),
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.verified) {
|
|
// Succès ! On ferme le modal
|
|
onVerified();
|
|
} else {
|
|
// Échec de vérification
|
|
setAttempts(prev => prev + 1);
|
|
setError(data.error || 'Date de naissance incorrecte');
|
|
setBirthdate("");
|
|
}
|
|
} catch (err) {
|
|
console.error('Erreur lors de la vérification:', err);
|
|
setError('Erreur lors de la vérification. Veuillez réessayer.');
|
|
} finally {
|
|
setIsVerifying(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-in fade-in duration-200">
|
|
<div className="w-full max-w-md bg-white rounded-2xl shadow-2xl border border-gray-200 overflow-hidden animate-in zoom-in-95 duration-300">
|
|
{/* Header avec gradient */}
|
|
<div className="bg-gradient-to-r from-blue-600 to-blue-700 px-6 py-5">
|
|
<div className="flex items-center gap-3">
|
|
<div className="p-2 bg-white/20 rounded-lg backdrop-blur-sm">
|
|
<Shield className="w-6 h-6 text-white" />
|
|
</div>
|
|
<div>
|
|
<h2 className="text-xl font-semibold text-white">
|
|
Vérification de sécurité
|
|
</h2>
|
|
<p className="text-blue-100 text-sm mt-0.5">
|
|
Protection de vos données personnelles
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Corps du modal */}
|
|
<form onSubmit={handleSubmit} className="p-6 space-y-5">
|
|
{/* Message d'explication */}
|
|
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
|
<p className="text-sm text-blue-900 leading-relaxed">
|
|
Pour accéder à votre document de signature, veuillez confirmer votre identité en renseignant votre <strong>date de naissance</strong>.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Input date de naissance */}
|
|
<div className="space-y-2">
|
|
<label
|
|
htmlFor="birthdate"
|
|
className="block text-sm font-medium text-gray-700 flex items-center gap-2"
|
|
>
|
|
<Calendar className="w-4 h-4 text-gray-500" />
|
|
Date de naissance
|
|
</label>
|
|
<input
|
|
id="birthdate"
|
|
type="date"
|
|
value={birthdate}
|
|
onChange={(e) => {
|
|
setBirthdate(e.target.value);
|
|
setError(null);
|
|
}}
|
|
max={new Date().toISOString().split('T')[0]}
|
|
required
|
|
disabled={isVerifying}
|
|
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all disabled:bg-gray-100 disabled:cursor-not-allowed text-base"
|
|
placeholder="jj/mm/aaaa"
|
|
/>
|
|
</div>
|
|
|
|
{/* Message d'erreur */}
|
|
{error && (
|
|
<div className="bg-red-50 border border-red-200 rounded-lg p-3 animate-in slide-in-from-top-2 duration-200">
|
|
<div className="flex items-start gap-2">
|
|
<AlertCircle className="w-5 h-5 text-red-600 flex-shrink-0 mt-0.5" />
|
|
<div>
|
|
<p className="text-sm font-medium text-red-900">{error}</p>
|
|
{attempts >= 2 && (
|
|
<p className="text-xs text-red-700 mt-1">
|
|
Besoin d'aide ? Contactez-nous à{' '}
|
|
<a
|
|
href="mailto:paie@odentas.fr"
|
|
className="underline hover:text-red-900"
|
|
>
|
|
paie@odentas.fr
|
|
</a>
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Bouton de validation */}
|
|
<button
|
|
type="submit"
|
|
disabled={isVerifying || !birthdate}
|
|
className="w-full bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 text-white font-medium py-3 px-4 rounded-lg transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2 shadow-lg hover:shadow-xl"
|
|
>
|
|
{isVerifying ? (
|
|
<>
|
|
<Loader2 className="w-5 h-5 animate-spin" />
|
|
Vérification en cours...
|
|
</>
|
|
) : (
|
|
<>
|
|
<Shield className="w-5 h-5" />
|
|
Vérifier et accéder au document
|
|
</>
|
|
)}
|
|
</button>
|
|
|
|
{/* Footer avec info */}
|
|
<div className="pt-4 border-t border-gray-200">
|
|
<p className="text-xs text-gray-500 text-center leading-relaxed">
|
|
🔒 Vos données sont protégées et ne sont utilisées que pour vérifier votre identité.
|
|
Cette étape garantit que seul vous pouvez accéder à votre contrat.
|
|
</p>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|