V2.0.1 : VOICI LES MODIFICATIONS MAJEURS APPRTÉES DANS CETTE VERSION :
-> REFONTE DU DESIGN DES AFFICHEURS CLASSIQUES (GÉNÉRAL + QUAIS) -> IMPLÉMENTATION DU DESIGN AFL : GÉNÉRAL ET QUAIS -> CHOIX DE LA SÉLECTION DES TYPES D'AFFICHEURS (GÉNÉRAL / QUAIS) UNE FOIS LE TYPE D'AFFICHEUR SÉLECTIONNÉS
This commit is contained in:
1 parent
71822823f2
commit
19868a451f
16 files changed
+156
-48
No files matched your search
@@ -0,0 +1,8 @@
|
|||||||
|
require('dotenv').config();
|
||||||
|
const { createClient } = require('@supabase/supabase-js');
|
||||||
|
const supabase = createClient(process.env.REACT_APP_SUPABASE_URL, process.env.REACT_APP_SUPABASE_ANON_KEY);
|
||||||
|
async function run() {
|
||||||
|
const { data, error } = await supabase.rpc('get_tables');
|
||||||
|
// If rpc fails, we can query information_schema or just list common table names
|
||||||
|
}
|
||||||
|
run();
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
require('dotenv').config();
|
||||||
|
const { createClient } = require('@supabase/supabase-js');
|
||||||
|
const supabase = createClient(process.env.REACT_APP_SUPABASE_URL, process.env.REACT_APP_SUPABASE_ANON_KEY);
|
||||||
|
async function run() {
|
||||||
|
const { data, error } = await supabase.from('annonces_diffusions').select('*').order('created_at', { ascending: false }).limit(1);
|
||||||
|
if (error) console.error(error);
|
||||||
|
else console.log(JSON.stringify(data[0], null, 2));
|
||||||
|
}
|
||||||
|
run();
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
require('dotenv').config();
|
||||||
|
const { createClient } = require('@supabase/supabase-js');
|
||||||
|
const supabase = createClient(process.env.REACT_APP_SUPABASE_URL, process.env.REACT_APP_SUPABASE_ANON_KEY);
|
||||||
|
async function run() {
|
||||||
|
const { data, error } = await supabase.from('annonces').select('*').limit(2);
|
||||||
|
if (error) console.error(error);
|
||||||
|
else console.log(JSON.stringify(data, null, 2));
|
||||||
|
}
|
||||||
|
run();
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
require('dotenv').config();
|
||||||
|
const { createClient } = require('@supabase/supabase-js');
|
||||||
|
const supabase = createClient(process.env.REACT_APP_SUPABASE_URL, process.env.REACT_APP_SUPABASE_ANON_KEY);
|
||||||
|
async function run() {
|
||||||
|
const { data, error } = await supabase.from('annonces_diffusions').select('*').limit(1);
|
||||||
|
if (error) console.error(error);
|
||||||
|
else console.log(Object.keys(data[0]));
|
||||||
|
}
|
||||||
|
run();
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
require('dotenv').config();
|
||||||
|
const { createClient } = require('@supabase/supabase-js');
|
||||||
|
const supabase = createClient(process.env.REACT_APP_SUPABASE_URL, process.env.REACT_APP_SUPABASE_ANON_KEY);
|
||||||
|
async function run() {
|
||||||
|
const { data, error } = await supabase.from('annonces_diffusions').select(`
|
||||||
|
*,
|
||||||
|
annonce:annonces_enregistrees(variables_values)
|
||||||
|
`).order('created_at', { ascending: false }).limit(1);
|
||||||
|
if (error) console.error(error);
|
||||||
|
else console.log(JSON.stringify(data[0], null, 2));
|
||||||
|
}
|
||||||
|
run();
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* Récupère TOUTES les lignes d'une table Supabase en paginant automatiquement.
|
||||||
|
*
|
||||||
|
* PostgREST (Supabase) limite par défaut à 1000 lignes par requête.
|
||||||
|
* Cette fonction envoie plusieurs requêtes avec `.range()` pour obtenir
|
||||||
|
* l'intégralité des résultats, puis les concatène.
|
||||||
|
*
|
||||||
|
* Usage :
|
||||||
|
* fetchAllRows(supabase.from('horaires').select('*'))
|
||||||
|
*
|
||||||
|
* En interne, `.range()` modifie le header Range de la requête et chaque
|
||||||
|
* `await` sur un PostgrestBuilder déclenche un nouveau fetch HTTP, ce qui
|
||||||
|
* permet de paginer sur le même builder.
|
||||||
|
*
|
||||||
|
* @param {object} query - Query Supabase (ex: supabase.from('horaires').select('*'))
|
||||||
|
* @param {number} [pageSize=500] - Nombre de lignes par page (≤ 1000)
|
||||||
|
* @returns {Promise<{data: Array, error: object|null}>}
|
||||||
|
*/
|
||||||
|
export async function fetchAllRows(query, pageSize = 500) {
|
||||||
|
let allData = [];
|
||||||
|
let from = 0;
|
||||||
|
let hasMore = true;
|
||||||
|
|
||||||
|
while (hasMore) {
|
||||||
|
const to = from + pageSize - 1;
|
||||||
|
const { data, error } = await query.range(from, to);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return { data: null, error };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data || data.length === 0) {
|
||||||
|
hasMore = false;
|
||||||
|
} else {
|
||||||
|
allData = allData.concat(data);
|
||||||
|
if (data.length < pageSize) {
|
||||||
|
hasMore = false;
|
||||||
|
} else {
|
||||||
|
from += pageSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { data: allData, error: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default fetchAllRows;
|
||||||
+13
-1
@@ -19,7 +19,19 @@ if (!supabaseUrl || !supabaseAnonKey) {
|
|||||||
'Vérifiez REACT_APP_SUPABASE_URL et REACT_APP_SUPABASE_ANON_KEY dans .env et redémarrez le serveur.'
|
'Vérifiez REACT_APP_SUPABASE_URL et REACT_APP_SUPABASE_ANON_KEY dans .env et redémarrez le serveur.'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
supabase = createClient(supabaseUrl, supabaseAnonKey);
|
supabase = createClient(supabaseUrl, supabaseAnonKey, {
|
||||||
|
realtime: {
|
||||||
|
// Désactivé : le reverse proxy ne supporte pas le WebSocket vers le port 3001.
|
||||||
|
// L'appli utilise un fallback par polling (useAnnonceSonoreRealtime).
|
||||||
|
params: { eventsPerSecond: 0 },
|
||||||
|
},
|
||||||
|
// Empêcher la connexion WebSocket automatique
|
||||||
|
global: {
|
||||||
|
headers: {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// Désactiver complètement le canal Realtime pour éviter les erreurs wss:// dans la console
|
||||||
|
try { supabase.realtime.disconnect(); } catch (e) { /* ignore */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
export { supabase };
|
export { supabase };
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default function SelectAfficheur({ onBack, navigate }) {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const { data, error } = await supabase.from('horaires').select('stops, quai_reel, voie, quai, gare_depart_nom, gare_arrivee_nom');
|
const { data, error } = await supabase.from('horaires').select('quai_reel, voie, quai, gare_depart_nom, gare_arrivee_nom, gares_desservies');
|
||||||
if (error) throw error;
|
if (error) throw error;
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
||||||
@@ -36,10 +36,10 @@ export default function SelectAfficheur({ onBack, navigate }) {
|
|||||||
|
|
||||||
(data || []).forEach(h => {
|
(data || []).forEach(h => {
|
||||||
let stopsList = [];
|
let stopsList = [];
|
||||||
if (Array.isArray(h.stops)) {
|
if (Array.isArray(h.gares_desservies)) {
|
||||||
stopsList = h.stops;
|
stopsList = h.gares_desservies;
|
||||||
} else if (typeof h.stops === 'string') {
|
} else if (typeof h.gares_desservies === 'string') {
|
||||||
try { stopsList = JSON.parse(h.stops); } catch (e) {}
|
try { stopsList = JSON.parse(h.gares_desservies); } catch (e) {}
|
||||||
}
|
}
|
||||||
if (!Array.isArray(stopsList)) stopsList = [];
|
if (!Array.isArray(stopsList)) stopsList = [];
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useState, useCallback } from 'react';
|
import React, { useEffect, useState, useCallback } from 'react';
|
||||||
import './AFLArrivees.css';
|
import './AFLArrivees.css';
|
||||||
import supabase from '../../../lib/supabase';
|
import supabase from '../../../lib/supabase';
|
||||||
|
import { fetchAllRows } from '../../../lib/fetchAllRows';
|
||||||
import MarqueeText from '../../../components/MarqueeText';
|
import MarqueeText from '../../../components/MarqueeText';
|
||||||
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
||||||
import useAutoAnnonce from '../../../hooks/useAutoAnnonce';
|
import useAutoAnnonce from '../../../hooks/useAutoAnnonce';
|
||||||
@@ -586,7 +587,7 @@ export default function AFLArrivees(){
|
|||||||
setError(null);
|
setError(null);
|
||||||
try {
|
try {
|
||||||
const [{ data: horairesData, error: hError }, { data: perturbData, error: pError }, { data: travauxData, error: tError }, { data: travauxSubstData }] = await Promise.all([
|
const [{ data: horairesData, error: hError }, { data: perturbData, error: pError }, { data: travauxData, error: tError }, { data: travauxSubstData }] = await Promise.all([
|
||||||
supabase.from('horaires').select('id, *'),
|
fetchAllRows(supabase.from('horaires').select('*')),
|
||||||
supabase.from('perturbations').select('*'),
|
supabase.from('perturbations').select('*'),
|
||||||
supabase.from('travaux').select('*'),
|
supabase.from('travaux').select('*'),
|
||||||
supabase.from('travaux_substitutions').select('*')
|
supabase.from('travaux_substitutions').select('*')
|
||||||
@@ -609,14 +610,14 @@ export default function AFLArrivees(){
|
|||||||
// conserver la liste complète telle que renvoyée par la BDD (avant filtrage par gare)
|
// conserver la liste complète telle que renvoyée par la BDD (avant filtrage par gare)
|
||||||
let parsedHoraires = (horairesData || []).map(h => h || {});
|
let parsedHoraires = (horairesData || []).map(h => h || {});
|
||||||
|
|
||||||
// Certains champs (comme stops) peuvent arriver en tant que chaîne JSON depuis la BDD;
|
// Certains champs (comme gares_desservies) peuvent arriver en tant que chaîne JSON depuis la BDD;
|
||||||
// essayer de parser pour garantir que stops est un tableau utilisable.
|
// essayer de parser pour garantir que gares_desservies est un tableau utilisable.
|
||||||
parsedHoraires = parsedHoraires.map(h => {
|
parsedHoraires = parsedHoraires.map(h => {
|
||||||
try {
|
try {
|
||||||
if (h && typeof h.stops === 'string') {
|
if (h && typeof h.gares_desservies === 'string') {
|
||||||
const parsed = JSON.parse(h.stops);
|
const parsed = JSON.parse(h.gares_desservies);
|
||||||
if (Array.isArray(parsed)) {
|
if (Array.isArray(parsed)) {
|
||||||
return { ...h, stops: parsed };
|
return { ...h, gares_desservies: parsed };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import supabase from '../../../lib/supabase';
|
import supabase from '../../../lib/supabase';
|
||||||
|
import { fetchAllRows } from '../../../lib/fetchAllRows';
|
||||||
import './AFLArriveesQuais.css';
|
import './AFLArriveesQuais.css';
|
||||||
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
||||||
|
|
||||||
@@ -419,7 +420,7 @@ const AFLArriveesQuais = () => {
|
|||||||
const fetchData = useCallback(async () => {
|
const fetchData = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const [{ data: horairesData }, { data: subData }, { data: perturbData }, { data: travauxData }] = await Promise.all([
|
const [{ data: horairesData }, { data: subData }, { data: perturbData }, { data: travauxData }] = await Promise.all([
|
||||||
supabase.from('horaires').select('*'),
|
fetchAllRows(supabase.from('horaires').select('*')),
|
||||||
supabase.from('travaux_substitutions').select('*'),
|
supabase.from('travaux_substitutions').select('*'),
|
||||||
supabase.from('perturbations').select('*'),
|
supabase.from('perturbations').select('*'),
|
||||||
supabase.from('travaux').select('*')
|
supabase.from('travaux').select('*')
|
||||||
@@ -427,9 +428,9 @@ const AFLArriveesQuais = () => {
|
|||||||
|
|
||||||
let parsedHoraires = (horairesData || []).map(h => {
|
let parsedHoraires = (horairesData || []).map(h => {
|
||||||
try {
|
try {
|
||||||
if (h && typeof h.stops === 'string') {
|
if (h && typeof h.gares_desservies === 'string') {
|
||||||
const parsed = JSON.parse(h.stops);
|
const parsed = JSON.parse(h.gares_desservies);
|
||||||
if (Array.isArray(parsed)) return { ...h, stops: parsed };
|
if (Array.isArray(parsed)) return { ...h, gares_desservies: parsed };
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
return h || {};
|
return h || {};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useState, useCallback } from 'react';
|
import React, { useEffect, useState, useCallback } from 'react';
|
||||||
import './AFLDeparts.css';
|
import './AFLDeparts.css';
|
||||||
import supabase from '../../../lib/supabase';
|
import supabase from '../../../lib/supabase';
|
||||||
|
import { fetchAllRows } from '../../../lib/fetchAllRows';
|
||||||
import MarqueeText from '../../../components/MarqueeText';
|
import MarqueeText from '../../../components/MarqueeText';
|
||||||
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
||||||
import useAutoAnnonce from '../../../hooks/useAutoAnnonce';
|
import useAutoAnnonce from '../../../hooks/useAutoAnnonce';
|
||||||
@@ -586,7 +587,7 @@ export default function AFLDeparts(){
|
|||||||
setError(null);
|
setError(null);
|
||||||
try {
|
try {
|
||||||
const [{ data: horairesData, error: hError }, { data: perturbData, error: pError }, { data: travauxData, error: tError }, { data: travauxSubstData }] = await Promise.all([
|
const [{ data: horairesData, error: hError }, { data: perturbData, error: pError }, { data: travauxData, error: tError }, { data: travauxSubstData }] = await Promise.all([
|
||||||
supabase.from('horaires').select('id, *'),
|
fetchAllRows(supabase.from('horaires').select('*')),
|
||||||
supabase.from('perturbations').select('*'),
|
supabase.from('perturbations').select('*'),
|
||||||
supabase.from('travaux').select('*'),
|
supabase.from('travaux').select('*'),
|
||||||
supabase.from('travaux_substitutions').select('*')
|
supabase.from('travaux_substitutions').select('*')
|
||||||
@@ -609,14 +610,14 @@ export default function AFLDeparts(){
|
|||||||
// conserver la liste complète telle que renvoyée par la BDD (avant filtrage par gare)
|
// conserver la liste complète telle que renvoyée par la BDD (avant filtrage par gare)
|
||||||
let parsedHoraires = (horairesData || []).map(h => h || {});
|
let parsedHoraires = (horairesData || []).map(h => h || {});
|
||||||
|
|
||||||
// Certains champs (comme stops) peuvent arriver en tant que chaîne JSON depuis la BDD;
|
// Certains champs (comme gares_desservies) peuvent arriver en tant que chaîne JSON depuis la BDD;
|
||||||
// essayer de parser pour garantir que stops est un tableau utilisable.
|
// essayer de parser pour garantir que gares_desservies est un tableau utilisable.
|
||||||
parsedHoraires = parsedHoraires.map(h => {
|
parsedHoraires = parsedHoraires.map(h => {
|
||||||
try {
|
try {
|
||||||
if (h && typeof h.stops === 'string') {
|
if (h && typeof h.gares_desservies === 'string') {
|
||||||
const parsed = JSON.parse(h.stops);
|
const parsed = JSON.parse(h.gares_desservies);
|
||||||
if (Array.isArray(parsed)) {
|
if (Array.isArray(parsed)) {
|
||||||
return { ...h, stops: parsed };
|
return { ...h, gares_desservies: parsed };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
import supabase from '../../../lib/supabase';
|
import supabase from '../../../lib/supabase';
|
||||||
|
import { fetchAllRows } from '../../../lib/fetchAllRows';
|
||||||
import './AFLDepartsQuais.css';
|
import './AFLDepartsQuais.css';
|
||||||
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
||||||
|
|
||||||
@@ -420,7 +421,7 @@ const AFLDepartsQuais = () => {
|
|||||||
const fetchData = useCallback(async () => {
|
const fetchData = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const [{ data: horairesData }, { data: subData }, { data: perturbData }, { data: travauxData }] = await Promise.all([
|
const [{ data: horairesData }, { data: subData }, { data: perturbData }, { data: travauxData }] = await Promise.all([
|
||||||
supabase.from('horaires').select('*'),
|
fetchAllRows(supabase.from('horaires').select('*')),
|
||||||
supabase.from('travaux_substitutions').select('*'),
|
supabase.from('travaux_substitutions').select('*'),
|
||||||
supabase.from('perturbations').select('*'),
|
supabase.from('perturbations').select('*'),
|
||||||
supabase.from('travaux').select('*')
|
supabase.from('travaux').select('*')
|
||||||
@@ -428,9 +429,9 @@ const AFLDepartsQuais = () => {
|
|||||||
|
|
||||||
let parsedHoraires = (horairesData || []).map(h => {
|
let parsedHoraires = (horairesData || []).map(h => {
|
||||||
try {
|
try {
|
||||||
if (h && typeof h.stops === 'string') {
|
if (h && typeof h.gares_desservies === 'string') {
|
||||||
const parsed = JSON.parse(h.stops);
|
const parsed = JSON.parse(h.gares_desservies);
|
||||||
if (Array.isArray(parsed)) return { ...h, stops: parsed };
|
if (Array.isArray(parsed)) return { ...h, gares_desservies: parsed };
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
return h || {};
|
return h || {};
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Logo from '../../../components/Logo';
|
|||||||
import MarqueeText from '../../../components/MarqueeText';
|
import MarqueeText from '../../../components/MarqueeText';
|
||||||
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
||||||
import useAutoAnnonce from '../../../hooks/useAutoAnnonce';
|
import useAutoAnnonce from '../../../hooks/useAutoAnnonce';
|
||||||
|
import { fetchAllRows } from '../../../lib/fetchAllRows';
|
||||||
|
|
||||||
// Helper utilitaire : format HHhMM sans secondes (ex: 06h44)
|
// Helper utilitaire : format HHhMM sans secondes (ex: 06h44)
|
||||||
const formatTimeNoSeconds = (v) => {
|
const formatTimeNoSeconds = (v) => {
|
||||||
@@ -625,9 +626,7 @@ export default function ClassiquesArrivees(){
|
|||||||
setError(null);
|
setError(null);
|
||||||
try {
|
try {
|
||||||
const [{ data: horairesData, error: hError }, { data: perturbData, error: pError }, { data: travauxData, error: tError }] = await Promise.all([
|
const [{ data: horairesData, error: hError }, { data: perturbData, error: pError }, { data: travauxData, error: tError }] = await Promise.all([
|
||||||
// DEBUG: récupérer explicitement l'id et toutes les colonnes pour s'assurer que l'identifiant
|
fetchAllRows(supabase.from('horaires').select('*')),
|
||||||
// `id` est bien présent et peut être mis en correspondance avec `horaire_id` dans perturbations
|
|
||||||
supabase.from('horaires').select('id, *'),
|
|
||||||
supabase.from('perturbations').select('*'),
|
supabase.from('perturbations').select('*'),
|
||||||
supabase.from('travaux').select('*')
|
supabase.from('travaux').select('*')
|
||||||
]);
|
]);
|
||||||
@@ -649,14 +648,13 @@ export default function ClassiquesArrivees(){
|
|||||||
// conserver la liste complète telle que renvoyée par la BDD (avant filtrage par gare)
|
// conserver la liste complète telle que renvoyée par la BDD (avant filtrage par gare)
|
||||||
let parsedHoraires = (horairesData || []).map(h => h || {});
|
let parsedHoraires = (horairesData || []).map(h => h || {});
|
||||||
|
|
||||||
// Certains champs (comme stops) peuvent arriver en tant que chaîne JSON depuis la BDD;
|
// Parser gares_desservies si c'est une chaîne JSON
|
||||||
// essayer de parser pour garantir que stops est un tableau utilisable.
|
|
||||||
parsedHoraires = parsedHoraires.map(h => {
|
parsedHoraires = parsedHoraires.map(h => {
|
||||||
try {
|
try {
|
||||||
if (h && typeof h.stops === 'string') {
|
if (h && typeof h.gares_desservies === 'string') {
|
||||||
const parsed = JSON.parse(h.stops);
|
const parsed = JSON.parse(h.gares_desservies);
|
||||||
if (Array.isArray(parsed)) {
|
if (Array.isArray(parsed)) {
|
||||||
return { ...h, stops: parsed };
|
return { ...h, gares_desservies: parsed };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Logo from '../../../components/Logo';
|
|||||||
import MarqueeText from '../../../components/MarqueeText';
|
import MarqueeText from '../../../components/MarqueeText';
|
||||||
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
||||||
import useAutoAnnonce from '../../../hooks/useAutoAnnonce';
|
import useAutoAnnonce from '../../../hooks/useAutoAnnonce';
|
||||||
|
import { fetchAllRows } from '../../../lib/fetchAllRows';
|
||||||
|
|
||||||
// Helper utilitaire : format HHhMM sans secondes (ex: 06h44)
|
// Helper utilitaire : format HHhMM sans secondes (ex: 06h44)
|
||||||
const formatTimeNoSeconds = (v) => {
|
const formatTimeNoSeconds = (v) => {
|
||||||
@@ -625,9 +626,7 @@ export default function ClassiquesDeparts(){
|
|||||||
setError(null);
|
setError(null);
|
||||||
try {
|
try {
|
||||||
const [{ data: horairesData, error: hError }, { data: perturbData, error: pError }, { data: travauxData, error: tError }] = await Promise.all([
|
const [{ data: horairesData, error: hError }, { data: perturbData, error: pError }, { data: travauxData, error: tError }] = await Promise.all([
|
||||||
// DEBUG: récupérer explicitement l'id et toutes les colonnes pour s'assurer que l'identifiant
|
fetchAllRows(supabase.from('horaires').select('*')),
|
||||||
// `id` est bien présent et peut être mis en correspondance avec `horaire_id` dans perturbations
|
|
||||||
supabase.from('horaires').select('id, *'),
|
|
||||||
supabase.from('perturbations').select('*'),
|
supabase.from('perturbations').select('*'),
|
||||||
supabase.from('travaux').select('*')
|
supabase.from('travaux').select('*')
|
||||||
]);
|
]);
|
||||||
@@ -649,14 +648,13 @@ export default function ClassiquesDeparts(){
|
|||||||
// conserver la liste complète telle que renvoyée par la BDD (avant filtrage par gare)
|
// conserver la liste complète telle que renvoyée par la BDD (avant filtrage par gare)
|
||||||
let parsedHoraires = (horairesData || []).map(h => h || {});
|
let parsedHoraires = (horairesData || []).map(h => h || {});
|
||||||
|
|
||||||
// Certains champs (comme stops) peuvent arriver en tant que chaîne JSON depuis la BDD;
|
// Parser gares_desservies si c'est une chaîne JSON
|
||||||
// essayer de parser pour garantir que stops est un tableau utilisable.
|
|
||||||
parsedHoraires = parsedHoraires.map(h => {
|
parsedHoraires = parsedHoraires.map(h => {
|
||||||
try {
|
try {
|
||||||
if (h && typeof h.stops === 'string') {
|
if (h && typeof h.gares_desservies === 'string') {
|
||||||
const parsed = JSON.parse(h.stops);
|
const parsed = JSON.parse(h.gares_desservies);
|
||||||
if (Array.isArray(parsed)) {
|
if (Array.isArray(parsed)) {
|
||||||
return { ...h, stops: parsed };
|
return { ...h, gares_desservies: parsed };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useState, useCallback } from 'react';
|
import React, { useEffect, useState, useCallback } from 'react';
|
||||||
import './ClassiquesArriveesQuais.css';
|
import './ClassiquesArriveesQuais.css';
|
||||||
import supabase from '../../../../lib/supabase';
|
import supabase from '../../../../lib/supabase';
|
||||||
|
import { fetchAllRows } from '../../../../lib/fetchAllRows';
|
||||||
import useAnnonceSonoreRealtime from '../../../../hooks/useAnnonceSonoreRealtime';
|
import useAnnonceSonoreRealtime from '../../../../hooks/useAnnonceSonoreRealtime';
|
||||||
import useAutoAnnonce from '../../../../hooks/useAutoAnnonce';
|
import useAutoAnnonce from '../../../../hooks/useAutoAnnonce';
|
||||||
function Clock() {
|
function Clock() {
|
||||||
@@ -490,7 +491,7 @@ export default function ClassiquesArriveesQuais() {
|
|||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
const { data: all, error } = await supabase.from('horaires').select('id, *');
|
const { data: all, error } = await fetchAllRows(supabase.from('horaires').select('*'));
|
||||||
if (error) {
|
if (error) {
|
||||||
if (mounted) setHoraireError(error.message || String(error));
|
if (mounted) setHoraireError(error.message || String(error));
|
||||||
setLoadingHoraire(false);
|
setLoadingHoraire(false);
|
||||||
@@ -784,8 +785,8 @@ export default function ClassiquesArriveesQuais() {
|
|||||||
const horaire = selectedHoraire && selectedHoraire.horaire ? selectedHoraire.horaire : null;
|
const horaire = selectedHoraire && selectedHoraire.horaire ? selectedHoraire.horaire : null;
|
||||||
let stops = horaire ? getStops(horaire) : [];
|
let stops = horaire ? getStops(horaire) : [];
|
||||||
if (!Array.isArray(stops) || stops.length === 0) {
|
if (!Array.isArray(stops) || stops.length === 0) {
|
||||||
if (horaire && typeof horaire.stops === 'string') {
|
if (horaire && typeof horaire.gares_desservies === 'string') {
|
||||||
try { const p = JSON.parse(horaire.stops); if (Array.isArray(p)) stops = p; } catch (e) { /* ignore */ }
|
try { const p = JSON.parse(horaire.gares_desservies); if (Array.isArray(p)) stops = p; } catch (e) { /* ignore */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Array.isArray(stops) || stops.length === 0) stops = mock.stops || [];
|
if (!Array.isArray(stops) || stops.length === 0) stops = mock.stops || [];
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useState, useCallback } from 'react';
|
import React, { useEffect, useState, useCallback } from 'react';
|
||||||
import './ClassiquesDepartsQuais.css';
|
import './ClassiquesDepartsQuais.css';
|
||||||
import supabase from '../../../../lib/supabase';
|
import supabase from '../../../../lib/supabase';
|
||||||
|
import { fetchAllRows } from '../../../../lib/fetchAllRows';
|
||||||
import useAnnonceSonoreRealtime from '../../../../hooks/useAnnonceSonoreRealtime';
|
import useAnnonceSonoreRealtime from '../../../../hooks/useAnnonceSonoreRealtime';
|
||||||
import useAutoAnnonce from '../../../../hooks/useAutoAnnonce';
|
import useAutoAnnonce from '../../../../hooks/useAutoAnnonce';
|
||||||
function Clock() {
|
function Clock() {
|
||||||
@@ -490,7 +491,7 @@ export default function ClassiquesDepartsQuais() {
|
|||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
const { data: all, error } = await supabase.from('horaires').select('id, *');
|
const { data: all, error } = await fetchAllRows(supabase.from('horaires').select('*'));
|
||||||
if (error) {
|
if (error) {
|
||||||
if (mounted) setHoraireError(error.message || String(error));
|
if (mounted) setHoraireError(error.message || String(error));
|
||||||
setLoadingHoraire(false);
|
setLoadingHoraire(false);
|
||||||
@@ -781,8 +782,8 @@ export default function ClassiquesDepartsQuais() {
|
|||||||
const horaire = selectedHoraire && selectedHoraire.horaire ? selectedHoraire.horaire : null;
|
const horaire = selectedHoraire && selectedHoraire.horaire ? selectedHoraire.horaire : null;
|
||||||
let stops = horaire ? getStops(horaire) : [];
|
let stops = horaire ? getStops(horaire) : [];
|
||||||
if (!Array.isArray(stops) || stops.length === 0) {
|
if (!Array.isArray(stops) || stops.length === 0) {
|
||||||
if (horaire && typeof horaire.stops === 'string') {
|
if (horaire && typeof horaire.gares_desservies === 'string') {
|
||||||
try { const p = JSON.parse(horaire.stops); if (Array.isArray(p)) stops = p; } catch (e) { /* ignore */ }
|
try { const p = JSON.parse(horaire.gares_desservies); if (Array.isArray(p)) stops = p; } catch (e) { /* ignore */ }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Array.isArray(stops) || stops.length === 0) stops = mock.stops || [];
|
if (!Array.isArray(stops) || stops.length === 0) stops = mock.stops || [];
|
||||||
|
|||||||
Reference in new issue
Block a user