commit
3fcdf7e5ef
172 files changed
+52525
No files matched your search
@@ -0,0 +1,115 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import supabase from '../lib/supabase';
|
||||
import sessionMemory from '../lib/sessionMemory';
|
||||
|
||||
export default function Departs({ onBack, navigate }) {
|
||||
const [gares, setGares] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
const [selected, setSelected] = useState('');
|
||||
const [search, setSearch] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
let mounted = true;
|
||||
|
||||
async function loadGares() {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
if (!supabase) {
|
||||
// Le client Supabase n'a pas pu être initialisé (variables d'env manquantes)
|
||||
if (mounted) {
|
||||
setError(
|
||||
"Supabase non initialisé : vérifiez REACT_APP_SUPABASE_URL et REACT_APP_SUPABASE_ANON_KEY dans votre .env et redémarrez le serveur de développement (npm start)."
|
||||
);
|
||||
setLoading(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const { data, error } = await supabase.from('gares').select('nom');
|
||||
if (error) throw error;
|
||||
if (mounted) setGares(Array.isArray(data) ? data.map((r) => r.nom) : []);
|
||||
} catch (err) {
|
||||
console.error('Supabase error:', err);
|
||||
if (mounted) setError(err.message || String(err));
|
||||
} finally {
|
||||
if (mounted) setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
loadGares();
|
||||
|
||||
return () => {
|
||||
mounted = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ padding: 20 }}>
|
||||
<h1>Départs</h1>
|
||||
|
||||
{loading && <p>Chargement des gares...</p>}
|
||||
{error && <p style={{ color: 'red' }}>Erreur : {error}</p>}
|
||||
|
||||
{!loading && !error && (
|
||||
<div>
|
||||
{/* Barre de recherche centrée */}
|
||||
<div style={{ display: 'flex', justifyContent: 'center', marginBottom: 16 }}>
|
||||
<input
|
||||
type="search"
|
||||
placeholder="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"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Résultats sous forme de lignes */}
|
||||
<div role="list" aria-label="Résultats des gares">
|
||||
{gares
|
||||
.filter((nom) => nom.toLowerCase().includes(search.trim().toLowerCase()))
|
||||
.map((nom) => (
|
||||
<div key={nom} role="listitem">
|
||||
<div
|
||||
style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '8px 0', cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
setSelected(nom);
|
||||
try { sessionMemory.set('afficheurMode', 'departs'); } catch (e) {}
|
||||
if (navigate) navigate(`/afficheurs/${encodeURIComponent(nom)}?mode=departs`);
|
||||
}}
|
||||
onKeyDown={(e) => (e.key === 'Enter' ? (navigate ? navigate(`/afficheurs/${encodeURIComponent(nom)}?mode=departs`) : setSelected(nom)) : null)}
|
||||
tabIndex={0}
|
||||
>
|
||||
<div>{nom}</div>
|
||||
{selected === nom && <div style={{ color: '#0070f3' }}>Sélectionnée</div>}
|
||||
</div>
|
||||
<div style={{ height: 1, background: '#e0e0e0', margin: '6px 0' }} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{selected && (
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<p>Gare sélectionnée : <strong>{selected}</strong></p>
|
||||
<button onClick={() => {
|
||||
try { sessionMemory.set('afficheurMode', 'departs'); } catch (e) {}
|
||||
if (navigate) {
|
||||
navigate(`/afficheurs/${encodeURIComponent(selected)}?mode=departs`);
|
||||
} else {
|
||||
alert(`Afficher les départs pour ${selected}`);
|
||||
}
|
||||
}}>Voir les départs</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ marginTop: 20 }}>
|
||||
<button onClick={onBack}>Retour</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user