Désactivation des annonces sonores et refonte responsive mobile/tablette des pages de guidage WCS
This commit is contained in:
1 parent
4f3a34b101
commit
983f4f0160
9 files changed
+1315
-842
No files matched your search
+141
-91
@@ -1,7 +1,21 @@
|
||||
import React, { useEffect, useState, useMemo } from 'react';
|
||||
import WcsButton from '../components/WcsButton';
|
||||
import sessionMemory from '../lib/sessionMemory';
|
||||
import { getSourceFromPath, searchGares } from '../services/railwayService';
|
||||
|
||||
const POPULAR_GARES = [
|
||||
'Paris-Gare-de-Lyon',
|
||||
'Besançon-Viotte',
|
||||
'Dijon-Ville',
|
||||
'Lyon-Part-Dieu',
|
||||
'Marseille-Saint-Charles',
|
||||
'Lille-Flandres',
|
||||
'Strasbourg',
|
||||
'Bordeaux-Saint-Jean',
|
||||
'Nantes',
|
||||
'Rennes'
|
||||
];
|
||||
|
||||
export default function Departs({ onBack, navigate }) {
|
||||
const source = getSourceFromPath(window.location.pathname);
|
||||
const prefix = source === 'supabase' ? '/ferrovia' : '';
|
||||
@@ -10,7 +24,6 @@ export default function Departs({ onBack, navigate }) {
|
||||
const [sncfResults, setSncfResults] = useState([]);
|
||||
const [loading, setLoading] = useState(source === 'supabase');
|
||||
const [error, setError] = useState(null);
|
||||
const [selected, setSelected] = useState('');
|
||||
const [search, setSearch] = useState('');
|
||||
|
||||
// Pour Supabase : charger les gares une seule fois au montage
|
||||
@@ -51,7 +64,7 @@ export default function Departs({ onBack, navigate }) {
|
||||
} catch (e) {
|
||||
if (active) setSncfResults([]);
|
||||
}
|
||||
}, 200);
|
||||
}, 180);
|
||||
|
||||
return () => {
|
||||
active = false;
|
||||
@@ -70,109 +83,146 @@ export default function Departs({ onBack, navigate }) {
|
||||
}, [source, allGares, sncfResults, search]);
|
||||
|
||||
const handleSelectGare = (nom) => {
|
||||
setSelected(nom);
|
||||
try { sessionMemory.set('afficheurMode', 'departs'); } catch (e) {}
|
||||
if (navigate) {
|
||||
navigate(`${prefix}/afficheurs/${encodeURIComponent(nom)}?mode=departs`);
|
||||
const cleanNom = String(nom).trim().replace(/\s+/g, '-');
|
||||
navigate(`${prefix}/afficheurs/${encodeURIComponent(cleanNom)}?mode=departs`);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ padding: 20 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
|
||||
<h1 style={{ margin: 0 }}>Départs</h1>
|
||||
<span style={{
|
||||
fontSize: '12px',
|
||||
fontWeight: '600',
|
||||
padding: '4px 10px',
|
||||
borderRadius: '12px',
|
||||
background: source === 'supabase' ? '#e6f4ea' : '#e8f0fe',
|
||||
color: source === 'supabase' ? '#137333' : '#1a73e8'
|
||||
}}>
|
||||
{source === 'supabase' ? '🗄️ BDD Ferrovia' : '🌐 SNCF (GTFS)'}
|
||||
</span>
|
||||
<div className="launcher-container">
|
||||
{/* Stepper */}
|
||||
<div className="launcher-stepper">
|
||||
<div className="launcher-step launcher-step--active">
|
||||
<span className="launcher-step-num">1</span>
|
||||
<span>Choix de la gare</span>
|
||||
</div>
|
||||
<span className="launcher-step-separator">›</span>
|
||||
<div className="launcher-step">
|
||||
<span className="launcher-step-num">2</span>
|
||||
<span>Type d'afficheur</span>
|
||||
</div>
|
||||
<span className="launcher-step-separator">›</span>
|
||||
<div className="launcher-step">
|
||||
<span className="launcher-step-num">3</span>
|
||||
<span>Options & Affichage</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{loading && <p>Chargement des gares...</p>}
|
||||
{error && <p style={{ color: 'red' }}>Erreur : {error}</p>}
|
||||
|
||||
{!loading && !error && (
|
||||
<div>
|
||||
{/* Barre de recherche */}
|
||||
<div style={{ display: 'flex', justifyContent: 'center', marginBottom: 16 }}>
|
||||
<input
|
||||
type="search"
|
||||
placeholder={source === 'sncf' ? "Rechercher une gare SNCF (ex: Dijon, Paris, Lyon...)" : "Rechercher une gare..."}
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
style={{ width: '60%', padding: '10px 12px', borderRadius: 6, border: '1px solid #ccc' }}
|
||||
aria-label="Rechercher une gare"
|
||||
autoFocus
|
||||
/>
|
||||
<div className="launcher-card">
|
||||
{/* Header */}
|
||||
<div className="launcher-header">
|
||||
<div>
|
||||
<h1 className="launcher-title">🚆 Prochains Départs</h1>
|
||||
<p className="launcher-subtitle">Recherchez une gare pour afficher le tableau des départs en temps réel.</p>
|
||||
</div>
|
||||
<span className={`launcher-badge ${source === 'supabase' ? 'launcher-badge--supabase' : ''}`}>
|
||||
{source === 'supabase' ? '🗄️ BDD Ferrovia' : '🌐 SNCF GTFS Live'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Invitation à la recherche en mode SNCF */}
|
||||
{source === 'sncf' && search.trim().length < 2 && (
|
||||
<div style={{ textAlign: 'center', padding: '30px 16px', color: '#666', background: '#fff', borderRadius: '8px', border: '1px dashed #ccc' }}>
|
||||
<p style={{ margin: 0, fontSize: '15px' }}>
|
||||
🔍 <strong>Saisissez au moins 2 caractères</strong> pour rechercher parmi les gares du référentiel GTFS SNCF.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Aucun résultat */}
|
||||
{source === 'sncf' && search.trim().length >= 2 && displayedGares.length === 0 && (
|
||||
<div style={{ textAlign: 'center', padding: '20px', color: '#777' }}>
|
||||
Aucune gare SNCF trouvée pour "{search}".
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Résultats */}
|
||||
{displayedGares.length > 0 && (
|
||||
<div role="list" aria-label="Résultats des gares" style={{ background: '#fff', borderRadius: '8px', padding: '8px 16px', boxShadow: '0 1px 4px rgba(0,0,0,0.06)' }}>
|
||||
{displayedGares.map((g) => {
|
||||
const nom = g.nom;
|
||||
return (
|
||||
<div key={g.uic || nom} role="listitem">
|
||||
<div
|
||||
style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '10px 0', cursor: 'pointer' }}
|
||||
onClick={() => handleSelectGare(nom)}
|
||||
onKeyDown={(e) => (e.key === 'Enter' ? handleSelectGare(nom) : null)}
|
||||
tabIndex={0}
|
||||
>
|
||||
<div>
|
||||
<strong style={{ fontSize: '15px' }}>{nom}</strong>
|
||||
{g.commune && <span style={{ marginLeft: '8px', color: '#666', fontSize: '13px' }}>({g.commune} - {g.departement})</span>}
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
||||
{g.uic && <span style={{ fontSize: '11px', color: '#888', background: '#f1f3f4', padding: '2px 6px', borderRadius: '4px' }}>UIC {g.uic}</span>}
|
||||
{selected === nom && <div style={{ color: '#0070f3' }}>Sélectionnée</div>}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ height: 1, background: '#eef1f6', margin: '2px 0' }} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selected && (
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<p>Gare sélectionnée : <strong>{selected}</strong></p>
|
||||
<button onClick={() => {
|
||||
try { sessionMemory.set('afficheurMode', 'departs'); } catch (e) {}
|
||||
if (navigate) {
|
||||
navigate(`${prefix}/afficheurs/${encodeURIComponent(selected)}?mode=departs`);
|
||||
}
|
||||
}}>Voir les départs</button>
|
||||
</div>
|
||||
{/* Barre de recherche */}
|
||||
<div className="launcher-search-box">
|
||||
<input
|
||||
type="search"
|
||||
placeholder="Rechercher une gare (ex: Dijon, Paris, Lyon, Besançon...)"
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
className="launcher-search-input"
|
||||
aria-label="Rechercher une gare"
|
||||
autoFocus
|
||||
/>
|
||||
{search && (
|
||||
<button
|
||||
type="button"
|
||||
className="launcher-search-clear"
|
||||
onClick={() => setSearch('')}
|
||||
aria-label="Effacer la recherche"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ marginTop: 20 }}>
|
||||
<button onClick={onBack}>Retour</button>
|
||||
{/* Suggestions rapides / Gares populaires */}
|
||||
<div className="launcher-chips-container">
|
||||
<span className="launcher-chips-label">Gares fréquentes :</span>
|
||||
<div className="launcher-chips-list">
|
||||
{POPULAR_GARES.map((gName) => (
|
||||
<button
|
||||
key={gName}
|
||||
type="button"
|
||||
className="launcher-chip"
|
||||
onClick={() => handleSelectGare(gName)}
|
||||
>
|
||||
{gName.replace(/-/g, ' ')}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{loading && <p style={{ color: '#00439e', fontWeight: 600 }}>⏳ Chargement des gares...</p>}
|
||||
{error && <p style={{ color: '#d70022', fontWeight: 600 }}>⚠️ Erreur : {error}</p>}
|
||||
|
||||
{/* Invitation à la recherche en mode SNCF */}
|
||||
{source === 'sncf' && search.trim().length < 2 && (
|
||||
<div style={{ textAlign: 'center', padding: '24px 16px', color: '#666', background: '#f8fafc', borderRadius: '8px', border: '1px dashed #d0d7de' }}>
|
||||
<p style={{ margin: 0, fontSize: '14px' }}>
|
||||
💡 Saisissez au moins <strong>2 lettres</strong> pour chercher parmi plus de 3 500 gares du réseau français.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Aucun résultat */}
|
||||
{source === 'sncf' && search.trim().length >= 2 && displayedGares.length === 0 && (
|
||||
<div style={{ textAlign: 'center', padding: '24px', color: '#777', background: '#fff', borderRadius: '8px' }}>
|
||||
Aucune gare trouvée pour « <strong>{search}</strong> ».
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Liste des résultats */}
|
||||
{displayedGares.length > 0 && (
|
||||
<div className="launcher-results-list" role="list">
|
||||
{displayedGares.map((g) => {
|
||||
const nom = g.nom;
|
||||
return (
|
||||
<div
|
||||
key={g.uic || nom}
|
||||
className="launcher-result-item"
|
||||
onClick={() => handleSelectGare(nom)}
|
||||
onKeyDown={(e) => (e.key === 'Enter' ? handleSelectGare(nom) : null)}
|
||||
tabIndex={0}
|
||||
role="listitem"
|
||||
>
|
||||
<div>
|
||||
<div className="launcher-result-name">{nom}</div>
|
||||
{g.commune && (
|
||||
<div className="launcher-result-sub">
|
||||
{g.commune} {g.departement ? `(${g.departement})` : ''}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
||||
{g.uic && <span className="launcher-result-tag">UIC {g.uic}</span>}
|
||||
<span style={{ color: '#00439e', fontSize: '18px', fontWeight: 'bold' }}>›</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Navigation retour */}
|
||||
<div className="launcher-footer-nav">
|
||||
<WcsButton
|
||||
mode="plain"
|
||||
onClick={onBack}
|
||||
label="← Retour à l'accueil"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user