'use client';
import { useState } from 'react';
import dynamic from 'next/dynamic';
import TrajetForm from './TrajetForm';
import ValidationModal from './ValidationModal';
import ConfirmModal from './ConfirmModal';
import { useNotification } from './NotificationProvider';
// Import dynamique pour éviter les problèmes SSR avec Leaflet
const TrajetMap = dynamic(() => import('./TrajetMap'), {
ssr: false,
loading: () => (
Chargement de la carte...
)
});
interface Trajet {
id: string;
date: string;
adresseDepart: string;
adresseArrivee: string;
commentaire?: string | null;
instructions?: string | null;
statut: string;
adherent: {
id: string;
nom: string;
prenom: string;
telephone: string;
telephoneSecondaire?: string | null;
email: string;
forfait?: string | null;
};
chauffeur?: {
id: string;
nom: string;
prenom: string;
telephone: string;
} | null;
}
interface TrajetDetailModalProps {
trajet: Trajet;
onClose: () => void;
onUpdate: () => void;
}
export default function TrajetDetailModal({ trajet, onClose, onUpdate }: TrajetDetailModalProps) {
const { showNotification } = useNotification();
const [showEditForm, setShowEditForm] = useState(false);
const [showValidationModal, setShowValidationModal] = useState(false);
const [showCancelConfirm, setShowCancelConfirm] = useState(false);
const [showArchiveConfirm, setShowArchiveConfirm] = useState(false);
const [loading, setLoading] = useState(false);
const formatDate = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleDateString('fr-FR', {
weekday: 'long',
day: 'numeric',
month: 'long',
year: 'numeric',
});
};
const formatTime = (dateString: string) => {
const date = new Date(dateString);
return date.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' });
};
const handleCancelClick = () => {
setShowCancelConfirm(true);
};
const handleCancel = async () => {
setShowCancelConfirm(false);
setLoading(true);
try {
const response = await fetch(`/api/trajets/${trajet.id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
statut: 'Annulé',
}),
});
if (response.ok) {
showNotification('info', 'Trajet annulé avec succès');
onUpdate();
onClose();
} else {
const error = await response.json();
showNotification('error', error.error || 'Erreur lors de l\'annulation du trajet');
}
} catch (error) {
console.error('Erreur lors de l\'annulation:', error);
showNotification('error', 'Erreur lors de l\'annulation du trajet');
} finally {
setLoading(false);
}
};
const handleArchiveClick = () => {
setShowArchiveConfirm(true);
};
const handleArchive = async () => {
setShowArchiveConfirm(false);
setLoading(true);
try {
const response = await fetch(`/api/trajets/${trajet.id}/archive`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
});
if (response.ok) {
showNotification('info', 'Trajet archivé avec succès');
onUpdate();
onClose();
} else {
const error = await response.json();
showNotification('error', error.error || 'Erreur lors de l\'archivage du trajet');
}
} catch (error) {
console.error('Erreur lors de l\'archivage:', error);
showNotification('error', 'Erreur lors de l\'archivage du trajet');
} finally {
setLoading(false);
}
};
const getInitials = (nom: string, prenom: string) => {
return `${prenom.charAt(0)}${nom.charAt(0)}`.toUpperCase();
};
const getStatutColor = (statut: string) => {
switch (statut) {
case 'Terminé':
return 'bg-green-100 text-green-700 border-green-200';
case 'En cours':
return 'bg-blue-100 text-blue-700 border-blue-200';
case 'Annulé':
return 'bg-red-100 text-red-700 border-red-200';
case 'Validé':
return 'bg-purple-100 text-purple-700 border-purple-200';
default:
return 'bg-gray-100 text-gray-700 border-gray-200';
}
};
const handleCopyAddress = async (address: string) => {
try {
await navigator.clipboard.writeText(address);
showNotification('success', 'Adresse copiée dans le presse-papiers');
} catch (error) {
console.error('Erreur lors de la copie:', error);
showNotification('error', 'Erreur lors de la copie de l\'adresse');
}
};
const handleOpenRoute = () => {
const encodedDepart = encodeURIComponent(trajet.adresseDepart);
const encodedArrivee = encodeURIComponent(trajet.adresseArrivee);
// Détecter le système d'exploitation pour ouvrir dans la bonne app
const userAgent = navigator.userAgent || navigator.vendor || (window as any).opera;
const isIOS = /iPad|iPhone|iPod/.test(userAgent) && !(window as any).MSStream;
if (isIOS) {
// Apple Maps avec itinéraire
window.open(`https://maps.apple.com/?saddr=${encodedDepart}&daddr=${encodedArrivee}`, '_blank');
} else {
// Google Maps avec itinéraire (par défaut sur Android et autres)
window.open(`https://www.google.com/maps/dir/${encodedDepart}/${encodedArrivee}`, '_blank');
}
};
if (showEditForm) {
return (
setShowEditForm(false)}
onSuccess={() => {
onUpdate();
setShowEditForm(false);
onClose();
}}
trajetToEdit={trajet}
/>
);
}
if (showValidationModal) {
return (
setShowValidationModal(false)}
onSuccess={() => {
onUpdate();
setShowValidationModal(false);
onClose();
}}
/>
);
}
return (
{/* Header */}
Détails du trajet
{trajet.statut}
Informations complètes du trajet
{/* Content */}
{/* Colonne gauche - Informations */}
{/* Adhérent */}
{getInitials(trajet.adherent.nom, trajet.adherent.prenom)}
{trajet.adherent.prenom} {trajet.adherent.nom}
{trajet.adherent.telephone}
{trajet.adherent.telephoneSecondaire && (
Secondaire: {trajet.adherent.telephoneSecondaire}
)}
{trajet.adherent.forfait && (
Forfait: {trajet.adherent.forfait} €
)}
{/* Chauffeur */}
{trajet.chauffeur ? (
{getInitials(trajet.chauffeur.nom, trajet.chauffeur.prenom)}
) : (
)}
{/* Date et heure */}
{formatDate(trajet.date)}
{formatTime(trajet.date)}
{/* Adresses */}
B
{trajet.adresseArrivee}
{/* Instructions */}
{trajet.instructions && (
)}
{/* Commentaire */}
{trajet.commentaire && (
)}
{/* Colonne droite - Carte */}
{/* Footer */}
{trajet.chauffeur && trajet.statut === 'Planifié' && (
)}
setShowCancelConfirm(false)}
/>
setShowArchiveConfirm(false)}
/>
);
}