Added Money System

This commit is contained in:
2026-01-22 19:25:25 +01:00
parent d5d0d5aaf4
commit bb5c3058b1
12 changed files with 703 additions and 266 deletions

View File

@@ -12,6 +12,13 @@ interface Adherent {
adresse: string;
telephone: string;
email: string;
commentaire?: string | null;
telephoneSecondaire?: string | null;
instructions?: string | null;
situation?: string | null;
prescripteur?: string | null;
facturation?: string | null;
forfait?: string | null;
}
interface Chauffeur {
@@ -31,6 +38,7 @@ interface TrajetFormProps {
adresseDepart: string;
adresseArrivee: string;
commentaire?: string | null;
instructions?: string | null;
statut: string;
adherentId: string;
chauffeurId?: string | null;
@@ -55,6 +63,9 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
adherentPrenom: '',
adherentAdresse: '',
adherentTelephone: '',
adherentTelephoneSecondaire: '',
adherentEmail: '',
adherentForfait: '',
chauffeurId: trajetToEdit?.chauffeurId || '',
chauffeurNom: '',
chauffeurPrenom: '',
@@ -64,6 +75,7 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
adresseDepart: trajetToEdit?.adresseDepart || '',
adresseArrivee: trajetToEdit?.adresseArrivee || '',
commentaire: trajetToEdit?.commentaire || '',
instructions: trajetToEdit?.instructions || '',
});
useEffect(() => {
@@ -79,6 +91,33 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
.then(res => res.json())
.then(data => {
if (data) {
// Construire le commentaire avec toutes les informations pertinentes
const commentaireParts: string[] = [];
if (data.commentaire) {
commentaireParts.push(`Commentaire adhérent: ${data.commentaire}`);
}
if (data.instructions) {
commentaireParts.push(`Instructions: ${data.instructions}`);
}
if (data.telephoneSecondaire) {
commentaireParts.push(`Téléphone secondaire: ${data.telephoneSecondaire}`);
}
if (data.situation) {
commentaireParts.push(`Situation: ${data.situation}`);
}
if (data.prescripteur) {
commentaireParts.push(`Prescripteur: ${data.prescripteur}`);
}
if (data.facturation) {
commentaireParts.push(`Facturation: ${data.facturation}`);
}
setFormData(prev => ({
...prev,
adherentId: data.id,
@@ -86,7 +125,12 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
adherentPrenom: data.prenom,
adherentAdresse: data.adresse,
adherentTelephone: data.telephone,
adherentTelephoneSecondaire: data.telephoneSecondaire || '',
adherentEmail: data.email,
adherentForfait: data.forfait || '',
adresseDepart: data.adresse,
commentaire: data.commentaire || prev.commentaire || trajetToEdit.commentaire || '',
instructions: data.instructions || prev.instructions || trajetToEdit.instructions || '',
}));
setSearchAdherent(`${data.prenom} ${data.nom}`);
}
@@ -161,16 +205,53 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
}
};
const handleSelectAdherent = (adherent: Adherent) => {
setFormData({
...formData,
adherentId: adherent.id,
adherentNom: adherent.nom,
adherentPrenom: adherent.prenom,
adherentAdresse: adherent.adresse,
adherentTelephone: adherent.telephone,
adresseDepart: adherent.adresse, // Remplir automatiquement l'adresse de départ
});
const handleSelectAdherent = async (adherent: Adherent) => {
// Charger toutes les informations complètes de l'adhérent depuis l'API
try {
const response = await fetch(`/api/adherents/${adherent.id}`);
if (response.ok) {
const fullAdherent = await response.json();
setFormData({
...formData,
adherentId: fullAdherent.id,
adherentNom: fullAdherent.nom,
adherentPrenom: fullAdherent.prenom,
adherentAdresse: fullAdherent.adresse,
adherentTelephone: fullAdherent.telephone,
adherentTelephoneSecondaire: fullAdherent.telephoneSecondaire || '',
adherentEmail: fullAdherent.email,
adherentForfait: fullAdherent.forfait || '',
adresseDepart: fullAdherent.adresse, // Remplir automatiquement l'adresse de départ
commentaire: fullAdherent.commentaire || formData.commentaire || '', // Prendre uniquement le commentaire de l'adhérent
instructions: fullAdherent.instructions || formData.instructions || '', // Pré-remplir les instructions
});
} else {
// Si l'API échoue, utiliser les données de base
setFormData({
...formData,
adherentId: adherent.id,
adherentNom: adherent.nom,
adherentPrenom: adherent.prenom,
adherentAdresse: adherent.adresse,
adherentTelephone: adherent.telephone,
adresseDepart: adherent.adresse,
});
}
} catch (error) {
console.error('Erreur lors du chargement des détails de l\'adhérent:', error);
// En cas d'erreur, utiliser les données de base
setFormData({
...formData,
adherentId: adherent.id,
adherentNom: adherent.nom,
adherentPrenom: adherent.prenom,
adherentAdresse: adherent.adresse,
adherentTelephone: adherent.telephone,
adresseDepart: adherent.adresse,
});
}
setSearchAdherent(`${adherent.prenom} ${adherent.nom}`);
setShowAdherentDropdown(false);
};
@@ -228,6 +309,7 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
adresseDepart: formData.adresseDepart,
adresseArrivee: formData.adresseArrivee,
commentaire: formData.commentaire || null,
instructions: formData.instructions || null,
statut: trajetToEdit?.statut || 'Planifié',
adherentId: formData.adherentId,
chauffeurId: formData.chauffeurId || null,
@@ -328,7 +410,7 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
)}
</div>
{formData.adherentId && (
<div className="mt-3 p-3 bg-gray-50 rounded-lg border border-gray-200">
<div className="mt-3 p-4 bg-gray-50 rounded-lg border border-gray-200 space-y-3">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-full bg-lgreen flex items-center justify-center text-white font-semibold text-sm">
{getInitials(formData.adherentNom, formData.adherentPrenom)}
@@ -337,10 +419,39 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
<div className="text-sm font-medium text-gray-900">
{formData.adherentPrenom} {formData.adherentNom}
</div>
<div className="text-xs text-gray-500">{formData.adherentTelephone}</div>
<div className="text-xs text-gray-500 mt-1">{formData.adherentAdresse}</div>
<div className="text-xs text-gray-500">{formData.adherentAdresse}</div>
</div>
</div>
<div className="grid grid-cols-1 gap-2 pt-2 border-t border-gray-200">
<div className="flex items-center gap-2">
<svg className="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
</svg>
<span className="text-xs text-gray-600">{formData.adherentTelephone}</span>
</div>
{formData.adherentTelephoneSecondaire && (
<div className="flex items-center gap-2">
<svg className="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
</svg>
<span className="text-xs text-gray-600">Secondaire: {formData.adherentTelephoneSecondaire}</span>
</div>
)}
<div className="flex items-center gap-2">
<svg className="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
<span className="text-xs text-gray-600">{formData.adherentEmail}</span>
</div>
{formData.adherentForfait && (
<div className="flex items-center gap-2">
<svg className="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span className="text-xs font-semibold text-lgreen">Forfait: {formData.adherentForfait} </span>
</div>
)}
</div>
</div>
)}
</div>
@@ -456,15 +567,39 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
/>
</div>
{/* Instructions */}
<div>
<label className="block text-sm font-semibold text-gray-900 mb-2">
Instructions
{formData.adherentId && (
<span className="ml-2 text-xs font-normal text-gray-500">
(pré-rempli depuis la fiche adhérent)
</span>
)}
</label>
<textarea
value={formData.instructions}
onChange={(e) => setFormData({ ...formData, instructions: e.target.value })}
placeholder="Instructions pour ce trajet... Les instructions de la fiche adhérent seront automatiquement ajoutées lors de la sélection."
rows={4}
className="w-full px-4 py-2.5 border border-gray-300 rounded-lg text-gray-900 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-lblue focus:border-transparent resize-none"
/>
</div>
{/* Commentaire */}
<div>
<label className="block text-sm font-semibold text-gray-900 mb-2">
Commentaire
{formData.adherentId && (
<span className="ml-2 text-xs font-normal text-gray-500">
(pré-rempli depuis la fiche adhérent)
</span>
)}
</label>
<textarea
value={formData.commentaire}
onChange={(e) => setFormData({ ...formData, commentaire: e.target.value })}
placeholder="Commentaire optionnel..."
placeholder="Commentaire optionnel... Le commentaire de la fiche adhérent sera automatiquement ajouté lors de la sélection."
rows={4}
className="w-full px-4 py-2.5 border border-gray-300 rounded-lg text-gray-900 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-lblue focus:border-transparent resize-none"
/>
@@ -485,7 +620,7 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
</div>
{/* Informations supplémentaires */}
{(formData.date || formData.heure || formData.chauffeurId || formData.commentaire) && (
{(formData.date || formData.heure || formData.chauffeurId || formData.instructions || formData.commentaire) && (
<div className="mt-4 bg-white rounded-lg p-4 border border-gray-200 space-y-3">
{formData.date && (
<div className="flex items-center gap-2">
@@ -520,10 +655,16 @@ export default function TrajetForm({ onClose, onSuccess, trajetToEdit }: TrajetF
</span>
</div>
)}
{formData.instructions && (
<div className="pt-3 border-t border-gray-200">
<div className="text-xs font-semibold text-gray-500 uppercase mb-1">Instructions</div>
<p className="text-sm text-gray-700 whitespace-pre-line">{formData.instructions}</p>
</div>
)}
{formData.commentaire && (
<div className="pt-3 border-t border-gray-200">
<div className="text-xs font-semibold text-gray-500 uppercase mb-1">Commentaire</div>
<p className="text-sm text-gray-700">{formData.commentaire}</p>
<p className="text-sm text-gray-700 whitespace-pre-line">{formData.commentaire}</p>
</div>
)}
</div>