155 lines
5.5 KiB
TypeScript
155 lines
5.5 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useState, useRef } from 'react';
|
|
import { useParams, useRouter } from 'next/navigation';
|
|
import { CheckCircle, Loader2, XCircle, Truck } from 'lucide-react';
|
|
|
|
export default function CarrierAcceptPage() {
|
|
const params = useParams();
|
|
const router = useRouter();
|
|
const token = params.token as string;
|
|
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [bookingId, setBookingId] = useState<string | null>(null);
|
|
const [isNewAccount, setIsNewAccount] = useState(false);
|
|
|
|
// Prevent double API calls (React 18 StrictMode issue)
|
|
const hasCalledApi = useRef(false);
|
|
|
|
useEffect(() => {
|
|
const acceptBooking = async () => {
|
|
// Protection contre les doubles appels
|
|
if (hasCalledApi.current) {
|
|
return;
|
|
}
|
|
hasCalledApi.current = true;
|
|
if (!token) {
|
|
setError('Token manquant');
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Appeler l'API backend pour accepter le booking
|
|
const response = await fetch(`http://localhost:4000/api/v1/csv-bookings/accept/${token}`, {
|
|
method: 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json();
|
|
|
|
// Messages d'erreur personnalisés
|
|
let errorMessage = errorData.message || 'Erreur lors de l\'acceptation du booking';
|
|
|
|
if (errorMessage.includes('status ACCEPTED')) {
|
|
errorMessage = 'Ce booking a déjà été accepté. Vous ne pouvez pas l\'accepter à nouveau.';
|
|
} else if (errorMessage.includes('status REJECTED')) {
|
|
errorMessage = 'Ce booking a déjà été refusé. Vous ne pouvez pas l\'accepter.';
|
|
} else if (errorMessage.includes('not found')) {
|
|
errorMessage = 'Booking introuvable. Le lien peut avoir expiré.';
|
|
}
|
|
|
|
throw new Error(errorMessage);
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
// Stocker le token JWT pour l'auto-login
|
|
if (data.autoLoginToken) {
|
|
localStorage.setItem('carrier_access_token', data.autoLoginToken);
|
|
}
|
|
|
|
setBookingId(data.bookingId);
|
|
setIsNewAccount(data.isNewAccount);
|
|
setLoading(false);
|
|
|
|
// Rediriger vers la page de détails après 2 secondes
|
|
setTimeout(() => {
|
|
router.push(`/carrier/dashboard/bookings/${data.bookingId}`);
|
|
}, 2000);
|
|
} catch (err) {
|
|
console.error('Error accepting booking:', err);
|
|
setError(err instanceof Error ? err.message : 'Erreur lors de l\'acceptation');
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
acceptBooking();
|
|
}, [token, router]);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-green-50 to-blue-50">
|
|
<div className="bg-white p-8 rounded-lg shadow-lg max-w-md w-full text-center">
|
|
<Loader2 className="w-16 h-16 text-green-600 mx-auto mb-4 animate-spin" />
|
|
<h1 className="text-2xl font-bold text-gray-900 mb-4">
|
|
Traitement en cours...
|
|
</h1>
|
|
<p className="text-gray-600">
|
|
Nous acceptons votre réservation et créons votre compte.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-red-50 to-orange-50">
|
|
<div className="bg-white p-8 rounded-lg shadow-lg max-w-md w-full text-center">
|
|
<XCircle className="w-16 h-16 text-red-500 mx-auto mb-4" />
|
|
<h1 className="text-2xl font-bold text-gray-900 mb-4">Erreur</h1>
|
|
<p className="text-gray-600 mb-6">{error}</p>
|
|
<button
|
|
onClick={() => router.push('/carrier/login')}
|
|
className="w-full px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700"
|
|
>
|
|
Retour à la connexion
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-green-50 to-blue-50">
|
|
<div className="bg-white p-8 rounded-lg shadow-lg max-w-md w-full text-center">
|
|
<CheckCircle className="w-16 h-16 text-green-500 mx-auto mb-4" />
|
|
<h1 className="text-3xl font-bold text-gray-900 mb-4">
|
|
Réservation Acceptée !
|
|
</h1>
|
|
|
|
<div className="bg-green-50 border-2 border-green-200 rounded-lg p-4 mb-6">
|
|
<p className="text-green-800 font-medium">
|
|
✅ La réservation a été acceptée avec succès
|
|
</p>
|
|
</div>
|
|
|
|
{isNewAccount && (
|
|
<div className="bg-blue-50 border-2 border-blue-200 rounded-lg p-4 mb-6">
|
|
<p className="text-blue-800 font-medium mb-2">
|
|
🎉 Compte transporteur créé !
|
|
</p>
|
|
<p className="text-sm text-blue-700">
|
|
Un email avec vos identifiants de connexion vous a été envoyé.
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex items-center justify-center text-gray-600 mb-6">
|
|
<Truck className="w-5 h-5 mr-2 animate-bounce" />
|
|
<p>Redirection vers les détails de la réservation...</p>
|
|
</div>
|
|
|
|
<div className="text-sm text-gray-500">
|
|
Vous serez automatiquement redirigé dans 2 secondes
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|