Added few functions

This commit is contained in:
2026-02-16 14:43:02 +01:00
parent 0c908a21ac
commit 1ec4c935c9
31 changed files with 352 additions and 35 deletions

45
lib/body-scroll-lock.ts Normal file
View File

@@ -0,0 +1,45 @@
'use client';
/**
* Gère le verrouillage du scroll du body quand des modales sont ouvertes.
* Gère plusieurs modales empilées via un compteur.
*/
let lockCount = 0;
let savedScrollY = 0;
export function lockBodyScroll() {
lockCount++;
if (lockCount === 1) {
savedScrollY = window.scrollY;
document.documentElement.style.overflow = 'hidden';
document.body.style.overflow = 'hidden';
document.body.style.position = 'fixed';
document.body.style.top = `-${savedScrollY}px`;
document.body.style.left = '0';
document.body.style.right = '0';
}
}
export function unlockBodyScroll() {
if (lockCount > 0) lockCount--;
if (lockCount === 0) {
document.documentElement.style.overflow = '';
document.body.style.overflow = '';
document.body.style.position = '';
document.body.style.top = '';
document.body.style.left = '';
document.body.style.right = '';
window.scrollTo(0, savedScrollY);
}
}
import { useEffect } from 'react';
export function useBodyScrollLock(isOpen: boolean) {
useEffect(() => {
if (isOpen) {
lockBodyScroll();
return () => unlockBodyScroll();
}
}, [isOpen]);
}

7
lib/participation-ref.ts Normal file
View File

@@ -0,0 +1,7 @@
/**
* Génère la référence de prescription (ex: PART-XXXXXXXX)
* utilisée dans les participations financières et affichée sur les trajets.
*/
export function getParticipationRef(participationId: string): string {
return `PART-${participationId.slice(-8).toUpperCase()}`;
}

72
lib/trajet-duree.ts Normal file
View File

@@ -0,0 +1,72 @@
/**
* Calcule la durée estimée d'un trajet en heures à partir des adresses.
* Utilise Nominatim pour géocoder et la formule de Haversine pour la distance.
*/
export async function calculerDureeTrajet(
adresseDepart: string,
adresseArrivee: string
): Promise<number | null> {
if (!adresseDepart?.trim() || !adresseArrivee?.trim()) {
return null;
}
try {
const departResponse = await fetch(
`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(adresseDepart.trim())}&limit=1&countrycodes=fr`,
{
headers: {
'User-Agent': 'MAD Platform',
'Accept-Language': 'fr-FR,fr;q=0.9',
},
}
);
if (!departResponse.ok) return null;
await new Promise((resolve) => setTimeout(resolve, 1000));
const arriveeResponse = await fetch(
`https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(adresseArrivee.trim())}&limit=1&countrycodes=fr`,
{
headers: {
'User-Agent': 'MAD Platform',
'Accept-Language': 'fr-FR,fr;q=0.9',
},
}
);
if (!arriveeResponse.ok) return null;
const [departData, arriveeData] = await Promise.all([
departResponse.json(),
arriveeResponse.json(),
]);
if (!departData?.length || !arriveeData?.length) return null;
const lat1 = parseFloat(departData[0].lat);
const lon1 = parseFloat(departData[0].lon);
const lat2 = parseFloat(arriveeData[0].lat);
const lon2 = parseFloat(arriveeData[0].lon);
const R = 6371; // Rayon de la Terre en km
const dLat = ((lat2 - lat1) * Math.PI) / 180;
const dLon = ((lon2 - lon1) * Math.PI) / 180;
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos((lat1 * Math.PI) / 180) *
Math.cos((lat2 * Math.PI) / 180) *
Math.sin(dLon / 2) *
Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = R * c;
const distanceWithDetour = distance * 1.3;
const vitesseMoyenne = 50; // km/h
const dureeEnHeures = distanceWithDetour / vitesseMoyenne;
return Math.round(dureeEnHeures * 10) / 10;
} catch {
return null;
}
}