Patch Build App
This commit is contained in:
1 parent
3fcdf7e5ef
commit
b5df269cf8
5 files changed
+40
-30
No files matched your search
Generated
+27
@@ -20,6 +20,33 @@
|
|||||||
</PendingDiffInfo>
|
</PendingDiffInfo>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="$PROJECT_DIR$/src/pages/afficheurs/classiques/ClassiquesDeparts.js">
|
||||||
|
<value>
|
||||||
|
<PendingDiffInfo>
|
||||||
|
<option name="filePath" value="$PROJECT_DIR$/src/pages/afficheurs/classiques/ClassiquesDeparts.js" />
|
||||||
|
<option name="originalContent" value="import React, { useEffect, useState, useCallback } from 'react'; import './ClassiquesDeparts.css'; import supabase from '../../../lib/supabase'; // Helper utilitaire : format HHhMM sans secondes (ex: 06h44) const formatTimeNoSeconds = (v) => { if (v == null) return ''; const tryDate = new Date(v); if (!isNaN(tryDate.getTime())) { 	const hh = String(tryDate.getHours()).padStart(2, '0'); 	const mm = String(tryDate.getMinutes()).padStart(2, '0'); 	return `${hh}h${mm}`; } if (typeof v === 'string') { 	const m = v.match(/(\d{1,2}):(\d{2})(?::\d{2})?/); 	if (m) return `${String(m[1]).padStart(2,'0')}h${m[2]}`; 	const m2 = v.match(/T(\d{2}):(\d{2})/); 	if (m2) return `${m2[1]}h${m2[2]}`; 	return v.slice(0,5).replace(':','h'); } return String(v).slice(0,5).replace(':','h'); }; // Données proviennent exclusivement de la table `horaires`. function Logo({op}){ // Tente de charger un logo SVG depuis /type/ en fonction de l'opérateur. // mapping pour opérateurs connus -> noms de fichiers dans public/type const mapping = { 	'TGV inOUI': 'logo-inoui.svg', 	'TGV inOUI ': 'logo-inoui.svg', 	'TGV': 'logo-tgv.svg', 	'TER': 'sncf-voyageurs-logo.png', 	'MOBIGO': 'logo-mobigo.svg', 	'TGV Lyria': 'logo-lyria.svg', 	'TGV Lyria ': 'logo-lyria.svg', }; const defaultFileFromOp = (name) => { 	if (!name) return null; 	// nettoyer et fabriquer un nom plausible : "logo-<slug>.svg" 	const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, ''); 	return `logo-${slug}.svg`; }; const fileName = mapping[op] || mapping[op.split(' ')[0]] || defaultFileFromOp(op); const [hasImg, setHasImg] = React.useState(true); return ( 	<div className="aff-classiques-departs__logo-box" aria-hidden> 	 {hasImg && fileName ? ( 		<img 		 src={`/type/${fileName}`} 		 alt={op} 		 className="aff-classiques-departs__op-logo" 		 onError={()=> setHasImg(false)} 		/> 	 ) : ( 		<div className="aff-classiques-departs__logo-text" aria-hidden>{op.split(' ')[0]}</div> 	 )} 	</div> ); } // (La fonction TrainType a été retirée car la colonne affiche désormais directement les // informations via .train-meta dans la colonne .col-train-type) function Clock(){ const [now, setNow] = useState(new Date()); useEffect(() => { 	const id = setInterval(() => setNow(new Date()), 1000); 	return () => clearInterval(id); }, []); const hh = String(now.getHours()).padStart(2, '0'); const mm = String(now.getMinutes()).padStart(2, '0'); const ss = String(now.getSeconds()).padStart(2, '0'); return ( 	<div className="aff-classiques-departs__clock-container" aria-hidden> 	 <div className="aff-classiques-departs__clock-box"> 		<div className="aff-classiques-departs__clock-main">{hh}:{mm}</div> 		<div className="aff-classiques-departs__clock-seconds">{ss}</div> 	 </div> 	</div> ); } export default function ClassiquesDeparts(){ // lire le paramètre de requête ?gare=Nom-de-la-gare const params = new URLSearchParams(window.location.search); const gareParam = params.get('gare'); // support pour ?gare_id=123 ou ?gareId=123 const gareIdParam = params.get('gare_id') || params.get('gareId'); // gérer les +, décoder et remplacer les tirets par des espaces const gareDisplay = gareParam ? decodeURIComponent(String(gareParam).replace(/\+/g, ' ')).replace(/-/g, ' ') : null; // debug flag activable via ?debug=1 or ?debug=true const debugEnabled = (params.get('debug') === '1' || String(params.get('debug')).toLowerCase() === 'true'); const debug = useCallback((...args) => { if (debugEnabled) console.debug(...args); }, [debugEnabled]); // État pour alterner l'affichage toutes les 3 secondes const [showStatus, setShowStatus] = useState(false); // Données depuis Supabase const [horaires, setHoraires] = useState([]); const [allHoraires, setAllHoraires] = useState([]); const [perturbations, setPerturbations] = useState([]); // type de la gare affichée (valeurs attendues: 'interurbaine', 'ville', ...) const [stationType, setStationType] = useState(null); const [, setTravaux] = useState([]); const [, setLoading] = useState(false); const [, setError] = uLine truncated
|
||||||
|
<option name="updatedContent" value="import React, { useEffect, useState, useCallback } from 'react'; import './ClassiquesDeparts.css'; import supabase from '../../../lib/supabase'; // Helper utilitaire : format HHhMM sans secondes (ex: 06h44) const formatTimeNoSeconds = (v) => { if (v == null) return ''; const tryDate = new Date(v); if (!isNaN(tryDate.getTime())) { 	const hh = String(tryDate.getHours()).padStart(2, '0'); 	const mm = String(tryDate.getMinutes()).padStart(2, '0'); 	return `${hh}h${mm}`; } if (typeof v === 'string') { 	const m = v.match(/(\d{1,2}):(\d{2})(?::\d{2})?/); 	if (m) return `${String(m[1]).padStart(2,'0')}h${m[2]}`; 	const m2 = v.match(/T(\d{2}):(\d{2})/); 	if (m2) return `${m2[1]}h${m2[2]}`; 	return v.slice(0,5).replace(':','h'); } return String(v).slice(0,5).replace(':','h'); }; // Données proviennent exclusivement de la table `horaires`. function Logo({op}){ // Tente de charger un logo SVG depuis /type/ en fonction de l'opérateur. // mapping pour opérateurs connus -> noms de fichiers dans public/type const mapping = { 	'TGV inOUI': 'logo-inoui.svg', 	'TGV inOUI ': 'logo-inoui.svg', 	'TGV': 'logo-tgv.svg', 	'TER': 'sncf-voyageurs-logo.png', 	'MOBIGO': 'logo-mobigo.svg', 	'TGV Lyria': 'logo-lyria.svg', 	'TGV Lyria ': 'logo-lyria.svg', }; const defaultFileFromOp = (name) => { 	if (!name) return null; 	// nettoyer et fabriquer un nom plausible : "logo-<slug>.svg" 	const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, ''); 	return `logo-${slug}.svg`; }; const fileName = mapping[op] || mapping[op.split(' ')[0]] || defaultFileFromOp(op); const [hasImg, setHasImg] = React.useState(true); return ( 	<div className="aff-classiques-departs__logo-box" aria-hidden> 	 {hasImg && fileName ? ( 		<img 		 src={`/type/${fileName}`} 		 alt={op} 		 className="aff-classiques-departs__op-logo" 		 onError={()=> setHasImg(false)} 		/> 	 ) : ( 		<div className="aff-classiques-departs__logo-text" aria-hidden>{op.split(' ')[0]}</div> 	 )} 	</div> ); } // (La fonction TrainType a été retirée car la colonne affiche désormais directement les // informations via .train-meta dans la colonne .col-train-type) function Clock(){ const [now, setNow] = useState(new Date()); useEffect(() => { 	const id = setInterval(() => setNow(new Date()), 1000); 	return () => clearInterval(id); }, []); const hh = String(now.getHours()).padStart(2, '0'); const mm = String(now.getMinutes()).padStart(2, '0'); const ss = String(now.getSeconds()).padStart(2, '0'); return ( 	<div className="aff-classiques-departs__clock-container" aria-hidden> 	 <div className="aff-classiques-departs__clock-box"> 		<div className="aff-classiques-departs__clock-main">{hh}:{mm}</div> 		<div className="aff-classiques-departs__clock-seconds">{ss}</div> 	 </div> 	</div> ); } export default function ClassiquesDeparts(){ // lire le paramètre de requête ?gare=Nom-de-la-gare const params = new URLSearchParams(window.location.search); const gareParam = params.get('gare'); // support pour ?gare_id=123 ou ?gareId=123 const gareIdParam = params.get('gare_id') || params.get('gareId'); // gérer les +, décoder et remplacer les tirets par des espaces const gareDisplay = gareParam ? decodeURIComponent(String(gareParam).replace(/\+/g, ' ')).replace(/-/g, ' ') : null; // debug flag activable via ?debug=1 or ?debug=true const debugEnabled = (params.get('debug') === '1' || String(params.get('debug')).toLowerCase() === 'true'); const debug = useCallback((...args) => { if (debugEnabled) console.debug(...args); }, [debugEnabled]); // État pour alterner l'affichage toutes les 3 secondes const [showStatus, setShowStatus] = useState(false); // Données depuis Supabase const [horaires, setHoraires] = useState([]); const [allHoraires, setAllHoraires] = useState([]); const [perturbations, setPerturbations] = useState([]); // type de la gare affichée (valeurs attendues: 'interurbaine', 'ville', ...) const [stationType, setStationType] = useState(null); const [, setTravaux] = useState([]); const [, setLoading] = useState(false); const [, setError] = usLine truncated
|
||||||
|
</PendingDiffInfo>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="$PROJECT_DIR$/src/pages/afficheurs/classiques/quais/ClassiquesArriveesQuais.js">
|
||||||
|
<value>
|
||||||
|
<PendingDiffInfo>
|
||||||
|
<option name="filePath" value="$PROJECT_DIR$/src/pages/afficheurs/classiques/quais/ClassiquesArriveesQuais.js" />
|
||||||
|
<option name="originalContent" value="import React, { useEffect, useState, useRef, useCallback } from 'react'; import './ClassiquesArriveesQuais.css'; import '../ClassiquesArrivees.css'; /* ClassiquesArriveesQuais.js Variante "Arrivées - quais" du composant quais. Différences principales avec la version départs: - utilise `heure_arrivee` / `gare_arrivee_*` lorsque disponible pour afficher l'heure et la destination - watermark affiché: "arrivée" - styles importés depuis `ClassiquesArriveesQuais.css` qui reprend la palette de `ClassiquesArrivees.css` Champs utilisés pour le calcul/affichage: - horaire.heure_arrivee, horaire.time, horaire.heure - horaire.gare_arrivee_nom, horaire.gare_arrivee - stop.heure_arrivee, stop.gare_nom, stop.gare_id - perturbations: mêmes clés que pour les départs (retard, retard_minutes, perturbations_arrets, etc.) */ import supabase from '../../../../lib/supabase'; // Hook pour récupérer la map des logos depuis /type/data.json function useTypeLogos(){ const [map, setMap] = useState({ default: '/type/quais/logo-sncf-color.svg' }); useEffect(() => { let mounted = true; const load = async () => { const candidates = ['/type/quais/data-color.json', '/type/data.json']; for(const url of candidates){ try{ const res = await fetch(url); if(!res.ok) continue; const data = await res.json(); if(!mounted) return; const logos = {}; if(Array.isArray(data.logos)){ data.logos.forEach(item => { // item.file is expected (ex: logo-tgv.svg). If absent, try to extract from path let file = item.file; if(!file && item.path){ const parts = String(item.path).split('/'); file = parts[parts.length-1]; } if(!file) return; const basename = file.replace(/\.[^/.]+$/, ''); const semantic = basename.replace(/^logo-/, ''); const key = semantic.toUpperCase().replace(/[^A-Z0-9]+/g, '-'); // Prefer color logos in the 'quais' subfolder if data came from the quais file if(url.includes('/quais/')){ logos[key] = `/type/quais/${file}`; } else { logos[key] = `/type/${file}`; } }); } logos.default = logos['SNCF-VOYAGEURS-LOGO'] || logos['SNFC-VOYAGEURS-LOGO'] || logos['SNCF'] || '/type/sncf-voyageurs-logo.png'; setMap(logos); return; }catch(e){ // try next candidate (ignore error and continue loop) } } // no candidate succeeded — keep fallback }; load(); return () => { mounted = false; }; }, []); return map; } function getTypeLogo(type, TYPE_LOGOS_MAP){ const map = TYPE_LOGOS_MAP || { default: '/type/sncf-voyageurs-logo.png' }; if(!type) return map.default; const norm = String(type).toUpperCase().replace(/[^A-Z0-9]+/g, '-'); if(map[norm]) return map[norm]; const keys = Object.keys(map).filter(k => k !== 'default'); for(const k of keys){ if(k.includes(norm) || norm.includes(k)) return map[k]; } return map.default; } function Clock() { const [now, setNow] = useState(new Date()); useEffect(() => { const id = setInterval(() => setNow(new Date()), 1000); return () => clearInterval(id); }, []); const hh = String(now.getHours()).padStart(2,'0'); const mm = String(now.getMinutes()).padStart(2,'0'); const ss = String(now.getSeconds()).padStart(2,'0'); return ( <div className="aff-quais__clock"> <div className="aff-quais__clock-box"><span className="aff-quais__clock-main">{hh}:{mm}:{ss}</span></div> </div> ); } export default function ClassiquesArriveesQuais(){ const typeLogos = useTypeLogos(); const rightRef = useRef(null); const stopsListRef = useRef(null);Line truncated
|
||||||
|
<option name="updatedContent" value="import React, { useEffect, useState, useRef, useCallback } from 'react'; import './ClassiquesArriveesQuais.css'; import '../ClassiquesArrivees.css'; /* ClassiquesArriveesQuais.js Variante "Arrivées - quais" du composant quais. Différences principales avec la version départs: - utilise `heure_arrivee` / `gare_arrivee_*` lorsque disponible pour afficher l'heure et la destination - watermark affiché: "arrivée" - styles importés depuis `ClassiquesArriveesQuais.css` qui reprend la palette de `ClassiquesArrivees.css` Champs utilisés pour le calcul/affichage: - horaire.heure_arrivee, horaire.time, horaire.heure - horaire.gare_arrivee_nom, horaire.gare_arrivee - stop.heure_arrivee, stop.gare_nom, stop.gare_id - perturbations: mêmes clés que pour les départs (retard, retard_minutes, perturbations_arrets, etc.) */ import supabase from '../../../../lib/supabase'; // Hook pour récupérer la map des logos depuis /type/data.json function useTypeLogos(){ const [map, setMap] = useState({ default: '/type/quais/logo-sncf-color.svg' }); useEffect(() => { let mounted = true; const load = async () => { const candidates = ['/type/quais/data-color.json', '/type/data.json']; for(const url of candidates){ try{ const res = await fetch(url); if(!res.ok) continue; const data = await res.json(); if(!mounted) return; const logos = {}; if(Array.isArray(data.logos)){ data.logos.forEach(item => { // item.file is expected (ex: logo-tgv.svg). If absent, try to extract from path let file = item.file; if(!file && item.path){ const parts = String(item.path).split('/'); file = parts[parts.length-1]; } if(!file) return; const basename = file.replace(/\.[^/.]+$/, ''); const semantic = basename.replace(/^logo-/, ''); const key = semantic.toUpperCase().replace(/[^A-Z0-9]+/g, '-'); // Prefer color logos in the 'quais' subfolder if data came from the quais file if(url.includes('/quais/')){ logos[key] = `/type/quais/${file}`; } else { logos[key] = `/type/${file}`; } }); } logos.default = logos['SNCF-VOYAGEURS-LOGO'] || logos['SNFC-VOYAGEURS-LOGO'] || logos['SNCF'] || '/type/sncf-voyageurs-logo.png'; setMap(logos); return; }catch(e){ // try next candidate (ignore error and continue loop) } } // no candidate succeeded — keep fallback }; load(); return () => { mounted = false; }; }, []); return map; } function getTypeLogo(type, TYPE_LOGOS_MAP){ const map = TYPE_LOGOS_MAP || { default: '/type/sncf-voyageurs-logo.png' }; if(!type) return map.default; const norm = String(type).toUpperCase().replace(/[^A-Z0-9]+/g, '-'); if(map[norm]) return map[norm]; const keys = Object.keys(map).filter(k => k !== 'default'); for(const k of keys){ if(k.includes(norm) || norm.includes(k)) return map[k]; } return map.default; } function Clock() { const [now, setNow] = useState(new Date()); useEffect(() => { const id = setInterval(() => setNow(new Date()), 1000); return () => clearInterval(id); }, []); const hh = String(now.getHours()).padStart(2,'0'); const mm = String(now.getMinutes()).padStart(2,'0'); const ss = String(now.getSeconds()).padStart(2,'0'); return ( <div className="aff-quais__clock"> <div className="aff-quais__clock-box"><span className="aff-quais__clock-main">{hh}:{mm}:{ss}</span></div> </div> ); } export default function ClassiquesArriveesQuais(){ const typeLogos = useTypeLogos(); const rightRef = useRef(null); const stopsListRef = useRef(null);
Line truncated
|
||||||
|
</PendingDiffInfo>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="$PROJECT_DIR$/src/pages/afficheurs/classiques/quais/ClassiquesDepartsQuais.js">
|
||||||
|
<value>
|
||||||
|
<PendingDiffInfo>
|
||||||
|
<option name="filePath" value="$PROJECT_DIR$/src/pages/afficheurs/classiques/quais/ClassiquesDepartsQuais.js" />
|
||||||
|
<option name="originalContent" value="import React, { useEffect, useState, useRef, useCallback } from 'react'; import './ClassiquesDepartsQuais.css'; import supabase from '../../../../lib/supabase'; // Hook pour récupérer la map des logos depuis /type/data.json function useTypeLogos(){ const [map, setMap] = useState({ default: '/type/quais/logo-sncf-color.svg' }); useEffect(() => { let mounted = true; const load = async () => { const candidates = ['/type/quais/data-color.json', '/type/data.json']; for(const url of candidates){ try{ const res = await fetch(url); if(!res.ok) continue; const data = await res.json(); if(!mounted) return; const logos = {}; if(Array.isArray(data.logos)){ data.logos.forEach(item => { // item.file is expected (ex: logo-tgv.svg). If absent, try to extract from path let file = item.file; if(!file && item.path){ const parts = String(item.path).split('/'); file = parts[parts.length-1]; } if(!file) return; const basename = file.replace(/\.[^/.]+$/, ''); const semantic = basename.replace(/^logo-/, ''); const key = semantic.toUpperCase().replace(/[^A-Z0-9]+/g, '-'); // Prefer color logos in the 'quais' subfolder if data came from the quais file if(url.includes('/quais/')){ logos[key] = `/type/quais/${file}`; } else { logos[key] = `/type/${file}`; } }); } logos.default = logos['SNCF-VOYAGEURS-LOGO'] || logos['SNFC-VOYAGEURS-LOGO'] || logos['SNCF'] || '/type/sncf-voyageurs-logo.png'; setMap(logos); return; }catch(e){ // try next candidate (ignore error and continue loop) } } // no candidate succeeded — keep fallback }; load(); return () => { mounted = false; }; }, []); return map; } function getTypeLogo(type, TYPE_LOGOS_MAP){ const map = TYPE_LOGOS_MAP || { default: '/type/sncf-voyageurs-logo.png' }; if(!type) return map.default; const norm = String(type).toUpperCase().replace(/[^A-Z0-9]+/g, '-'); if(map[norm]) return map[norm]; const keys = Object.keys(map).filter(k => k !== 'default'); for(const k of keys){ if(k.includes(norm) || norm.includes(k)) return map[k]; } return map.default; } function Clock() { const [now, setNow] = useState(new Date()); useEffect(() => { const id = setInterval(() => setNow(new Date()), 1000); return () => clearInterval(id); }, []); const hh = String(now.getHours()).padStart(2,'0'); const mm = String(now.getMinutes()).padStart(2,'0'); const ss = String(now.getSeconds()).padStart(2,'0'); return ( <div className="aff-quais__clock"> <div className="aff-quais__clock-box"><span className="aff-quais__clock-main">{hh}:{mm}:{ss}</span></div> </div> ); } export default function ClassiquesDepartsQuais(){ const typeLogos = useTypeLogos(); const rightRef = useRef(null); const stopsListRef = useRef(null); const railRef = useRef(null); // fallback mock strict (utilisé uniquement si aucune donnée réelle n'est trouvée) const mock = { time: '16h44', status: "à l'heure", trainType: 'Fluo', trainNumber: '891811', destinationBig: 'Seurre', destinationStation: '', stops: [ 'Ouges','Saulon','Longecourt','Aiserey','Brazey-en-Plaine','Saint-Jean-de-Losne','Chaugey','Pagny','Seurre','Mervans','Louhans','Saint-Amour','Bourg-en-Bresse' ], }; // état pour l'horaire sélectionné const [selectedHoraire, setSelectedHoraire] = useState(null); const [loadingHoraire, setLoadingHoraire] = useState(false); const [horaireError, setHoraireError] = useState(null); const [candidatesCount, setCandidatesCount] = useState(0); // perturbations/travaux (récupérées depuis Supabase) const [perturbations, setPerturbations] = useState([]); const [, setTravaux] = useState([]); // helpers locaux (simples) — similaires à ceux du composant principal const normalizeName = useCallback((s) => { if (!s) return ''; try { return String(s).normalize('NFD').replace(/\p{M}/gu,'').toLowerCase().trim().replace(/[-_]+/g,' ').replace(/\s+/g,' '); } catch (eLine truncated
|
||||||
|
<option name="updatedContent" value="import React, { useEffect, useState, useRef, useCallback } from 'react'; import './ClassiquesDepartsQuais.css'; import supabase from '../../../../lib/supabase'; // Hook pour récupérer la map des logos depuis /type/data.json function useTypeLogos(){ const [map, setMap] = useState({ default: '/type/quais/logo-sncf-color.svg' }); useEffect(() => { let mounted = true; const load = async () => { const candidates = ['/type/quais/data-color.json', '/type/data.json']; for(const url of candidates){ try{ const res = await fetch(url); if(!res.ok) continue; const data = await res.json(); if(!mounted) return; const logos = {}; if(Array.isArray(data.logos)){ data.logos.forEach(item => { // item.file is expected (ex: logo-tgv.svg). If absent, try to extract from path let file = item.file; if(!file && item.path){ const parts = String(item.path).split('/'); file = parts[parts.length-1]; } if(!file) return; const basename = file.replace(/\.[^/.]+$/, ''); const semantic = basename.replace(/^logo-/, ''); const key = semantic.toUpperCase().replace(/[^A-Z0-9]+/g, '-'); // Prefer color logos in the 'quais' subfolder if data came from the quais file if(url.includes('/quais/')){ logos[key] = `/type/quais/${file}`; } else { logos[key] = `/type/${file}`; } }); } logos.default = logos['SNCF-VOYAGEURS-LOGO'] || logos['SNFC-VOYAGEURS-LOGO'] || logos['SNCF'] || '/type/sncf-voyageurs-logo.png'; setMap(logos); return; }catch(e){ // try next candidate (ignore error and continue loop) } } // no candidate succeeded — keep fallback }; load(); return () => { mounted = false; }; }, []); return map; } function getTypeLogo(type, TYPE_LOGOS_MAP){ const map = TYPE_LOGOS_MAP || { default: '/type/sncf-voyageurs-logo.png' }; if(!type) return map.default; const norm = String(type).toUpperCase().replace(/[^A-Z0-9]+/g, '-'); if(map[norm]) return map[norm]; const keys = Object.keys(map).filter(k => k !== 'default'); for(const k of keys){ if(k.includes(norm) || norm.includes(k)) return map[k]; } return map.default; } function Clock() { const [now, setNow] = useState(new Date()); useEffect(() => { const id = setInterval(() => setNow(new Date()), 1000); return () => clearInterval(id); }, []); const hh = String(now.getHours()).padStart(2,'0'); const mm = String(now.getMinutes()).padStart(2,'0'); const ss = String(now.getSeconds()).padStart(2,'0'); return ( <div className="aff-quais__clock"> <div className="aff-quais__clock-box"><span className="aff-quais__clock-main">{hh}:{mm}:{ss}</span></div> </div> ); } export default function ClassiquesDepartsQuais(){ const typeLogos = useTypeLogos(); const rightRef = useRef(null); const stopsListRef = useRef(null); const railRef = useRef(null); // fallback mock strict (utilisé uniquement si aucune donnée réelle n'est trouvée) const mock = { time: '16h44', status: "à l'heure", trainType: 'Fluo', trainNumber: '891811', destinationBig: 'Seurre', destinationStation: '', stops: [ 'Ouges','Saulon','Longecourt','Aiserey','Brazey-en-Plaine','Saint-Jean-de-Losne','Chaugey','Pagny','Seurre','Mervans','Louhans','Saint-Amour','Bourg-en-Bresse' ], }; // état pour l'horaire sélectionné const [selectedHoraire, setSelectedHoraire] = useState(null); const [loadingHoraire, setLoadingHoraire] = useState(false); const [horaireError, setHoraireError] = useState(null); const [candidatesCount, setCandidatesCount] = useState(0); // perturbations/travaux (récupérées depuis Supabase) const [perturbations, setPerturbations] = useState([]); const [, setTravaux] = useState([]); // helpers locaux (simples) — similaires à ceux du composant principal const normalizeName = useCallback((s) => { if (!s) return ''; try { return String(s).normalize('NFD').replace(/\p{M}/gu,'').toLowerCase().trim().replace(/[-_]+/g,' ').replace(/\s+/g,' '); } catch (e)Line truncated
|
||||||
|
</PendingDiffInfo>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
Generated
-17
@@ -16098,23 +16098,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tailwindcss/node_modules/yaml": {
|
|
||||||
"version": "2.8.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
|
|
||||||
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
|
|
||||||
"license": "ISC",
|
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
|
||||||
"yaml": "bin.mjs"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 14.6"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/eemeli"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
|
||||||
|
|||||||
@@ -416,7 +416,7 @@ export default function ClassiquesDeparts(){
|
|||||||
|
|
||||||
if (maxDelay != null) return { label: `retardé +${maxDelay}min.`, detail: '', delayMinutes: maxDelay };
|
if (maxDelay != null) return { label: `retardé +${maxDelay}min.`, detail: '', delayMinutes: maxDelay };
|
||||||
return { label: "à l'heure", detail: '', delayMinutes: null };
|
return { label: "à l'heure", detail: '', delayMinutes: null };
|
||||||
}, [findPerturbsForHoraireAndStop, parsePerturbArretsObject, getPerturbationJours, parseDelayMinutesFromArret, normalizeName]);
|
}, [findPerturbsForHoraireAndStop, parsePerturbArretsObject, getPerturbationJours, parseDelayMinutesFromArret, normalizeName, debug]);
|
||||||
|
|
||||||
// Applique les perturbations à une liste d'horaires : calcule status par arrêt et met à jour l'heure affichée
|
// Applique les perturbations à une liste d'horaires : calcule status par arrêt et met à jour l'heure affichée
|
||||||
const applyPerturbationsToHoraires = useCallback((list = [], perturbList = perturbations, displayStationId = null, displayStationName = null, serviceDate = null) => {
|
const applyPerturbationsToHoraires = useCallback((list = [], perturbList = perturbations, displayStationId = null, displayStationName = null, serviceDate = null) => {
|
||||||
@@ -471,7 +471,7 @@ export default function ClassiquesDeparts(){
|
|||||||
horaire._displayPlatform = (stopForStation && (stopForStation.quai || stopForStation.platform || stopForStation.quay)) || horaire.platform || '';
|
horaire._displayPlatform = (stopForStation && (stopForStation.quai || stopForStation.platform || stopForStation.quay)) || horaire.platform || '';
|
||||||
return horaire;
|
return horaire;
|
||||||
});
|
});
|
||||||
}, [buildPerturbMap, computeStatusForHoraireAtStop, formatTimeFromHM, perturbations, gareDisplay, gareIdParam, getStops, normalizeName, debug]);
|
}, [buildPerturbMap, computeStatusForHoraireAtStop, formatTimeFromHM, perturbations, gareDisplay, gareIdParam, getStops, normalizeName]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const id = setInterval(() => setShowStatus(s => !s), 3000);
|
const id = setInterval(() => setShowStatus(s => !s), 3000);
|
||||||
@@ -915,7 +915,7 @@ export default function ClassiquesDeparts(){
|
|||||||
const intervalId = setInterval(fetchData, intervalMs);
|
const intervalId = setInterval(fetchData, intervalMs);
|
||||||
|
|
||||||
return () => { mounted = false; clearInterval(intervalId); };
|
return () => { mounted = false; clearInterval(intervalId); };
|
||||||
}, [gareDisplay, gareIdParam, buildPerturbMap, computeStatusForHoraireAtStop, findPerturbsForHoraireAndStop, normalizeName, formatTimeFromHM, applyPerturbationsToHoraires, debug, getStops]);
|
}, [gareDisplay, gareIdParam, buildPerturbMap, computeStatusForHoraireAtStop, findPerturbsForHoraireAndStop, normalizeName, formatTimeFromHM, applyPerturbationsToHoraires, debug, getStops, getPerturbationJours]);
|
||||||
|
|
||||||
// Helpers pour perturbations (memoized plus haut)
|
// Helpers pour perturbations (memoized plus haut)
|
||||||
|
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ export default function ClassiquesArriveesQuais(){
|
|||||||
} catch (e) { return []; }
|
} catch (e) { return []; }
|
||||||
};
|
};
|
||||||
|
|
||||||
const parsePerturbArretsObject = (p) => {
|
const parsePerturbArretsObject = useCallback((p) => {
|
||||||
const raw = p && (p.perturbations_arrets || p.arrets || p.arrets_perturbations);
|
const raw = p && (p.perturbations_arrets || p.arrets || p.arrets_perturbations);
|
||||||
if (!raw) return { arrets: [], jours: null };
|
if (!raw) return { arrets: [], jours: null };
|
||||||
if (typeof raw === 'object') {
|
if (typeof raw === 'object') {
|
||||||
@@ -230,7 +230,7 @@ export default function ClassiquesArriveesQuais(){
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
return { arrets: [], jours: null };
|
return { arrets: [], jours: null };
|
||||||
}
|
}
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const getPerturbationJours = useCallback((p) => {
|
const getPerturbationJours = useCallback((p) => {
|
||||||
if (!p) return null;
|
if (!p) return null;
|
||||||
@@ -371,7 +371,7 @@ export default function ClassiquesArriveesQuais(){
|
|||||||
}
|
}
|
||||||
if (maxDelay != null) return { label: `retardé +${maxDelay}min.`, detail: '', delayMinutes: maxDelay };
|
if (maxDelay != null) return { label: `retardé +${maxDelay}min.`, detail: '', delayMinutes: maxDelay };
|
||||||
return { label: "à l'heure", detail: '', delayMinutes: null };
|
return { label: "à l'heure", detail: '', delayMinutes: null };
|
||||||
}, [findPerturbsForHoraireAndStop, parseDelayMinutesFromArret, getPerturbationJours]);
|
}, [findPerturbsForHoraireAndStop, parseDelayMinutesFromArret, getPerturbationJours, normalizeName]);
|
||||||
|
|
||||||
// Fetch perturbations & travaux from Supabase periodically
|
// Fetch perturbations & travaux from Supabase periodically
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -417,7 +417,7 @@ export default function ClassiquesArriveesQuais(){
|
|||||||
fetchPerturb();
|
fetchPerturb();
|
||||||
const id = setInterval(fetchPerturb, 15000);
|
const id = setInterval(fetchPerturb, 15000);
|
||||||
return () => { mounted = false; clearInterval(id); };
|
return () => { mounted = false; clearInterval(id); };
|
||||||
}, []);
|
}, [getPerturbationJours]);
|
||||||
|
|
||||||
// Annotate selectedHoraire with computed status when perturbations change
|
// Annotate selectedHoraire with computed status when perturbations change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -579,7 +579,7 @@ export default function ClassiquesArriveesQuais(){
|
|||||||
|
|
||||||
loadNextForQuai();
|
loadNextForQuai();
|
||||||
return () => { mounted = false; };
|
return () => { mounted = false; };
|
||||||
}, [gareDisplayParam, gareIdParam, quaiParam, parseTimeHM]);
|
}, [gareDisplayParam, gareIdParam, quaiParam, parseTimeHM, normalizeName]);
|
||||||
|
|
||||||
// toggle flag to alternate time/status when needed (observe selectedHoraire.status when present)
|
// toggle flag to alternate time/status when needed (observe selectedHoraire.status when present)
|
||||||
const [showTime, setShowTime] = useState(true);
|
const [showTime, setShowTime] = useState(true);
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ export default function ClassiquesDepartsQuais(){
|
|||||||
} catch (e) { return []; }
|
} catch (e) { return []; }
|
||||||
};
|
};
|
||||||
|
|
||||||
const parsePerturbArretsObject = (p) => {
|
const parsePerturbArretsObject = useCallback((p) => {
|
||||||
const raw = p && (p.perturbations_arrets || p.arrets || p.arrets_perturbations);
|
const raw = p && (p.perturbations_arrets || p.arrets || p.arrets_perturbations);
|
||||||
if (!raw) return { arrets: [], jours: null };
|
if (!raw) return { arrets: [], jours: null };
|
||||||
if (typeof raw === 'object') {
|
if (typeof raw === 'object') {
|
||||||
@@ -213,7 +213,7 @@ export default function ClassiquesDepartsQuais(){
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
return { arrets: [], jours: null };
|
return { arrets: [], jours: null };
|
||||||
}
|
}
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const getPerturbationJours = useCallback((p) => {
|
const getPerturbationJours = useCallback((p) => {
|
||||||
if (!p) return null;
|
if (!p) return null;
|
||||||
@@ -354,7 +354,7 @@ export default function ClassiquesDepartsQuais(){
|
|||||||
}
|
}
|
||||||
if (maxDelay != null) return { label: `retardé +${maxDelay}min.`, detail: '', delayMinutes: maxDelay };
|
if (maxDelay != null) return { label: `retardé +${maxDelay}min.`, detail: '', delayMinutes: maxDelay };
|
||||||
return { label: "à l'heure", detail: '', delayMinutes: null };
|
return { label: "à l'heure", detail: '', delayMinutes: null };
|
||||||
}, [findPerturbsForHoraireAndStop, parseDelayMinutesFromArret, getPerturbationJours]);
|
}, [findPerturbsForHoraireAndStop, parseDelayMinutesFromArret, getPerturbationJours, normalizeName]);
|
||||||
|
|
||||||
// Fetch perturbations & travaux from Supabase periodically
|
// Fetch perturbations & travaux from Supabase periodically
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -400,7 +400,7 @@ export default function ClassiquesDepartsQuais(){
|
|||||||
fetchPerturb();
|
fetchPerturb();
|
||||||
const id = setInterval(fetchPerturb, 15000);
|
const id = setInterval(fetchPerturb, 15000);
|
||||||
return () => { mounted = false; clearInterval(id); };
|
return () => { mounted = false; clearInterval(id); };
|
||||||
}, []);
|
}, [getPerturbationJours]);
|
||||||
|
|
||||||
// Annotate selectedHoraire with computed status when perturbations change
|
// Annotate selectedHoraire with computed status when perturbations change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -609,7 +609,7 @@ export default function ClassiquesDepartsQuais(){
|
|||||||
|
|
||||||
loadNextForQuai();
|
loadNextForQuai();
|
||||||
return () => { mounted = false; };
|
return () => { mounted = false; };
|
||||||
}, [gareDisplayParam, gareIdParam, quaiParam, parseTimeHM]);
|
}, [gareDisplayParam, gareIdParam, quaiParam, parseTimeHM, normalizeName]);
|
||||||
|
|
||||||
// toggle flag to alternate time/status when needed (observe selectedHoraire.status when present)
|
// toggle flag to alternate time/status when needed (observe selectedHoraire.status when present)
|
||||||
const [showTime, setShowTime] = useState(true);
|
const [showTime, setShowTime] = useState(true);
|
||||||
|
|||||||
Reference in new issue
Block a user