preivision
This commit is contained in:
@@ -220,6 +220,7 @@ return [
|
||||
'weather_cloudy' => 'Ennuvolat',
|
||||
'weather_rainy' => 'Plujós',
|
||||
'weather_snowy' => 'Nevat',
|
||||
'weather_historical' => 'Basat en l\'històric (estimació)',
|
||||
|
||||
// Anciennes clés Holidays non préfixées (conservades)
|
||||
'outbound_trip' => 'Anada',
|
||||
|
||||
@@ -220,6 +220,7 @@ return [
|
||||
'weather_cloudy' => 'Nuageux',
|
||||
'weather_rainy' => 'Pluvieux',
|
||||
'weather_snowy' => 'Neigeux',
|
||||
'weather_historical' => 'Basé sur l\'historique (estimation)',
|
||||
|
||||
// Anciennes clés Holidays non préfixées (conservées pour compatibilité si utilisées)
|
||||
'outbound_trip' => 'Aller',
|
||||
|
||||
@@ -49,10 +49,20 @@ async function loadWeatherForStep(pt) {
|
||||
|
||||
if (res.success) {
|
||||
const info = getWeatherInfo(res.data.code);
|
||||
|
||||
// Si c'est une estimation basée sur le passé, on adapte l'affichage
|
||||
const approxSymbol = res.data.is_historical ? "~" : "";
|
||||
const badgeTitle = res.data.is_historical
|
||||
? `${info.label} (${tr("weather_historical")})`
|
||||
: info.label;
|
||||
const opacityStyle = res.data.is_historical
|
||||
? "opacity: 0.85; font-style: italic;"
|
||||
: "";
|
||||
|
||||
container.innerHTML = `
|
||||
<div class="pf-weather-badge" title="${info.label}">
|
||||
<div class="pf-weather-badge" title="${badgeTitle}" style="${opacityStyle}">
|
||||
<span class="pf-weather-icon">${info.icon}</span>
|
||||
<span>${Math.round(res.data.temp_min)}° / ${Math.round(res.data.temp_max)}°C</span>
|
||||
<span>${approxSymbol}${Math.round(res.data.temp_min)}° / ${Math.round(res.data.temp_max)}°C</span>
|
||||
</div>`;
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
<?php
|
||||
// modules/holidays/includes/api/get_weather.php
|
||||
|
||||
// 1. Désactiver les erreurs HTML pour ne pas corrompre le JSON
|
||||
ini_set('display_errors', 0);
|
||||
error_reporting(0);
|
||||
|
||||
// 2. Inclusion de tes fichiers vitaux (C'est auth.php qui sécurise l'accès !)
|
||||
$basePath = '../../../../';
|
||||
require_once $basePath . 'includes/db.php';
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
require_once $basePath . 'includes/auth.php';
|
||||
|
||||
// Si on arrive à cette ligne, c'est que auth.php a validé la session.
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// 3. Récupération des paramètres GPS et Date
|
||||
$lat = filter_input(INPUT_GET, 'lat', FILTER_VALIDATE_FLOAT);
|
||||
$lng = filter_input(INPUT_GET, 'lng', FILTER_VALIDATE_FLOAT);
|
||||
$date = $_GET['date'] ?? null;
|
||||
@@ -29,43 +28,98 @@ $targetDate = new DateTime($date);
|
||||
$interval = $today->diff($targetDate);
|
||||
$daysDiff = (int)$interval->format('%R%a');
|
||||
|
||||
// 4. Choix du bon modèle météo (Prévisions vs Historique)
|
||||
if ($daysDiff < -2) {
|
||||
// --- 🧠 GESTION INTELLIGENTE DU TEMPS (Prévisions vs Historique) ---
|
||||
if ($daysDiff > 16) {
|
||||
// 1. VOYAGE LOINTAIN : Calcul de la moyenne sur 3 ans
|
||||
$currentYear = (int)$today->format('Y');
|
||||
$monthDay = $targetDate->format('m-d');
|
||||
if ($monthDay === '02-29') $monthDay = '02-28'; // Sécurité année bissextile
|
||||
|
||||
$tempMaxSum = 0;
|
||||
$tempMinSum = 0;
|
||||
$validYearsCount = 0;
|
||||
$representativeCode = 0; // On gardera le code de l'année N-1
|
||||
|
||||
for ($i = 1; $i <= 3; $i++) {
|
||||
$pastYear = $currentYear - $i;
|
||||
$searchDate = $pastYear . '-' . $monthDay;
|
||||
|
||||
$url = "https://archive-api.open-meteo.com/v1/archive?latitude=$lat&longitude=$lng&daily=weather_code,temperature_2m_max,temperature_2m_min&timezone=auto&start_date=$searchDate&end_date=$searchDate";
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 2); // Timeout court pour ne pas ralentir le serveur
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
$res = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($res) {
|
||||
$data = json_decode($res, true);
|
||||
if (isset($data['daily']['temperature_2m_max'][0])) {
|
||||
$tempMaxSum += $data['daily']['temperature_2m_max'][0];
|
||||
$tempMinSum += $data['daily']['temperature_2m_min'][0];
|
||||
|
||||
if ($i === 1) { // On prend le temps qu'il a fait à N-1 pour l'icône
|
||||
$representativeCode = $data['daily']['weather_code'][0];
|
||||
}
|
||||
$validYearsCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Si on a pu récupérer au moins une année de données
|
||||
if ($validYearsCount > 0) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'code' => $representativeCode,
|
||||
'temp_max' => round($tempMaxSum / $validYearsCount, 1), // Moyenne arrondie à 1 décimale
|
||||
'temp_min' => round($tempMinSum / $validYearsCount, 1),
|
||||
'is_historical' => true
|
||||
]
|
||||
]);
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'message' => 'Archives indisponibles']);
|
||||
}
|
||||
exit; // On arrête l'exécution ici pour les voyages lointains
|
||||
|
||||
} elseif ($daysDiff < -2) {
|
||||
// 2. VOYAGE PASSÉ : On interroge les archives pour cette date précise
|
||||
$baseUrl = "https://archive-api.open-meteo.com/v1/archive";
|
||||
$searchDate = $date;
|
||||
} else {
|
||||
// 3. FUTUR PROCHE (Prévisions fiables) : On interroge les prévisions
|
||||
$baseUrl = "https://api.open-meteo.com/v1/forecast";
|
||||
$searchDate = $date;
|
||||
}
|
||||
|
||||
$url = "$baseUrl?latitude=$lat&longitude=$lng&daily=weather_code,temperature_2m_max,temperature_2m_min&timezone=auto&start_date=$date&end_date=$date";
|
||||
// --- APPEL API CLASSIQUE (Pour les prévisions et les voyages passés) ---
|
||||
$url = "$baseUrl?latitude=$lat&longitude=$lng&daily=weather_code,temperature_2m_max,temperature_2m_min&timezone=auto&start_date=$searchDate&end_date=$searchDate";
|
||||
|
||||
// 5. Interrogation d'Open-Meteo via cURL (plus robuste)
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 5); // Timeout de 5 secondes max
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Contourne les erreurs SSL en local
|
||||
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
$res = curl_exec($ch);
|
||||
$curlError = curl_error($ch); // On capture l'erreur exacte au cas où
|
||||
curl_close($ch);
|
||||
|
||||
if (!$res) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Erreur API Open-Meteo',
|
||||
'debug' => $curlError, // L'inspecteur JS nous donnera la vraie raison !
|
||||
'url' => $url
|
||||
]);
|
||||
echo json_encode(['success' => false, 'message' => 'Erreur API Open-Meteo']);
|
||||
exit;
|
||||
}
|
||||
// 6. Formatage et envoi au Javascript
|
||||
|
||||
$data = json_decode($res, true);
|
||||
|
||||
if (isset($data['daily']['weather_code'][0])) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'code' => $data['daily']['weather_code'][0],
|
||||
'temp_max' => $data['daily']['temperature_2m_max'][0],
|
||||
'temp_min' => $data['daily']['temperature_2m_min'][0]
|
||||
'temp_min' => $data['daily']['temperature_2m_min'][0],
|
||||
'is_historical' => false
|
||||
]
|
||||
]);
|
||||
} else {
|
||||
|
||||
@@ -386,7 +386,8 @@ window.I18N = {
|
||||
'weather_cloudy': "<?= tr('weather_cloudy') ?>",
|
||||
'weather_rainy': "<?= tr('weather_rainy') ?>",
|
||||
'weather_snowy': "<?= tr('weather_snowy') ?>",
|
||||
'weather_forecast': "<?= tr('weather_forecast') ?>"
|
||||
'weather_forecast': "<?= tr('weather_forecast') ?>",
|
||||
'weather_historical': "<?= tr('weather_historical') ?>"
|
||||
};
|
||||
|
||||
// Fallback de sécurité pour s'assurer que les modales peuvent toujours se fermer
|
||||
|
||||
Reference in New Issue
Block a user