RELEASE V5.5.0 : Voici les modifications apportées :
-> REFONTE TOTALE DE TOUS LES AFFICHEURS CLASSIQUES + QUAIS FONCTIONNALITÉS EN COURS DE DÉVELOPPEMENT : -> ADAPTABILITÉ EN FONCTION DES SITUATIONS
This commit is contained in:
1 parent
b90c699302
commit
9c6ac798f1
26 files changed
+2900
-2050
No files matched your search
+24
-24
@@ -3,133 +3,133 @@
|
||||
"logos": [
|
||||
{
|
||||
"file": "logo-aleop.svg",
|
||||
"path": "/img/type/logo-aleop.svg",
|
||||
"path": "/logo-aleop.svg",
|
||||
"slug": "aleop",
|
||||
"name": "Aleop"
|
||||
},
|
||||
{
|
||||
"file": "logo-auvergerhonealpes.svg",
|
||||
"path": "/img/type/logo-auvergerhonealpes.svg",
|
||||
"path": "/logo-auvergerhonealpes.svg",
|
||||
"slug": "auvergerhonealpes",
|
||||
"name": "Auvergerhonealpes"
|
||||
},
|
||||
{
|
||||
"file": "logo-breizhgo.svg",
|
||||
"path": "/img/type/logo-breizhgo.svg",
|
||||
"path": "/logo-breizhgo.svg",,
|
||||
"slug": "breizhgo",
|
||||
"name": "Breizhgo"
|
||||
},
|
||||
{
|
||||
"file": "logo-cfl.svg",
|
||||
"path": "/img/type/logo-cfl.svg",
|
||||
"path": "/logo-cfl.svg",
|
||||
"slug": "cfl",
|
||||
"name": "CFL"
|
||||
},
|
||||
{
|
||||
"file": "logo-db.svg",
|
||||
"path": "/img/type/logo-db.svg",
|
||||
"path": "/logo-db.svg",
|
||||
"slug": "db",
|
||||
"name": "DB"
|
||||
},
|
||||
{
|
||||
"file": "logo-eurostar.svg",
|
||||
"path": "/img/type/logo-eurostar.svg",
|
||||
"path": "/logo-eurostar.svg",
|
||||
"slug": "eurostar",
|
||||
"name": "Eurostar"
|
||||
},
|
||||
{
|
||||
"file": "logo-fluo.svg",
|
||||
"path": "/img/type/logo-fluo.svg",
|
||||
"path": "/logo-fluo.svg",
|
||||
"slug": "fluo",
|
||||
"name": "Fluo"
|
||||
},
|
||||
{
|
||||
"file": "logo-frecciarossa.svg",
|
||||
"path": "/img/type/logo-frecciarossa.svg",
|
||||
"path": "/logo-frecciarossa.svg",
|
||||
"slug": "frecciarossa",
|
||||
"name": "Frecciarossa"
|
||||
},
|
||||
{
|
||||
"file": "logo-hautsdefrance.svg",
|
||||
"path": "/img/type/logo-hautsdefrance.svg",
|
||||
"path": "/logo-hautsdefrance.svg",
|
||||
"slug": "hautsdefrance",
|
||||
"name": "Hautsdefrance"
|
||||
},
|
||||
{
|
||||
"file": "logo-ice.svg",
|
||||
"path": "/img/type/logo-ice.svg",
|
||||
"path": "/logo-ice.svg",
|
||||
"slug": "ice",
|
||||
"name": "ICE"
|
||||
},
|
||||
{
|
||||
"file": "logo-intercites.svg",
|
||||
"path": "/img/type/logo-intercites.svg",
|
||||
"path": "/logo-intercites.svg",
|
||||
"slug": "intercites",
|
||||
"name": "Intercités"
|
||||
},
|
||||
{
|
||||
"file": "logo-ler.svg",
|
||||
"path": "/img/type/logo-ler.svg",
|
||||
"path": "/logo-ler.svg",
|
||||
"slug": "ler",
|
||||
"name": "Ler"
|
||||
},
|
||||
{
|
||||
"file": "logo-lio.svg",
|
||||
"path": "/img/type/logo-lio.svg",
|
||||
"path": "/logo-lio.svg",
|
||||
"slug": "lio",
|
||||
"name": "Lio"
|
||||
},
|
||||
{
|
||||
"file": "logo-lunea.svg",
|
||||
"path": "/img/type/logo-lunea.svg",
|
||||
"path": "/logo-lunea.svg",
|
||||
"slug": "lunea",
|
||||
"name": "Lunea"
|
||||
},
|
||||
{
|
||||
"file": "logo-metrolor.svg",
|
||||
"path": "/img/type/logo-metrolor.svg",
|
||||
"path": "/logo-metrolor.svg",
|
||||
"slug": "metrolor",
|
||||
"name": "Metrolor"
|
||||
},
|
||||
{
|
||||
"file": "logo-mobigo.svg",
|
||||
"path": "/img/type/logo-mobigo.svg",
|
||||
"path": "/logo-mobigo.svg",
|
||||
"slug": "mobigo",
|
||||
"name": "Mobigo"
|
||||
},
|
||||
{
|
||||
"file": "logo-nomad.svg",
|
||||
"path": "/img/type/logo-nomad.svg",
|
||||
"path": "/logo-nomad.svg",
|
||||
"slug": "nomad",
|
||||
"name": "Nomad"
|
||||
},
|
||||
{
|
||||
"file": "logo-occitanie.svg",
|
||||
"path": "/img/type/logo-occitanie.svg",
|
||||
"path": "/logo-occitanie.svg",
|
||||
"slug": "occitanie",
|
||||
"name": "Occitanie"
|
||||
},
|
||||
{
|
||||
"file": "logo-ouigo.svg",
|
||||
"path": "/img/type/logo-ouigo.svg",
|
||||
"path": "/logo-ouigo.svg",
|
||||
"slug": "ouigo",
|
||||
"name": "TGV Ouigo"
|
||||
},
|
||||
{
|
||||
"file": "logo-ouigo-classique.svg",
|
||||
"path": "/img/type/logo-ouigo-classique.svg",
|
||||
"path": "/logo-ouigo-classique.svg",
|
||||
"slug": "ouigo-classique",
|
||||
"name": "OUIGO Trains Classiques"
|
||||
},
|
||||
{
|
||||
"file": "logo-remi.svg",
|
||||
"path": "/img/type/logo-remi.svg",
|
||||
"path": "/logo-remi.svg",
|
||||
"slug": "remi",
|
||||
"name": "Remi"
|
||||
},
|
||||
{
|
||||
"file": "logo-renfeave.svg",
|
||||
"path": "/img/type/logo-renfeave.svg",
|
||||
"path": "/logo-renfeave.svg",
|
||||
"slug": "renfeave",
|
||||
"name": "Renfe AVE"
|
||||
},
|
||||
@@ -255,8 +255,8 @@
|
||||
},
|
||||
{
|
||||
"file": "sncf-voyageurs-logo.png",
|
||||
"path": "/img/type/sncf-voyageurs-logo.png",
|
||||
"slug": "ter",
|
||||
"path": "/sncf-voyageurs-logo.png",
|
||||
"slug": "TER",
|
||||
"name": "TER"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -3,379 +3,379 @@
|
||||
"logos": [
|
||||
{
|
||||
"file": "logo-aleop-color.svg",
|
||||
"path": "/img/type/logo-aleop-color.svg",
|
||||
"path": "/type/quais/logo-aleop-color.svg",
|
||||
"slug": "aleop",
|
||||
"name": "Aleop"
|
||||
},
|
||||
{
|
||||
"file": "logo-auvergerhonealpes-color.svg",
|
||||
"path": "/img/type/logo-auvergerhonealpes-color.svg",
|
||||
"path": "/type/quais/logo-auvergerhonealpes-color.svg",
|
||||
"slug": "auvergerhonealpes",
|
||||
"name": "Auvergerhonealpes"
|
||||
},
|
||||
{
|
||||
"file": "logo-breizhgo-color.svg",
|
||||
"path": "/img/type/logo-breizhgo-color.svg",
|
||||
"path": "/type/quais/logo-breizhgo-color.svg",
|
||||
"slug": "breizhgo",
|
||||
"name": "Breizhgo"
|
||||
},
|
||||
{
|
||||
"file": "logo-cfl-color.svg",
|
||||
"path": "/img/type/logo-cfl-color.svg",
|
||||
"path": "/type/quais/logo-cfl-color.svg",
|
||||
"slug": "cfl",
|
||||
"name": "CFL"
|
||||
},
|
||||
{
|
||||
"file": "logo-db-color.svg",
|
||||
"path": "/img/type/logo-db-color.svg",
|
||||
"path": "/type/quais/logo-db-color.svg",
|
||||
"slug": "db",
|
||||
"name": "DB"
|
||||
},
|
||||
{
|
||||
"file": "logo-eurostar-color.svg",
|
||||
"path": "/img/type/logo-eurostar-color.svg",
|
||||
"path": "/type/quais/logo-eurostar-color.svg",
|
||||
"slug": "eurostar",
|
||||
"name": "Eurostar"
|
||||
},
|
||||
{
|
||||
"file": "logo-fluo-color.svg",
|
||||
"path": "/img/type/logo-fluo-color.svg",
|
||||
"path": "/type/quais/logo-fluo-color.svg",
|
||||
"slug": "fluo",
|
||||
"name": "Fluo"
|
||||
},
|
||||
{
|
||||
"file": "logo-frecciarossa-color.svg",
|
||||
"path": "/img/type/logo-frecciarossa-color.svg",
|
||||
"path": "/type/quais/logo-frecciarossa-color.svg",
|
||||
"slug": "frecciarossa",
|
||||
"name": "Frecciarossa"
|
||||
},
|
||||
{
|
||||
"file": "logo-hautsdefrance-color.svg",
|
||||
"path": "/img/type/logo-hautsdefrance-color.svg",
|
||||
"path": "/type/quais/logo-hautsdefrance-color.svg",
|
||||
"slug": "hautsdefrance",
|
||||
"name": "Hautsdefrance"
|
||||
},
|
||||
{
|
||||
"file": "logo-ice-color.svg",
|
||||
"path": "/img/type/logo-ice-color.svg",
|
||||
"path": "/type/quais/logo-ice-color.svg",
|
||||
"slug": "ice",
|
||||
"name": "ICE"
|
||||
},
|
||||
{
|
||||
"file": "logo-intercites-color.svg",
|
||||
"path": "/img/type/logo-intercites-color.svg",
|
||||
"path": "/type/quais/logo-intercites-color.svg",
|
||||
"slug": "intercites",
|
||||
"name": "Intercités"
|
||||
},
|
||||
{
|
||||
"file": "logo-ler-color.svg",
|
||||
"path": "/img/type/logo-ler-color.svg",
|
||||
"path": "/type/quais/logo-ler-color.svg",
|
||||
"slug": "ler",
|
||||
"name": "Ler"
|
||||
},
|
||||
{
|
||||
"file": "logo-lio-color.svg",
|
||||
"path": "/img/type/logo-lio-color.svg",
|
||||
"path": "/type/quais/logo-lio-color.svg",
|
||||
"slug": "lio",
|
||||
"name": "Lio"
|
||||
},
|
||||
{
|
||||
"file": "logo-lunea-color.svg",
|
||||
"path": "/img/type/logo-lunea-color.svg",
|
||||
"path": "/type/quais/logo-lunea-color.svg",
|
||||
"slug": "lunea",
|
||||
"name": "Lunea"
|
||||
},
|
||||
{
|
||||
"file": "logo-metrolor-color.svg",
|
||||
"path": "/img/type/logo-metrolor-color.svg",
|
||||
"path": "/type/quais/logo-metrolor-color.svg",
|
||||
"slug": "metrolor",
|
||||
"name": "Metrolor"
|
||||
},
|
||||
{
|
||||
"file": "logo-mobigo-color.svg",
|
||||
"path": "/img/type/logo-mobigo-color.svg",
|
||||
"path": "/type/quais/logo-mobigo-color.svg",
|
||||
"slug": "mobigo",
|
||||
"name": "Mobigo"
|
||||
},
|
||||
{
|
||||
"file": "logo-nomad-color.svg",
|
||||
"path": "/img/type/logo-nomad-color.svg",
|
||||
"path": "/type/quais/logo-nomad-color.svg",
|
||||
"slug": "nomad",
|
||||
"name": "Nomad"
|
||||
},
|
||||
{
|
||||
"file": "logo-occitanie-color.svg",
|
||||
"path": "/img/type/logo-occitanie-color.svg",
|
||||
"path": "/type/quais/logo-occitanie-color.svg",
|
||||
"slug": "occitanie",
|
||||
"name": "Occitanie"
|
||||
},
|
||||
{
|
||||
"file": "logo-ouigo-color.svg",
|
||||
"path": "/img/type/logo-ouigo-color.svg",
|
||||
"path": "/type/quais/logo-ouigo-color.svg",
|
||||
"slug": "ouigo",
|
||||
"name": "OUIGO"
|
||||
},
|
||||
{
|
||||
"file": "logo-ouigo-classique-color.svg",
|
||||
"path": "/img/type/logo-ouigo-classique-color.svg",
|
||||
"path": "/type/quais/logo-ouigo-classique-color.svg",
|
||||
"slug": "ouigo-classique",
|
||||
"name": "OUIGO Trains Classiques"
|
||||
},
|
||||
{
|
||||
"file": "logo-remi-color.svg",
|
||||
"path": "/img/type/logo-remi-color.svg",
|
||||
"path": "/type/quais/logo-remi-color.svg",
|
||||
"slug": "remi",
|
||||
"name": "Remi"
|
||||
},
|
||||
{
|
||||
"file": "logo-renfeave-color.svg",
|
||||
"path": "/img/type/logo-renfeave-color.svg",
|
||||
"path": "/type/quais/logo-renfeave-color.svg",
|
||||
"slug": "renfeave",
|
||||
"name": "Renfe AVE"
|
||||
},
|
||||
{
|
||||
"file": "logo-rer-a-color.svg",
|
||||
"path": "/img/type/logo-rer-a-color.svg",
|
||||
"path": "/type/quais/logo-rer-a-color.svg",
|
||||
"slug": "rer-a",
|
||||
"name": "RER A"
|
||||
},
|
||||
{
|
||||
"file": "logo-rer-b-color.svg",
|
||||
"path": "/img/type/logo-rer-b-color.svg",
|
||||
"path": "/type/quais/logo-rer-b-color.svg",
|
||||
"slug": "rer-b",
|
||||
"name": "RER B"
|
||||
},
|
||||
{
|
||||
"file": "logo-rer-c-color.svg",
|
||||
"path": "/img/type/logo-rer-c-color.svg",
|
||||
"path": "/type/quais/logo-rer-c-color.svg",
|
||||
"slug": "rer-c",
|
||||
"name": "RER C"
|
||||
},
|
||||
{
|
||||
"file": "logo-rer-d-color.svg",
|
||||
"path": "/img/type/logo-rer-d-color.svg",
|
||||
"path": "/type/quais/logo-rer-d-color.svg",
|
||||
"slug": "rer-d",
|
||||
"name": "RER D"
|
||||
},
|
||||
{
|
||||
"file": "logo-rer-e-color.svg",
|
||||
"path": "/img/type/logo-rer-e-color.svg",
|
||||
"path": "/type/quais/logo-rer-e-color.svg",
|
||||
"slug": "rer-e",
|
||||
"name": "RER E"
|
||||
},
|
||||
{
|
||||
"file": "logo-sbb-color.svg",
|
||||
"path": "/img/type/logo-sbb-color.svg",
|
||||
"path": "/type/quais/logo-sbb-color.svg",
|
||||
"slug": "sbb",
|
||||
"name": "SBB"
|
||||
},
|
||||
{
|
||||
"file": "logo-sncb-color.svg",
|
||||
"path": "/img/type/logo-sncb-color.svg",
|
||||
"path": "/type/quais/logo-sncb-color.svg",
|
||||
"slug": "sncb",
|
||||
"name": "SNCB"
|
||||
},
|
||||
{
|
||||
"file": "logo-sncf-color.svg",
|
||||
"path": "/img/type/logo-sncf-color.svg",
|
||||
"path": "/type/quais/logo-sncf-color.svg",
|
||||
"slug": "sncf",
|
||||
"name": "Sncf"
|
||||
},
|
||||
{
|
||||
"file": "sncf-voyageurs-logo-color.png",
|
||||
"path": "/img/type/sncf-voyageurs-logo-color.png",
|
||||
"path": "/type/quais/img/type/sncf-voyageurs-logo-color.png",
|
||||
"slug": "sncf-voyageurs-logo",
|
||||
"name": "SNCF"
|
||||
},
|
||||
{
|
||||
"file": "logo-sncf1985.svg",
|
||||
"path": "/img/type/logo-sncf1985.svg",
|
||||
"path": "/type/quais/img/type/logo-sncf1985.svg",
|
||||
"slug": "sncf1985",
|
||||
"name": "Sncf1985"
|
||||
},
|
||||
{
|
||||
"file": "logo-sncf1992.svg",
|
||||
"path": "/img/type/logo-sncf1992.svg",
|
||||
"path": "/type/quais/img/type/logo-sncf1992.svg",
|
||||
"slug": "sncf1992",
|
||||
"name": "Sncf1992"
|
||||
},
|
||||
{
|
||||
"file": "logo-t-h.svg",
|
||||
"path": "/img/type/logo-t-h.svg",
|
||||
"path": "/type/quais/img/type/logo-t-h.svg",
|
||||
"slug": "t-h",
|
||||
"name": "T H"
|
||||
},
|
||||
{
|
||||
"file": "logo-t-j.svg",
|
||||
"path": "/img/type/logo-t-j.svg",
|
||||
"path": "/type/quais/img/type/logo-t-j.svg",
|
||||
"slug": "t-j",
|
||||
"name": "T J"
|
||||
},
|
||||
{
|
||||
"file": "logo-t-k.svg",
|
||||
"path": "/img/type/logo-t-k.svg",
|
||||
"path": "/type/quais/img/type/logo-t-k.svg",
|
||||
"slug": "t-k",
|
||||
"name": "T K"
|
||||
},
|
||||
{
|
||||
"file": "logo-t-l.svg",
|
||||
"path": "/img/type/logo-t-l.svg",
|
||||
"path": "/type/quais/img/type/logo-t-l.svg",
|
||||
"slug": "t-l",
|
||||
"name": "T L"
|
||||
},
|
||||
{
|
||||
"file": "logo-t-n.svg",
|
||||
"path": "/img/type/logo-t-n.svg",
|
||||
"path": "/type/quais/img/type/logo-t-n.svg",
|
||||
"slug": "t-n",
|
||||
"name": "T N"
|
||||
},
|
||||
{
|
||||
"file": "logo-t-p.svg",
|
||||
"path": "/img/type/logo-t-p.svg",
|
||||
"path": "/type/quais/img/type/logo-t-p.svg",
|
||||
"slug": "t-p",
|
||||
"name": "T P"
|
||||
},
|
||||
{
|
||||
"file": "logo-t-r.svg",
|
||||
"path": "/img/type/logo-t-r.svg",
|
||||
"path": "/type/quais/img/type/logo-t-r.svg",
|
||||
"slug": "t-r",
|
||||
"name": "T R"
|
||||
},
|
||||
{
|
||||
"file": "logo-t-u.svg",
|
||||
"path": "/img/type/logo-t-u.svg",
|
||||
"path": "/type/quais/img/type/logo-t-u.svg",
|
||||
"slug": "t-u",
|
||||
"name": "T U"
|
||||
},
|
||||
{
|
||||
"file": "logo-teoz.svg",
|
||||
"path": "/img/type/logo-teoz.svg",
|
||||
"path": "/type/quais/img/type/logo-teoz.svg",
|
||||
"slug": "teoz",
|
||||
"name": "Teoz"
|
||||
},
|
||||
{
|
||||
"file": "sncf-voyageurs-logo.png",
|
||||
"path": "/img/type/sncf-voyageurs-logo.png",
|
||||
"path": "/type/quais/sncf-voyageurs-logo.png",
|
||||
"slug": "ter",
|
||||
"name": "TER"
|
||||
},
|
||||
{
|
||||
"file": "logo-ter-rhone-alpes.svg",
|
||||
"path": "/img/type/logo-ter-rhone-alpes.svg",
|
||||
"path": "/type/quais/logo-ter-rhone-alpes.svg",
|
||||
"slug": "ter-rhone-alpes",
|
||||
"name": "TER Rhone Alpes"
|
||||
},
|
||||
{
|
||||
"file": "logo-teralsace.svg",
|
||||
"path": "/img/type/logo-teralsace.svg",
|
||||
"path": "/type/quais/logo-teralsace.svg",
|
||||
"slug": "teralsace",
|
||||
"name": "Teralsace"
|
||||
},
|
||||
{
|
||||
"file": "logo-teraquitaine.svg",
|
||||
"path": "/img/type/logo-teraquitaine.svg",
|
||||
"path": "/type/quais/logo-teraquitaine.svg",
|
||||
"slug": "teraquitaine",
|
||||
"name": "Teraquitaine"
|
||||
},
|
||||
{
|
||||
"file": "logo-terbassenormandie.svg",
|
||||
"path": "/img/type/logo-terbassenormandie.svg",
|
||||
"path": "/type/quais/logo-terbassenormandie.svg",
|
||||
"slug": "terbassenormandie",
|
||||
"name": "Terbassenormandie"
|
||||
},
|
||||
{
|
||||
"file": "logo-terbourgogne.svg",
|
||||
"path": "/img/type/logo-terbourgogne.svg",
|
||||
"path": "/type/quais/logo-terbourgogne.svg",
|
||||
"slug": "terbourgogne",
|
||||
"name": "Terbourgogne"
|
||||
},
|
||||
{
|
||||
"file": "logo-terbretagne.svg",
|
||||
"path": "/img/type/logo-terbretagne.svg",
|
||||
"path": "/type/quais/logo-terbretagne.svg",
|
||||
"slug": "terbretagne",
|
||||
"name": "Terbretagne"
|
||||
},
|
||||
{
|
||||
"file": "logo-tercentre.svg",
|
||||
"path": "/img/type/logo-tercentre.svg",
|
||||
"path": "/type/quais/logo-tercentre.svg",
|
||||
"slug": "tercentre",
|
||||
"name": "Tercentre"
|
||||
},
|
||||
{
|
||||
"file": "logo-terlanguedocroussillon.svg",
|
||||
"path": "/img/type/logo-terlanguedocroussillon.svg",
|
||||
"path": "/type/quais/logo-terlanguedocroussillon.svg",
|
||||
"slug": "terlanguedocroussillon",
|
||||
"name": "Terlanguedocroussillon"
|
||||
},
|
||||
{
|
||||
"file": "logo-termidipyrenees.svg",
|
||||
"path": "/img/type/logo-termidipyrenees.svg",
|
||||
"path": "/type/quais/logo-termidipyrenees.svg",
|
||||
"slug": "termidipyrenees",
|
||||
"name": "Termidipyrenees"
|
||||
},
|
||||
{
|
||||
"file": "logo-ternordpasdecalais.svg",
|
||||
"path": "/img/type/logo-ternordpasdecalais.svg",
|
||||
"path": "/type/quais/logo-ternordpasdecalais.svg",
|
||||
"slug": "ternordpasdecalais",
|
||||
"name": "Ternordpasdecalais"
|
||||
},
|
||||
{
|
||||
"file": "logo-terpoitoucharentes.svg",
|
||||
"path": "/img/type/logo-terpoitoucharentes.svg",
|
||||
"path": "/type/quais/logo-terpoitoucharentes.svg",
|
||||
"slug": "terpoitoucharentes",
|
||||
"name": "Terpoitoucharentes"
|
||||
},
|
||||
{
|
||||
"file": "logo-tgv.svg",
|
||||
"path": "/img/type/logo-tgv.svg",
|
||||
"path": "/type/quais/logo-tgv.svg",
|
||||
"slug": "tgv",
|
||||
"name": "TGV"
|
||||
},
|
||||
{
|
||||
"file": "logo-inoui.svg",
|
||||
"path": "/img/type/logo-inoui.svg",
|
||||
"path": "/type/quais/logo-inoui.svg",
|
||||
"slug": "inoui",
|
||||
"name": "TGV InOui"
|
||||
},
|
||||
{
|
||||
"file": "logo-lyria.svg",
|
||||
"path": "/img/type/logo-lyria.svg",
|
||||
"path": "/type/quais/logo-lyria.svg",
|
||||
"slug": "lyria",
|
||||
"name": "TGV Lyria"
|
||||
},
|
||||
{
|
||||
"file": "logo-thalys.svg",
|
||||
"path": "/img/type/logo-thalys.svg",
|
||||
"path": "/type/quais/logo-thalys.svg",
|
||||
"slug": "thalys",
|
||||
"name": "Thalys"
|
||||
},
|
||||
{
|
||||
"file": "logo-thello.svg",
|
||||
"path": "/img/type/logo-thello.svg",
|
||||
"path": "/type/quais/logo-thello.svg",
|
||||
"slug": "thello",
|
||||
"name": "Thello"
|
||||
},
|
||||
{
|
||||
"file": "track-car.svg",
|
||||
"path": "/img/type/track-car.svg",
|
||||
"path": "/type/quais/track-car.svg",
|
||||
"slug": "track-car",
|
||||
"name": "Track Car"
|
||||
},
|
||||
{
|
||||
"file": "logo-tramtrain.svg",
|
||||
"path": "/img/type/logo-tramtrain.svg",
|
||||
"path": "/type/quais/logo-tramtrain.svg",
|
||||
"slug": "tramtrain",
|
||||
"name": "Tramtrain"
|
||||
},
|
||||
{
|
||||
"file": "logo-trenitalia.svg",
|
||||
"path": "/img/type/logo-trenitalia.svg",
|
||||
"path": "/type/quais/logo-trenitalia.svg",
|
||||
"slug": "trenitalia",
|
||||
"name": "Trenitalia"
|
||||
},
|
||||
{
|
||||
"file": "logo-zou.svg",
|
||||
"path": "/img/type/logo-zou.svg",
|
||||
"path": "/type/quais/logo-zou.svg",
|
||||
"slug": "zou",
|
||||
"name": "Zou"
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
+18
@@ -9,6 +9,8 @@ import ClassiquesDeparts from './pages/afficheurs/classiques/ClassiquesDeparts';
|
||||
import ClassiquesArrivees from './pages/afficheurs/classiques/ClassiquesArrivees';
|
||||
import ClassiquesDepartsQuais from './pages/afficheurs/classiques/quais/ClassiquesDepartsQuais';
|
||||
import ClassiquesArriveesQuais from './pages/afficheurs/classiques/quais/ClassiquesArriveesQuais';
|
||||
import ClassiquesFlashInfo from './pages/afficheurs/classiques/ClassiquesFlashInfo';
|
||||
import ClassiquesInformations from './pages/afficheurs/classiques/ClassiquesInformations';
|
||||
import AFLDeparts from './pages/afficheurs/afl/AFLDeparts';
|
||||
import AFLArrivees from './pages/afficheurs/afl/AFLArrivees';
|
||||
import AFLDepartsQuais from './pages/afficheurs/afl/AFLDepartsQuais';
|
||||
@@ -198,6 +200,22 @@ function App() {
|
||||
}
|
||||
|
||||
// Routes pour afficheurs : supporte le mode racine ET le mode /ferrovia
|
||||
if (
|
||||
cleanRoute.startsWith('/afficheurs/classiques/flash-info') ||
|
||||
cleanRoute.startsWith('/afficheurs/classiques/flash-circulation') ||
|
||||
cleanRoute.startsWith('/afficheurs/departs/classiques/flash-info') ||
|
||||
cleanRoute.startsWith('/afficheurs/arrivees/classiques/flash-info')
|
||||
) {
|
||||
return <AfficheurViewportWrapper><ClassiquesFlashInfo /></AfficheurViewportWrapper>;
|
||||
}
|
||||
if (
|
||||
cleanRoute.startsWith('/afficheurs/classiques/informations') ||
|
||||
cleanRoute.startsWith('/afficheurs/classiques/infos') ||
|
||||
cleanRoute.startsWith('/afficheurs/departs/classiques/informations') ||
|
||||
cleanRoute.startsWith('/afficheurs/arrivees/classiques/informations')
|
||||
) {
|
||||
return <AfficheurViewportWrapper><ClassiquesInformations /></AfficheurViewportWrapper>;
|
||||
}
|
||||
if (cleanRoute.startsWith('/afficheurs/departs/classiques/quais')) {
|
||||
return <AfficheurViewportWrapper><ClassiquesDepartsQuais /></AfficheurViewportWrapper>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
.aff-attentifs__container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
user-select: none;
|
||||
font-family: 'Achemine', 'Arial', sans-serif;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* COLONNE GAUCHE (36%) */
|
||||
.aff-attentifs__left-col {
|
||||
flex: 0 0 36%;
|
||||
background-color: #313131;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 70px 50px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.aff-attentifs__title-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.aff-attentifs__title-word {
|
||||
font-size: 78px;
|
||||
font-weight: 900;
|
||||
color: #fdb913;
|
||||
letter-spacing: 2px;
|
||||
line-height: 1.05;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.aff-attentifs__vigipirate-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.aff-attentifs__vigipirate-svg {
|
||||
width: 270px;
|
||||
height: auto;
|
||||
filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.45));
|
||||
}
|
||||
|
||||
/* COLONNE DROITE (64%) */
|
||||
.aff-attentifs__right-col {
|
||||
flex: 1;
|
||||
background-color: #4a4a4a;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 60px 80px;
|
||||
box-sizing: border-box;
|
||||
gap: 40px;
|
||||
}
|
||||
|
||||
.aff-attentifs__info-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.aff-attentifs__info-desc {
|
||||
font-size: 27px;
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
margin: 0 0 36px 0;
|
||||
color: #f8f8f8;
|
||||
}
|
||||
|
||||
.aff-attentifs__call-action {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.aff-attentifs__call-text {
|
||||
font-size: 44px;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0.5px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.aff-attentifs__call-hours {
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
color: #eaeaea;
|
||||
}
|
||||
|
||||
.aff-attentifs__call-footnote {
|
||||
font-size: 19px;
|
||||
font-weight: 400;
|
||||
color: #d0d0d0;
|
||||
}
|
||||
|
||||
/* SECTION BULLE D'ALERTE 3117 */
|
||||
.aff-attentifs__bubble-section {
|
||||
flex: 0 0 460px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.aff-attentifs__bubble-wrap {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.aff-attentifs__bubble-card {
|
||||
position: relative;
|
||||
background-color: #ffffff;
|
||||
border: 7px solid #e2001a;
|
||||
border-radius: 36px;
|
||||
padding: 30px 42px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
|
||||
min-width: 360px;
|
||||
}
|
||||
|
||||
.aff-attentifs__bubble-title {
|
||||
font-size: 28px;
|
||||
font-weight: 900;
|
||||
color: #e2001a;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.aff-attentifs__bubble-rows {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.aff-attentifs__bubble-line {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.aff-attentifs__bubble-label {
|
||||
font-size: 30px;
|
||||
font-weight: 800;
|
||||
color: #e2001a;
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
.aff-attentifs__bubble-number {
|
||||
font-size: 58px;
|
||||
font-weight: 900;
|
||||
color: #e2001a;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
|
||||
.aff-attentifs__bubble-tail {
|
||||
position: absolute;
|
||||
bottom: -32px;
|
||||
left: 54px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 20px solid transparent;
|
||||
border-right: 20px solid transparent;
|
||||
border-top: 32px solid #e2001a;
|
||||
}
|
||||
|
||||
.aff-attentifs__bubble-tail::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -38px;
|
||||
left: -13px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 13px solid transparent;
|
||||
border-right: 13px solid transparent;
|
||||
border-top: 24px solid #ffffff;
|
||||
}
|
||||
|
||||
/* SMARTPHONE BADGE */
|
||||
.aff-attentifs__phone-badge {
|
||||
position: absolute;
|
||||
top: -34px;
|
||||
right: -36px;
|
||||
z-index: 10;
|
||||
filter: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.4));
|
||||
}
|
||||
|
||||
.aff-attentifs__phone-svg {
|
||||
width: 86px;
|
||||
height: auto;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import React from 'react';
|
||||
import './AttentifsEnsemble.css';
|
||||
|
||||
export default function AttentifsEnsemble() {
|
||||
return (
|
||||
<div className="aff-attentifs__container">
|
||||
{/* COLONNE GAUCHE : ANTHRACITE FONCÉ (ATTENTIFS ENSEMBLE + VIGIPIRATE) */}
|
||||
<div className="aff-attentifs__left-col">
|
||||
<div className="aff-attentifs__title-group">
|
||||
<div className="aff-attentifs__title-word">ATTENTIFS</div>
|
||||
<div className="aff-attentifs__title-word">ENSEMBLE</div>
|
||||
</div>
|
||||
|
||||
{/* Insigne Vigipirate Officiel */}
|
||||
<div className="aff-attentifs__vigipirate-wrap">
|
||||
<svg
|
||||
viewBox="0 0 280 240"
|
||||
className="aff-attentifs__vigipirate-svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
{/* Triangle noir extérieur */}
|
||||
<polygon points="140,12 268,228 12,228" fill="#1e1e1e" stroke="#1e1e1e" strokeWidth="8" strokeLinejoin="round" />
|
||||
{/* Triangle rouge intérieur */}
|
||||
<polygon points="140,42 238,206 42,206" fill="#e2001a" />
|
||||
{/* Bandeau blanc en bas */}
|
||||
<polygon points="56,182 224,182 238,206 42,206" fill="#ffffff" />
|
||||
{/* Texte VIGIPIRATE */}
|
||||
<text
|
||||
x="140"
|
||||
y="201"
|
||||
fill="#1e1e1e"
|
||||
fontSize="23"
|
||||
fontWeight="900"
|
||||
fontFamily="Achemine, Arial, sans-serif"
|
||||
textAnchor="middle"
|
||||
letterSpacing="2.5"
|
||||
>
|
||||
VIGIPIRATE
|
||||
</text>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* COLONNE DROITE : GRIS MOYEN (CONSIGNES + BULLE ALERTE 3117) */}
|
||||
<div className="aff-attentifs__right-col">
|
||||
{/* Partie gauche des consignes */}
|
||||
<div className="aff-attentifs__info-section">
|
||||
<p className="aff-attentifs__info-desc">
|
||||
Si vous êtes témoin<br />
|
||||
d'une situation<br />
|
||||
qui présente un risque<br />
|
||||
pour votre sécurité<br />
|
||||
ou celle des autres<br />
|
||||
voyageurs,
|
||||
</p>
|
||||
|
||||
<div className="aff-attentifs__call-action">
|
||||
<span className="aff-attentifs__call-text">APPELER* LE 3117</span>
|
||||
<span className="aff-attentifs__call-hours">24h/24 · 7j/7</span>
|
||||
</div>
|
||||
|
||||
<div className="aff-attentifs__call-footnote">
|
||||
* Appel non surtaxé et enregistré
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Partie droite avec la bulle Alerte SNCF 3117 et le smartphone */}
|
||||
<div className="aff-attentifs__bubble-section">
|
||||
<div className="aff-attentifs__bubble-wrap">
|
||||
{/* Bulle blanche à bordure rouge */}
|
||||
<div className="aff-attentifs__bubble-card">
|
||||
<div className="aff-attentifs__bubble-title">ALERTE SNCF</div>
|
||||
<div className="aff-attentifs__bubble-rows">
|
||||
<div className="aff-attentifs__bubble-line">
|
||||
<span className="aff-attentifs__bubble-label">TÉL.</span>
|
||||
<span className="aff-attentifs__bubble-number">3117*</span>
|
||||
</div>
|
||||
<div className="aff-attentifs__bubble-line">
|
||||
<span className="aff-attentifs__bubble-label">SMS</span>
|
||||
<span className="aff-attentifs__bubble-number">31177**</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Pointe de la bulle */}
|
||||
<div className="aff-attentifs__bubble-tail" />
|
||||
</div>
|
||||
|
||||
{/* Smartphone Rouge d'alerte */}
|
||||
<div className="aff-attentifs__phone-badge">
|
||||
<svg viewBox="0 0 68 104" className="aff-attentifs__phone-svg" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
{/* Corps de téléphone rouge arrondi */}
|
||||
<rect x="4" y="4" width="60" height="96" rx="14" fill="#e2001a" stroke="#ffffff" strokeWidth="4.5" />
|
||||
{/* Écran blanc */}
|
||||
<rect x="12" y="14" width="44" height="50" rx="6" fill="#ffffff" />
|
||||
{/* Point d'exclamation rouge d'urgence */}
|
||||
<rect x="30.5" y="24" width="7" height="20" rx="3.5" fill="#e2001a" />
|
||||
<circle cx="34" cy="53" r="4" fill="#e2001a" />
|
||||
{/* Touches du pavé numérique */}
|
||||
<circle cx="20" cy="74" r="3" fill="#ffffff" />
|
||||
<circle cx="34" cy="74" r="3" fill="#ffffff" />
|
||||
<circle cx="48" cy="74" r="3" fill="#ffffff" />
|
||||
<circle cx="20" cy="85" r="3" fill="#ffffff" />
|
||||
<circle cx="34" cy="85" r="3" fill="#ffffff" />
|
||||
<circle cx="48" cy="85" r="3" fill="#ffffff" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
.aff-dep-afl__container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #d61e38;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
font-family: 'Achemine', 'Arial', sans-serif;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* FRISSE SUPÉRIEURE RAYÉE */
|
||||
.aff-dep-afl__hazard-stripes {
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
background: repeating-linear-gradient(
|
||||
-45deg,
|
||||
#ffffff,
|
||||
#ffffff 28px,
|
||||
#d61e38 28px,
|
||||
#d61e38 56px
|
||||
);
|
||||
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* CONTENU PRINCIPAL */
|
||||
.aff-dep-afl__content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40px 100px;
|
||||
gap: 120px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.aff-dep-afl__icon-col {
|
||||
flex: 0 0 460px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.aff-dep-afl__no-entry-svg {
|
||||
width: 100%;
|
||||
max-width: 440px;
|
||||
height: auto;
|
||||
filter: drop-shadow(0 10px 24px rgba(0, 0, 0, 0.35));
|
||||
}
|
||||
|
||||
.aff-dep-afl__text-col {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 48px;
|
||||
}
|
||||
|
||||
.aff-dep-afl__heading-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1.02;
|
||||
}
|
||||
|
||||
.aff-dep-afl__title-main,
|
||||
.aff-dep-afl__title-sub {
|
||||
font-size: 102px;
|
||||
font-weight: 900;
|
||||
letter-spacing: 2px;
|
||||
color: #ffffff;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.aff-dep-afl__instructions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.aff-dep-afl__instruction-line {
|
||||
font-size: 48px;
|
||||
font-weight: 600;
|
||||
line-height: 1.35;
|
||||
color: #ffffff;
|
||||
margin: 0;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import React from 'react';
|
||||
import './DepartEnCoursAFL.css';
|
||||
|
||||
export default function DepartEnCoursAFL() {
|
||||
return (
|
||||
<div className="aff-dep-afl__container">
|
||||
{/* RUBAN SUPÉRIEUR RAYÉ BLANC ET ROUGE */}
|
||||
<div className="aff-dep-afl__hazard-stripes" />
|
||||
|
||||
{/* CONTENU PRINCIPAL */}
|
||||
<div className="aff-dep-afl__content">
|
||||
{/* Panneau d'interdiction blanc à gauche */}
|
||||
<div className="aff-dep-afl__icon-col">
|
||||
<svg
|
||||
viewBox="0 0 240 240"
|
||||
className="aff-dep-afl__no-entry-svg"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
{/* Cercle blanc extérieur */}
|
||||
<circle cx="120" cy="120" r="105" stroke="#ffffff" strokeWidth="18" />
|
||||
|
||||
{/* Silhouette du piéton marchant avec valise */}
|
||||
<g fill="#ffffff">
|
||||
{/* Tête */}
|
||||
<circle cx="126" cy="62" r="15" />
|
||||
{/* Corps marchant */}
|
||||
<path d="M116 84 C116 84, 134 84, 138 98 L152 144 L140 148 L128 110 L118 132 L112 186 L98 184 L106 126 L96 112 Z" />
|
||||
{/* Jambe droite enjambant */}
|
||||
<path d="M122 134 L138 180 C138 180, 146 186, 140 190 C134 194, 126 188, 126 188 L114 148 Z" />
|
||||
{/* Bras gauche */}
|
||||
<path d="M128 88 L146 114 L138 120 L122 96 Z" />
|
||||
{/* Bras droit tenant la valise */}
|
||||
<path d="M116 86 L98 116 L88 110" stroke="#ffffff" strokeWidth="8" strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
||||
{/* Valise inclinée */}
|
||||
<g transform="rotate(-15, 80, 140)">
|
||||
<rect x="58" y="122" width="38" height="52" rx="7" fill="#ffffff" />
|
||||
<path d="M70 122 V112 H84 V122" stroke="#ffffff" strokeWidth="6" fill="none" />
|
||||
</g>
|
||||
</g>
|
||||
|
||||
{/* Barre diagonale blanche d'interdiction */}
|
||||
<line x1="46" y1="46" x2="194" y2="194" stroke="#ffffff" strokeWidth="18" strokeLinecap="round" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Textes d'alerte et de consigne à droite */}
|
||||
<div className="aff-dep-afl__text-col">
|
||||
<div className="aff-dep-afl__heading-group">
|
||||
<div className="aff-dep-afl__title-main">DÉPARTS</div>
|
||||
<div className="aff-dep-afl__title-sub">EN COURS</div>
|
||||
</div>
|
||||
|
||||
<div className="aff-dep-afl__instructions">
|
||||
<p className="aff-dep-afl__instruction-line">Pour votre sécurité</p>
|
||||
<p className="aff-dep-afl__instruction-line">merci de vous éloigner</p>
|
||||
<p className="aff-dep-afl__instruction-line">de la bordure du quai.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
.aff-dep-classique__container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
font-family: 'Achemine', 'Arial', sans-serif;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* ZONE DU HAUT : GRIS FONCÉ (~72%) */
|
||||
.aff-dep-classique__top {
|
||||
flex: 1;
|
||||
background-color: #222226;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 160px;
|
||||
padding: 40px 100px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.aff-dep-classique__prohibition-sign {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.aff-dep-classique__no-entry-svg {
|
||||
width: 480px;
|
||||
height: 480px;
|
||||
filter: drop-shadow(0 12px 28px rgba(0, 0, 0, 0.45));
|
||||
}
|
||||
|
||||
.aff-dep-classique__train-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.aff-dep-classique__train-gif {
|
||||
width: 480px;
|
||||
height: auto;
|
||||
max-height: 480px;
|
||||
object-fit: contain;
|
||||
filter: drop-shadow(0 12px 28px rgba(0, 0, 0, 0.45));
|
||||
}
|
||||
|
||||
.aff-dep-classique__train-svg {
|
||||
width: 460px;
|
||||
height: 460px;
|
||||
filter: drop-shadow(0 12px 28px rgba(0, 0, 0, 0.45));
|
||||
}
|
||||
|
||||
/* BANDEAU ROUGE INFÉRIEUR (~28%) */
|
||||
.aff-dep-classique__bottom {
|
||||
flex: 0 0 280px;
|
||||
background-color: #d0102a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.aff-dep-classique__banner-text {
|
||||
font-size: 110px;
|
||||
font-weight: 900;
|
||||
color: #ffffff;
|
||||
margin: 0;
|
||||
letter-spacing: 1px;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import React, { useState } from 'react';
|
||||
import './DepartEnCoursClassique.css';
|
||||
|
||||
const GIF_URL = 'https://cdn.discordapp.com/attachments/1265325000290992258/1282018214720835725/SNCF_-_Depart_Train.gif?ex=6a95af01&is=6a945d81&hm=14570f1423217cb52437d767b3125a698ac5955fc088028fbc3d24d820e9a76b&';
|
||||
|
||||
export default function DepartEnCoursClassique() {
|
||||
const [gifError, setGifError] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="aff-dep-classique__container">
|
||||
{/* ZONE SUPÉRIEURE : PICTOS (FOND GRIS FONCÉ) */}
|
||||
<div className="aff-dep-classique__top">
|
||||
{/* Panneau d'interdiction : Ne pas monter (voyageur avec valise barré) */}
|
||||
<div className="aff-dep-classique__prohibition-sign">
|
||||
<svg viewBox="0 0 200 200" className="aff-dep-classique__no-entry-svg" xmlns="http://www.w3.org/2000/svg">
|
||||
{/* Fond blanc du cercle */}
|
||||
<circle cx="100" cy="100" r="90" fill="#ffffff" stroke="#d0102a" strokeWidth="18" />
|
||||
|
||||
{/* Silhouette du voyageur avec valise */}
|
||||
<g fill="#141416">
|
||||
{/* Tête */}
|
||||
<circle cx="92" cy="52" r="14" />
|
||||
{/* Corps */}
|
||||
<rect x="76" y="70" width="32" height="52" rx="10" />
|
||||
{/* Jambe gauche */}
|
||||
<rect x="80" y="118" width="10" height="38" rx="5" />
|
||||
{/* Jambe droite */}
|
||||
<rect x="94" y="118" width="10" height="38" rx="5" />
|
||||
{/* Bras gauche */}
|
||||
<rect x="66" y="72" width="9" height="36" rx="4.5" />
|
||||
{/* Bras droit tenant la poignée */}
|
||||
<path d="M106 74 L120 102 L120 114" stroke="#141416" strokeWidth="8" strokeLinecap="round" strokeLinejoin="round" fill="none" />
|
||||
{/* Poignée télescopique de valise */}
|
||||
<path d="M116 102 V116 H124 V102" stroke="#141416" strokeWidth="4" fill="none" />
|
||||
{/* Valise à roulettes */}
|
||||
<rect x="110" y="116" width="24" height="38" rx="4" fill="#141416" />
|
||||
{/* Roulettes */}
|
||||
<circle cx="114" cy="156" r="3" fill="#141416" />
|
||||
<circle cx="130" cy="156" r="3" fill="#141416" />
|
||||
</g>
|
||||
|
||||
{/* Barre diagonale rouge d'interdiction */}
|
||||
<line x1="36" y1="36" x2="164" y2="164" stroke="#d0102a" strokeWidth="18" strokeLinecap="round" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Animation du train au départ (GIF ou SVG de secours) */}
|
||||
<div className="aff-dep-classique__train-wrap">
|
||||
{!gifError ? (
|
||||
<img
|
||||
src={GIF_URL}
|
||||
alt="Train au départ"
|
||||
className="aff-dep-classique__train-gif"
|
||||
onError={() => setGifError(true)}
|
||||
/>
|
||||
) : (
|
||||
<svg viewBox="0 0 240 240" className="aff-dep-classique__train-svg" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
{/* Rails et traverses */}
|
||||
<path d="M40 200 L95 140 M200 200 L145 140" stroke="#ffffff" strokeWidth="8" strokeLinecap="round" />
|
||||
<line x1="60" y1="185" x2="180" y2="185" stroke="#ffffff" strokeWidth="8" strokeLinecap="round" />
|
||||
<line x1="85" y1="160" x2="155" y2="160" stroke="#ffffff" strokeWidth="6" strokeLinecap="round" />
|
||||
|
||||
{/* Face avant du train */}
|
||||
<rect x="55" y="40" width="130" height="110" rx="35" fill="#ffffff" />
|
||||
{/* Pare-brise */}
|
||||
<rect x="68" y="52" width="104" height="42" rx="14" fill="#1c1c20" />
|
||||
{/* Phares rouges */}
|
||||
<circle cx="82" cy="120" r="10" fill="#d0102a" />
|
||||
<circle cx="158" cy="120" r="10" fill="#d0102a" />
|
||||
</svg>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* BANDEAU INFÉRIEUR ROUGE : DÉPART EN COURS */}
|
||||
<div className="aff-dep-classique__bottom">
|
||||
<h1 className="aff-dep-classique__banner-text">Départ en cours</h1>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
.aff-videoprot__container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #141416;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40px 80px;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Achemine', 'Arial', sans-serif;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.aff-videoprot__wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 80px;
|
||||
width: 100%;
|
||||
max-width: 1600px;
|
||||
}
|
||||
|
||||
.aff-videoprot__icon-col {
|
||||
flex: 0 0 420px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.aff-videoprot__camera-svg {
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
height: auto;
|
||||
filter: drop-shadow(0 6px 16px rgba(242, 91, 42, 0.25));
|
||||
}
|
||||
|
||||
.aff-videoprot__text-col {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.aff-videoprot__title-vigi {
|
||||
font-size: 52px;
|
||||
font-weight: 800;
|
||||
color: #f25b2a;
|
||||
letter-spacing: 1.5px;
|
||||
margin-bottom: 24px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.aff-videoprot__main-heading {
|
||||
font-size: 46px;
|
||||
font-weight: 800;
|
||||
color: #ffffff;
|
||||
line-height: 1.28;
|
||||
letter-spacing: 0.5px;
|
||||
margin: 0 0 54px 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.aff-videoprot__subtext-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.aff-videoprot__legal-line,
|
||||
.aff-videoprot__access-line {
|
||||
font-size: 26px;
|
||||
font-weight: 600;
|
||||
line-height: 1.45;
|
||||
color: #f0f0f0;
|
||||
margin: 0;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import React from 'react';
|
||||
import './GareVideoprotection.css';
|
||||
|
||||
export default function GareVideoprotection() {
|
||||
return (
|
||||
<div className="aff-videoprot__container">
|
||||
<div className="aff-videoprot__wrapper">
|
||||
{/* Caméra de surveillance stylisée orange */}
|
||||
<div className="aff-videoprot__icon-col">
|
||||
<svg
|
||||
viewBox="0 0 320 240"
|
||||
className="aff-videoprot__camera-svg"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
{/* Support mural */}
|
||||
<rect x="20" y="105" width="22" height="75" rx="5" fill="#f25b2a" />
|
||||
<path
|
||||
d="M38 132 H80 L95 105 H125"
|
||||
stroke="#f25b2a"
|
||||
strokeWidth="20"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
|
||||
{/* Corps de la caméra orienté vers le bas à droite */}
|
||||
<g transform="rotate(18, 140, 110)">
|
||||
{/* Corps principal */}
|
||||
<rect x="35" y="55" width="165" height="70" rx="14" fill="#f25b2a" />
|
||||
{/* Parasoleil / Visière supérieure */}
|
||||
<path d="M30 48 L210 48 L195 58 L30 58 Z" fill="#f25b2a" />
|
||||
{/* Cône avant / Objectif */}
|
||||
<polygon points="198,62 250,38 250,142 198,118" fill="#f25b2a" />
|
||||
{/* Fentes d'aération & détails noirs */}
|
||||
<circle cx="65" cy="88" r="10" fill="#141416" />
|
||||
<rect x="95" y="78" width="10" height="26" rx="4" fill="#141416" />
|
||||
<rect x="120" y="78" width="10" height="26" rx="4" fill="#141416" />
|
||||
<rect x="145" y="78" width="10" height="26" rx="4" fill="#141416" />
|
||||
{/* Bague optique */}
|
||||
<rect x="250" y="44" width="14" height="92" rx="3" fill="#f25b2a" />
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Textes d'information et réglementaires */}
|
||||
<div className="aff-videoprot__text-col">
|
||||
<div className="aff-videoprot__title-vigi">VIGI360</div>
|
||||
|
||||
<h1 className="aff-videoprot__main-heading">
|
||||
POUR VOTRE SÉCURITÉ, CET ESPACE<br />
|
||||
EST ÉQUIPÉ DE VIDÉOPROTECTION.
|
||||
</h1>
|
||||
|
||||
<div className="aff-videoprot__subtext-group">
|
||||
<p className="aff-videoprot__legal-line">
|
||||
En application des dispositions des textes législatifs et<br />
|
||||
règlementaires en vigueur.
|
||||
</p>
|
||||
<p className="aff-videoprot__access-line">
|
||||
Pour l'exercice du droit d'accès au enregistrements,<br />
|
||||
s'adresser à un agent d'accueil de la gare.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -408,6 +408,73 @@ export default function SelectAfficheur({ onBack, navigate }) {
|
||||
🚉 Lancer l'Afficheur de Quai
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Options 3 & 4 pour le mode Classiques : Flash Info & Informations */}
|
||||
{typeParam === 'classiques' && (
|
||||
<>
|
||||
{/* Option 3 : Flash Information */}
|
||||
<div className="launcher-select-card" style={{ cursor: 'default' }}>
|
||||
<div>
|
||||
<span className="launcher-card-icon">⚡</span>
|
||||
<span className="launcher-card-tag launcher-card-tag--retro" style={{ background: '#fab23e', color: '#00337f' }}>
|
||||
Flash Info Trafic
|
||||
</span>
|
||||
<h2 className="launcher-card-title">Flash Information</h2>
|
||||
<p className="launcher-card-desc">
|
||||
Écran dédié aux perturbations de circulation en temps réel et travaux de maintenance sur le réseau.
|
||||
</p>
|
||||
<div style={{ background: '#f8fafc', border: '1px solid #e2ebf6', borderRadius: '10px', padding: '16px', marginBottom: '20px' }}>
|
||||
<div style={{ fontSize: '13px', color: '#00337f', fontWeight: 600 }}>
|
||||
⚡ Conforme au design historique <em>Flash Circulation</em> avec fond ambre et bandeau bleu nuit.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const kebab = gareParam ? String(gareParam).trim() : '';
|
||||
navigate(`${prefix}/afficheurs/classiques/flash-info?gare=${encodeURIComponent(kebab)}`);
|
||||
}}
|
||||
className="launcher-btn"
|
||||
style={{ background: '#00337f', color: '#fab23e', border: 'none', fontWeight: 700 }}
|
||||
>
|
||||
⚡ Lancer le Flash Information
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Option 4 : Informations (Messages Dynamiques) */}
|
||||
<div className="launcher-select-card" style={{ cursor: 'default' }}>
|
||||
<div>
|
||||
<span className="launcher-card-icon">ℹ️</span>
|
||||
<span className="launcher-card-tag launcher-card-tag--retro" style={{ background: '#00337f', color: '#ffffff' }}>
|
||||
Messages Gare
|
||||
</span>
|
||||
<h2 className="launcher-card-title">Informations Voyageurs</h2>
|
||||
<p className="launcher-card-desc">
|
||||
Écran d'annonces et consignes dynamiques de la gare (Vigipirate, étiquetage des bagages, sécurité en gare).
|
||||
</p>
|
||||
<div style={{ background: '#f8fafc', border: '1px solid #e2ebf6', borderRadius: '10px', padding: '16px', marginBottom: '20px' }}>
|
||||
<div style={{ fontSize: '13px', color: '#00337f', fontWeight: 600 }}>
|
||||
ℹ️ Conforme au design historique <em>Information</em> avec messages voyageurs de la gare de {decodedGare}.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const kebab = gareParam ? String(gareParam).trim() : '';
|
||||
navigate(`${prefix}/afficheurs/classiques/informations?gare=${encodeURIComponent(kebab)}`);
|
||||
}}
|
||||
className="launcher-btn"
|
||||
style={{ background: '#00337f', color: '#ffffff', border: 'none', fontWeight: 700 }}
|
||||
>
|
||||
ℹ️ Lancer l'Afficheur Informations
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Accès direct aux pages fixes AFL */}
|
||||
|
||||
@@ -6,6 +6,10 @@ import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
||||
import Logo from '../../../components/Logo';
|
||||
import { getSourceFromPath } from '../../../services/railwayService';
|
||||
import { getSncfTimetable } from '../../../services/sncfApi';
|
||||
import GareVideoprotection from '../../../components/afficheurs/GareVideoprotection';
|
||||
import AttentifsEnsemble from '../../../components/afficheurs/AttentifsEnsemble';
|
||||
import AFLInformationsPage from './components/AFLInformationsPage';
|
||||
import AFLArrivees from './AFLArrivees';
|
||||
|
||||
// Helper utilitaire : format HH:MM sans secondes (ex: 15:57)
|
||||
const formatTimeNoSeconds = (v) => {
|
||||
@@ -28,12 +32,16 @@ const AFLArriveesQuais = () => {
|
||||
const [currentTime, setCurrentTime] = useState(new Date());
|
||||
const [nextArrival, setNextArrival] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [idlePhase, setIdlePhase] = useState(0); // 0 = Attentifs (20s), 1 = Quai (20s), 2 = Information (10s)
|
||||
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
const gareParam = searchParams.get('gare') || '';
|
||||
const quaiParam = searchParams.get('quai') || searchParams.get('voie') || '';
|
||||
const gareDisplay = gareParam ? decodeURIComponent(String(gareParam).replace(/\+/g, ' ')).replace(/-/g, ' ') : null;
|
||||
|
||||
const pageParam = (searchParams.get('page') || searchParams.get('mode') || '').toLowerCase();
|
||||
const isVideoprotection = pageParam === 'videoprotection' || searchParams.get('videoprotection') === 'true';
|
||||
|
||||
useAnnonceSonoreRealtime(null, 'AFLArriveesQuais', quaiParam);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -669,7 +677,9 @@ const AFLArriveesQuais = () => {
|
||||
stopForStation = stopsList.find(s => normalizeName((s.gare_nom || s.nom || s.name || '').toString()) === normalizeName(gareDisplay));
|
||||
}
|
||||
const platform = ((stopForStation && (stopForStation.quai_reel || stopForStation.quai || stopForStation.platform || stopForStation.quay)) || h.quai_reel || h.voie || h.quai || '').toString().trim();
|
||||
return quaiParam && platform.toLowerCase() === quaiParam.toLowerCase();
|
||||
if (!quaiParam) return true;
|
||||
const cleanP = (p) => String(p || '').toLowerCase().replace(/^(?:voie|quai|track|platform)\s*/i, '').replace(/\s+/g, '').trim();
|
||||
return cleanP(platform) === cleanP(quaiParam);
|
||||
});
|
||||
|
||||
if (candidatesOnPlatform.length > 0) {
|
||||
@@ -684,13 +694,44 @@ const AFLArriveesQuais = () => {
|
||||
}
|
||||
}, [applyPerturbationsToHoraires, buildPerturbMap, gareDisplay, gareParam, getPerturbationJours, getStops, normalizeName, parseTimeHM, quaiParam]);
|
||||
|
||||
// Alternance par défaut (20s Attentifs -> 20s Quai -> 10s Information) si aucun train n'est prévu sur le quai
|
||||
useEffect(() => {
|
||||
if (nextArrival) return;
|
||||
let duration = 20000;
|
||||
if (idlePhase === 2) duration = 10000;
|
||||
else duration = 20000;
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
setIdlePhase(prev => (prev + 1) % 3);
|
||||
}, duration);
|
||||
return () => clearTimeout(timer);
|
||||
}, [idlePhase, nextArrival]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
const interval = setInterval(fetchData, 15000);
|
||||
return () => clearInterval(interval);
|
||||
}, [fetchData]);
|
||||
|
||||
if (loading) return <div className="afl-q-arr-container" style={{ background: '#173e31' }}></div>;
|
||||
// AFFICHAGE 1 : Page Vidéoprotection (via query)
|
||||
if (isVideoprotection) {
|
||||
return <GareVideoprotection />;
|
||||
}
|
||||
|
||||
// AFFICHAGE 2 : Alternance si aucun train n'est attribué à ce quai
|
||||
if (!nextArrival && gareParam) {
|
||||
if (idlePhase === 0) {
|
||||
return <AttentifsEnsemble />;
|
||||
}
|
||||
if (idlePhase === 1) {
|
||||
return <AFLArrivees />;
|
||||
}
|
||||
if (idlePhase === 2) {
|
||||
return <AFLInformationsPage mode="arrivees" gareName={gareDisplay || 'Votre Gare'} />;
|
||||
}
|
||||
}
|
||||
|
||||
if (loading && !nextArrival) return <div className="afl-q-arr-container" style={{ background: '#173e31' }}></div>;
|
||||
|
||||
if (!nextArrival) {
|
||||
return (
|
||||
|
||||
@@ -6,6 +6,11 @@ import useAnnonceSonoreRealtime from '../../../hooks/useAnnonceSonoreRealtime';
|
||||
import Logo from '../../../components/Logo';
|
||||
import { getSourceFromPath } from '../../../services/railwayService';
|
||||
import { getSncfTimetable } from '../../../services/sncfApi';
|
||||
import GareVideoprotection from '../../../components/afficheurs/GareVideoprotection';
|
||||
import AttentifsEnsemble from '../../../components/afficheurs/AttentifsEnsemble';
|
||||
import DepartEnCoursAFL from '../../../components/afficheurs/DepartEnCoursAFL';
|
||||
import AFLInformationsPage from './components/AFLInformationsPage';
|
||||
import AFLDeparts from './AFLDeparts';
|
||||
|
||||
// Helper utilitaire : format HH:MM sans secondes (ex: 15:57)
|
||||
const formatTimeNoSeconds = (v) => {
|
||||
@@ -28,6 +33,7 @@ const AFLDepartsQuais = () => {
|
||||
const [currentTime, setCurrentTime] = useState(new Date());
|
||||
const [nextDeparture, setNextDeparture] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [idlePhase, setIdlePhase] = useState(0); // 0 = Attentifs (20s), 1 = Quai (20s), 2 = Information (10s)
|
||||
|
||||
// Parse URL manually since we are not in a React Router context
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
@@ -36,6 +42,10 @@ const AFLDepartsQuais = () => {
|
||||
const quaiParam = searchParams.get('quai') || searchParams.get('voie') || '';
|
||||
const gareDisplay = gareParam ? decodeURIComponent(String(gareParam).replace(/\+/g, ' ')).replace(/-/g, ' ') : null;
|
||||
|
||||
const pageParam = (searchParams.get('page') || searchParams.get('mode') || '').toLowerCase();
|
||||
const isVideoprotection = pageParam === 'videoprotection' || searchParams.get('videoprotection') === 'true';
|
||||
const isForceDepartEnCours = pageParam === 'depart_en_cours' || searchParams.get('depart_en_cours') === 'true' || searchParams.get('test_depart') === 'true';
|
||||
|
||||
const [resolvedGareId, setResolvedGareId] = useState(gareIdParam || null);
|
||||
useAnnonceSonoreRealtime(resolvedGareId, 'AFLDepartsQuais', quaiParam);
|
||||
|
||||
@@ -743,7 +753,8 @@ const AFLDepartsQuais = () => {
|
||||
}
|
||||
const platform = ((stopForStation && (stopForStation.quai_reel || stopForStation.quai || stopForStation.platform || stopForStation.quay)) || h.quai_reel || h.voie || h.quai || '').toString().trim();
|
||||
if (!quaiParam) return true;
|
||||
return platform.toLowerCase() === quaiParam.toLowerCase();
|
||||
const cleanP = (p) => String(p || '').toLowerCase().replace(/^(?:voie|quai|track|platform)\s*/i, '').replace(/\s+/g, '').trim();
|
||||
return cleanP(platform) === cleanP(quaiParam);
|
||||
});
|
||||
|
||||
if (candidatesOnPlatform.length > 0) {
|
||||
@@ -758,13 +769,66 @@ const AFLDepartsQuais = () => {
|
||||
}
|
||||
}, [applyPerturbationsToHoraires, buildPerturbMap, gareDisplay, gareParam, getPerturbationJours, getStops, normalizeName, parseTimeHM, quaiParam]);
|
||||
|
||||
// Alternance par défaut (20s Attentifs -> 20s Quai -> 10s Information) si aucun train n'est prévu sur le quai
|
||||
useEffect(() => {
|
||||
if (nextDeparture) return;
|
||||
let duration = 20000;
|
||||
if (idlePhase === 2) duration = 10000;
|
||||
else duration = 20000;
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
setIdlePhase(prev => (prev + 1) % 3);
|
||||
}, duration);
|
||||
return () => clearTimeout(timer);
|
||||
}, [idlePhase, nextDeparture]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
const interval = setInterval(fetchData, 15000);
|
||||
return () => clearInterval(interval);
|
||||
}, [fetchData]);
|
||||
|
||||
if (loading) return <div className="afl-q-container" style={{ background: '#0c0f2e' }}></div>;
|
||||
// 1. Détection "Départ en cours" (2 minutes avant l'heure de départ réelle)
|
||||
let isDepartEnCours = isForceDepartEnCours;
|
||||
if (!isDepartEnCours && nextDeparture) {
|
||||
const rawTime = nextDeparture._rawTime || nextDeparture.heure_depart || nextDeparture.time;
|
||||
const depHM = parseTimeHM(rawTime);
|
||||
const delayMin = nextDeparture._status?.delayMinutes || nextDeparture.retard_minutes || 0;
|
||||
if (depHM != null) {
|
||||
const nowSec = currentTime.getHours() * 3600 + currentTime.getMinutes() * 60 + currentTime.getSeconds();
|
||||
const depSec = (depHM + delayMin) * 60;
|
||||
let diffSec = depSec - nowSec;
|
||||
if (diffSec < -43200) diffSec += 86400;
|
||||
if (diffSec <= 120 && diffSec >= 0) {
|
||||
isDepartEnCours = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AFFICHAGE 1 : Page Vidéoprotection (via query)
|
||||
if (isVideoprotection) {
|
||||
return <GareVideoprotection />;
|
||||
}
|
||||
|
||||
// AFFICHAGE 2 : Départ en cours (T - 2 min)
|
||||
if (isDepartEnCours) {
|
||||
return <DepartEnCoursAFL />;
|
||||
}
|
||||
|
||||
// AFFICHAGE 3 : Alternance si aucun train n'est attribué à ce quai
|
||||
if (!nextDeparture && gareParam) {
|
||||
if (idlePhase === 0) {
|
||||
return <AttentifsEnsemble />;
|
||||
}
|
||||
if (idlePhase === 1) {
|
||||
return <AFLDeparts />;
|
||||
}
|
||||
if (idlePhase === 2) {
|
||||
return <AFLInformationsPage mode="departs" gareName={gareDisplay || 'Votre Gare'} />;
|
||||
}
|
||||
}
|
||||
|
||||
if (loading && !nextDeparture) return <div className="afl-q-container" style={{ background: '#0c0f2e' }}></div>;
|
||||
|
||||
if (!nextDeparture) {
|
||||
return (
|
||||
|
||||
@@ -143,7 +143,7 @@ function Clock(){
|
||||
);
|
||||
}
|
||||
|
||||
export default function ClassiquesArrivees(){
|
||||
export default function ClassiquesArrivees({ defilement = null } = {}){
|
||||
// lire le paramètre de requête ?gare=Nom-de-la-gare
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const gareParam = params.get('gare');
|
||||
@@ -151,8 +151,8 @@ export default function ClassiquesArrivees(){
|
||||
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;
|
||||
// Mode défilement (marquee vertical infini) si ?defilement=true dans l'URL
|
||||
const defilementMode = params.get('defilement') === 'true';
|
||||
// Mode défilement (marquee vertical infini) si ?defilement=true dans l'URL ou passé en prop
|
||||
const defilementMode = defilement !== null ? Boolean(defilement) : (params.get('defilement') === 'true');
|
||||
|
||||
// debug flag activable via ?debug=1 or ?debug=true
|
||||
const debugEnabled = (params.get('debug') === '1' || String(params.get('debug')).toLowerCase() === 'true');
|
||||
|
||||
@@ -143,7 +143,7 @@ function Clock(){
|
||||
);
|
||||
}
|
||||
|
||||
export default function ClassiquesDeparts(){
|
||||
export default function ClassiquesDeparts({ defilement = null } = {}){
|
||||
// lire le paramètre de requête ?gare=Nom-de-la-gare
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const gareParam = params.get('gare');
|
||||
@@ -151,8 +151,8 @@ export default function ClassiquesDeparts(){
|
||||
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;
|
||||
// Mode défilement (marquee vertical infini) si ?defilement=true dans l'URL
|
||||
const defilementMode = params.get('defilement') === 'true';
|
||||
// Mode défilement (marquee vertical infini) si ?defilement=true dans l'URL ou passé en prop
|
||||
const defilementMode = defilement !== null ? Boolean(defilement) : (params.get('defilement') === 'true');
|
||||
|
||||
// debug flag activable via ?debug=1 or ?debug=true
|
||||
const debugEnabled = (params.get('debug') === '1' || String(params.get('debug')).toLowerCase() === 'true');
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #fab23e;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
CONTAINER (1920x1080)
|
||||
========================================================= */
|
||||
.aff-classique-flash__container {
|
||||
position: relative;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
background-color: #fab23e;
|
||||
color: #00337f;
|
||||
font-family: 'Achemine', 'Avenir', 'Helvetica Neue', Arial, sans-serif;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
SIDEBAR GAUCHE : BLEU NUIT (Conforme Image 3)
|
||||
========================================================= */
|
||||
.aff-classique-flash__sidebar {
|
||||
width: 320px;
|
||||
height: 1080px;
|
||||
background-color: #00337f;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.aff-classique-flash__sidebar-text {
|
||||
transform: rotate(-90deg);
|
||||
transform-origin: center center;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 24px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.aff-classique-flash__title-flash {
|
||||
color: #f5a623;
|
||||
font-size: 10.5rem; /* ~125px */
|
||||
font-weight: 700;
|
||||
letter-spacing: 4px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.aff-classique-flash__title-circulation {
|
||||
color: #ffffff;
|
||||
font-size: 10.5rem; /* ~125px */
|
||||
font-weight: 700;
|
||||
letter-spacing: 4px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
ZONE PRINCIPALE : JAUNE / AMBRE (Conforme Image 3)
|
||||
========================================================= */
|
||||
.aff-classique-flash__main {
|
||||
flex: 1;
|
||||
height: 1080px;
|
||||
background-color: #fab23e;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
padding: 60px 80px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.aff-classique-flash__content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding-bottom: 90px;
|
||||
}
|
||||
|
||||
/* AFFICHAGE NOMINAL (TRAFIC NORMAL) */
|
||||
.aff-classique-flash__nominal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
max-width: 1300px;
|
||||
}
|
||||
|
||||
.aff-classique-flash__nominal-title {
|
||||
color: #00337f;
|
||||
font-size: 6.5rem; /* ~78px */
|
||||
font-weight: 700;
|
||||
margin-bottom: 24px;
|
||||
line-height: 1.1;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.aff-classique-flash__nominal-subtitle {
|
||||
color: #00337f;
|
||||
font-size: 3.8rem; /* ~45px */
|
||||
font-weight: 500;
|
||||
line-height: 1.25;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.aff-classique-flash__nominal-detail {
|
||||
color: #00337f;
|
||||
font-size: 2.8rem; /* ~33px */
|
||||
font-weight: 400;
|
||||
line-height: 1.3;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* CARTES D'ALERTE TRAFIC */
|
||||
.aff-classique-flash__alerts-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 28px;
|
||||
max-width: 1350px;
|
||||
}
|
||||
|
||||
.aff-classique-flash__alert-card {
|
||||
background-color: #00337f;
|
||||
color: #ffffff;
|
||||
border-radius: 8px;
|
||||
padding: 32px 40px;
|
||||
box-shadow: 0 8px 24px rgba(0, 51, 127, 0.2);
|
||||
}
|
||||
|
||||
.aff-classique-flash__alert-card--travaux {
|
||||
background-color: #1a2332;
|
||||
}
|
||||
|
||||
.aff-classique-flash__alert-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.aff-classique-flash__alert-tag {
|
||||
background-color: #d32f2f;
|
||||
color: #ffffff;
|
||||
font-size: 2rem;
|
||||
font-weight: 700;
|
||||
padding: 4px 14px;
|
||||
border-radius: 4px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.aff-classique-flash__alert-tag--travaux {
|
||||
background-color: #f5a623;
|
||||
color: #00337f;
|
||||
}
|
||||
|
||||
.aff-classique-flash__alert-line {
|
||||
font-size: 2.6rem;
|
||||
font-weight: 700;
|
||||
color: #fab23e;
|
||||
}
|
||||
|
||||
.aff-classique-flash__alert-title {
|
||||
font-size: 3.6rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 12px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.aff-classique-flash__alert-desc {
|
||||
font-size: 2.8rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.35;
|
||||
color: #e5eaf3;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
HORLOGE BAS DROITE (Conforme Image 3)
|
||||
========================================================= */
|
||||
.aff-classique-flash__footer-clock-box {
|
||||
position: absolute;
|
||||
bottom: 25px;
|
||||
right: 35px;
|
||||
background-color: #00337f;
|
||||
border: 2.5px solid #ffffff;
|
||||
border-radius: 4px;
|
||||
padding: 4px 16px;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.aff-classique-flash__clock {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
font-family: 'Achemine', 'Helvetica Neue', Arial, sans-serif;
|
||||
font-size: 3.4rem;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.aff-classique-flash__clock-hm {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.aff-classique-flash__clock-s {
|
||||
color: #f5a623;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import './ClassiquesFlashInfo.css';
|
||||
import useAfficheurData from '../../../hooks/useAfficheurData';
|
||||
|
||||
function DigitalClock() {
|
||||
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-classique-flash__clock">
|
||||
<span className="aff-classique-flash__clock-hm">{hh}:{mm}</span>
|
||||
<span className="aff-classique-flash__clock-s">{ss}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ClassiquesFlashInfo() {
|
||||
const params = new URLSearchParams(window.location.search || '');
|
||||
const gareParam = params.get('gare');
|
||||
const gareIdParam = params.get('gare_id') || params.get('gareId');
|
||||
|
||||
const gareDisplay = gareParam
|
||||
? decodeURIComponent(String(gareParam).replace(/\+/g, ' ')).replace(/-/g, ' ')
|
||||
: 'Votre Gare';
|
||||
|
||||
const {
|
||||
perturbations = [],
|
||||
travaux = []
|
||||
} = useAfficheurData({
|
||||
gareName: gareDisplay,
|
||||
gareId: gareIdParam,
|
||||
mode: 'departs',
|
||||
refreshIntervalMs: 20000
|
||||
});
|
||||
|
||||
const activePerturbations = (perturbations || []).filter(p => {
|
||||
const t = (p.type_perturbation || p.type || '').toString().toLowerCase();
|
||||
return Boolean(t);
|
||||
});
|
||||
|
||||
const hasTrafficAlerts = activePerturbations.length > 0 || (travaux && travaux.length > 0);
|
||||
|
||||
return (
|
||||
<div className="aff-classique-flash__container">
|
||||
{/* BANDEAU GAUCHE : BLEU NUIT (Conforme Image 3) */}
|
||||
<div className="aff-classique-flash__sidebar">
|
||||
<div className="aff-classique-flash__sidebar-text">
|
||||
<span className="aff-classique-flash__title-flash">flash</span>
|
||||
<span className="aff-classique-flash__title-circulation">circulation</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ZONE PRINCIPALE : AMBRE / JAUNE ORANGE (Conforme Image 3) */}
|
||||
<div className="aff-classique-flash__main">
|
||||
<div className="aff-classique-flash__content">
|
||||
{hasTrafficAlerts ? (
|
||||
<div className="aff-classique-flash__alerts-container">
|
||||
{activePerturbations.map((p, idx) => (
|
||||
<div key={`p-${idx}`} className="aff-classique-flash__alert-card">
|
||||
<div className="aff-classique-flash__alert-header">
|
||||
<span className="aff-classique-flash__alert-tag">Info Trafic</span>
|
||||
<span className="aff-classique-flash__alert-line">{p.ligne_nom || p.ligne || gareDisplay}</span>
|
||||
</div>
|
||||
<div className="aff-classique-flash__alert-title">
|
||||
{p.type_perturbation || p.titre || 'Perturbation en cours'}
|
||||
</div>
|
||||
<div className="aff-classique-flash__alert-desc">
|
||||
{p.message || p.description || p.detail || p.cause || 'Des adaptations de circulation peuvent survenir sur vos trajets. Veuillez écouter les annonces en gare.'}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{(travaux || []).slice(0, 2).map((t, idx) => (
|
||||
<div key={`t-${idx}`} className="aff-classique-flash__alert-card aff-classique-flash__alert-card--travaux">
|
||||
<div className="aff-classique-flash__alert-header">
|
||||
<span className="aff-classique-flash__alert-tag aff-classique-flash__alert-tag--travaux">Travaux</span>
|
||||
<span className="aff-classique-flash__alert-line">{t.nom || t.intitule || 'Maintenance du réseau'}</span>
|
||||
</div>
|
||||
<div className="aff-classique-flash__alert-title">
|
||||
{t.intitule || t.nom || 'Travaux de modernisation'}
|
||||
</div>
|
||||
<div className="aff-classique-flash__alert-desc">
|
||||
{t.description || t.motif || 'Des substitutions par autocars peuvent être mises en place. Merci de vérifier vos horaires.'}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="aff-classique-flash__nominal">
|
||||
<div className="aff-classique-flash__nominal-box">
|
||||
<div className="aff-classique-flash__nominal-title">
|
||||
Trafic normal
|
||||
</div>
|
||||
<div className="aff-classique-flash__nominal-subtitle">
|
||||
La circulation des trains s'effectue normalement sur l'ensemble des lignes desservant la gare de {gareDisplay}.
|
||||
</div>
|
||||
<div className="aff-classique-flash__nominal-detail">
|
||||
Pour toute information complémentaire concernant vos trajets, nos agents en gare sont à votre disposition.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* HORLOGE EN BAS À DROITE (Conforme Image 3) */}
|
||||
<div className="aff-classique-flash__footer-clock-box">
|
||||
<DigitalClock />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #fab23e;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
CONTAINER (1920x1080)
|
||||
========================================================= */
|
||||
.aff-classique-infos__container {
|
||||
position: relative;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
background-color: #fab23e;
|
||||
color: #00337f;
|
||||
font-family: 'Achemine', 'Avenir', 'Helvetica Neue', Arial, sans-serif;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
SIDEBAR GAUCHE : BLEU NUIT (Conforme Image 4)
|
||||
========================================================= */
|
||||
.aff-classique-infos__sidebar {
|
||||
width: 320px;
|
||||
height: 1080px;
|
||||
background-color: #00337f;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.aff-classique-infos__sidebar-text {
|
||||
transform: rotate(-90deg);
|
||||
transform-origin: center center;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.aff-classique-infos__title-information {
|
||||
color: #ffffff;
|
||||
font-size: 10.5rem; /* ~125px */
|
||||
font-weight: 700;
|
||||
letter-spacing: 4px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
ZONE PRINCIPALE : CADRE JAUNE DE DROITE
|
||||
========================================================= */
|
||||
.aff-classique-infos__main {
|
||||
flex: 1;
|
||||
height: 1080px;
|
||||
background-color: #fab23e;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
padding: 80px 100px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* CONTENEUR DU MESSAGE UNIQUE (TEXTE BLEU SUR FOND JAUNE) */
|
||||
.aff-classique-infos__single-message-container {
|
||||
max-width: 1350px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 36px;
|
||||
padding-bottom: 90px;
|
||||
}
|
||||
|
||||
.aff-classique-infos__single-title {
|
||||
color: #00337f;
|
||||
font-size: 64px;
|
||||
font-weight: 900;
|
||||
line-height: 1.15;
|
||||
margin: 0;
|
||||
letter-spacing: -0.5px;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.aff-classique-infos__single-body {
|
||||
color: #00337f;
|
||||
font-size: 46px;
|
||||
font-weight: 600;
|
||||
line-height: 1.45;
|
||||
margin: 0;
|
||||
max-width: 1250px;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
HORLOGE DIGITALE EN BAS À DROITE (Conforme Image 4)
|
||||
========================================================= */
|
||||
.aff-classique-infos__footer-clock-box {
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
right: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.aff-classique-infos__clock {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
background-color: #00337f;
|
||||
border: 4px solid #ffffff;
|
||||
border-radius: 8px;
|
||||
padding: 10px 22px;
|
||||
gap: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.aff-classique-infos__clock-hm {
|
||||
font-size: 3.4rem; /* ~54px */
|
||||
font-weight: 800;
|
||||
color: #ffffff;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.aff-classique-infos__clock-s {
|
||||
font-size: 2.2rem; /* ~35px */
|
||||
font-weight: 800;
|
||||
color: #ff9e1b;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import './ClassiquesInformations.css';
|
||||
import supabase from '../../../lib/supabase';
|
||||
|
||||
function DigitalClock() {
|
||||
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-classique-infos__clock">
|
||||
<span className="aff-classique-infos__clock-hm">{hh}:{mm}</span>
|
||||
<span className="aff-classique-infos__clock-s">{ss}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ClassiquesInformations() {
|
||||
const params = new URLSearchParams(window.location.search || '');
|
||||
const gareParam = params.get('gare');
|
||||
|
||||
const gareDisplay = gareParam
|
||||
? decodeURIComponent(String(gareParam).replace(/\+/g, ' ')).replace(/-/g, ' ')
|
||||
: 'Votre Gare';
|
||||
|
||||
const defaultMessages = [
|
||||
{
|
||||
title: 'Plan Vigipirate & Sécurité',
|
||||
content: 'Ne laissez aucun bagage sans surveillance. Tout bagage abandonné sera détruit. Signalez tout colis ou comportement suspect aux agents SNCF ou aux forces de l\'ordre.'
|
||||
},
|
||||
{
|
||||
title: 'Étiquetage obligatoire de vos bagages',
|
||||
content: 'Pour votre tranquillité et la sécurité de tous, vos valises et sacs doivent impérativement comporter une étiquette visible indiquant vos nom, prénom, téléphone et adresse.'
|
||||
},
|
||||
{
|
||||
title: 'Traversée des voies formellement interdite',
|
||||
content: 'Pour votre sécurité, il est strictement interdit de descendre sur les voies ou de les traverser. Utilisez systématiquement les passages souterrains ou les passerelles.'
|
||||
},
|
||||
{
|
||||
title: 'Espace sans tabac ni vapotage',
|
||||
content: 'Conformément à la réglementation, il est strictement interdit de fumer ou de vapoter dans les espaces couverts, les bâtiments de la gare ainsi que sur les quais.'
|
||||
}
|
||||
];
|
||||
|
||||
const [messagesList, setMessagesList] = useState(defaultMessages);
|
||||
const [activeMessageIndex, setActiveMessageIndex] = useState(0);
|
||||
|
||||
// Chargement éventuel de messages dynamiques depuis Supabase
|
||||
useEffect(() => {
|
||||
let mounted = true;
|
||||
const fetchStationMessages = async () => {
|
||||
if (!supabase) return;
|
||||
try {
|
||||
const { data, error } = await supabase
|
||||
.from('messages_dynamiques')
|
||||
.select('*')
|
||||
.order('id', { ascending: false });
|
||||
if (!error && Array.isArray(data) && data.length > 0 && mounted) {
|
||||
const formatted = data.map(m => ({
|
||||
title: m.titre || m.title || 'Information Voyageurs',
|
||||
content: m.contenu || m.content || m.message || ''
|
||||
})).filter(m => Boolean(m.content));
|
||||
if (formatted.length > 0) {
|
||||
setMessagesList(formatted);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Notice chargement messages_dynamiques:', e);
|
||||
}
|
||||
};
|
||||
fetchStationMessages();
|
||||
return () => { mounted = false; };
|
||||
}, []);
|
||||
|
||||
// Défilement d'un seul message à la fois toutes les 10s si plusieurs messages
|
||||
useEffect(() => {
|
||||
if (messagesList.length <= 1) return;
|
||||
const timer = setInterval(() => {
|
||||
setActiveMessageIndex(prev => (prev + 1) % messagesList.length);
|
||||
}, 10000);
|
||||
return () => clearInterval(timer);
|
||||
}, [messagesList.length]);
|
||||
|
||||
const activeMsg = messagesList[activeMessageIndex % messagesList.length] || defaultMessages[0];
|
||||
|
||||
return (
|
||||
<div className="aff-classique-infos__container">
|
||||
{/* BANDEAU GAUCHE : BLEU NUIT (Conforme Image 4) */}
|
||||
<div className="aff-classique-infos__sidebar">
|
||||
<div className="aff-classique-infos__sidebar-text">
|
||||
<span className="aff-classique-infos__title-information">information</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ZONE PRINCIPALE : CADRE JAUNE DE DROITE AVEC TEXTE BLEU (Conforme Image 4) */}
|
||||
<div className="aff-classique-infos__main">
|
||||
<div className="aff-classique-infos__single-message-container">
|
||||
{activeMsg.title && (
|
||||
<h1 className="aff-classique-infos__single-title">
|
||||
{activeMsg.title}
|
||||
</h1>
|
||||
)}
|
||||
|
||||
<p className="aff-classique-infos__single-body">
|
||||
{activeMsg.content}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* HORLOGE EN BAS À DROITE */}
|
||||
<div className="aff-classique-infos__footer-clock-box">
|
||||
<DigitalClock />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,337 +1,315 @@
|
||||
@font-face {
|
||||
font-family: 'Achemine';
|
||||
src: url('/public/fonts/achemine_regular.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Achemine';
|
||||
src: url('/public/fonts/achemine_bold.ttf') format('truetype');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #006330; /* Green theme */
|
||||
background-color: #116938;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
font-family: 'Achemine', 'Helvetica Neue', Arial, sans-serif;
|
||||
background-color: #006330;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__empty {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__empty-text {
|
||||
font-size: 6rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
LEFT PANEL
|
||||
CONTAINER (1920x1080)
|
||||
========================================================= */
|
||||
.aff-quais-arrivees-redesign__left {
|
||||
.aff-classique-quai-arr__container {
|
||||
position: relative;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
background-color: #116938;
|
||||
color: #ffffff;
|
||||
font-family: 'Achemine', 'Avenir', 'Helvetica Neue', Arial, sans-serif;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
LEFT PANEL (BLANC - Conforme Image 2)
|
||||
========================================================= */
|
||||
.aff-classique-quai-arr__left {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 35%;
|
||||
bottom: 80px;
|
||||
background-color: #f3eef4; /* Lilac/Light Grey background */
|
||||
width: 672px;
|
||||
bottom: 85px;
|
||||
background-color: #ffffff;
|
||||
box-sizing: border-box;
|
||||
padding: 30px 40px;
|
||||
padding: 42px 48px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__sncf-logo {
|
||||
width: 90px;
|
||||
height: auto;
|
||||
margin-bottom: 25px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__time-status {
|
||||
/* Logo Dynamique (TER Bleu / Opérateur) */
|
||||
.aff-classique-quai-arr__brand {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 24px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.aff-classique-quai-arr__brand-logo {
|
||||
height: 50px;
|
||||
max-width: 220px;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.aff-classique-quai-arr__sncf-voyageurs {
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
color: #116938;
|
||||
letter-spacing: 2px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Ligne Heure + Statut */
|
||||
.aff-classique-quai-arr__time-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 15px;
|
||||
margin-bottom: 5px;
|
||||
z-index: 2;
|
||||
margin-bottom: 8px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__time {
|
||||
color: #006330; /* Green theme text */
|
||||
.aff-classique-quai-arr__time {
|
||||
color: #116938;
|
||||
font-weight: 700;
|
||||
font-size: 7.5rem;
|
||||
font-size: 105px;
|
||||
line-height: 0.92;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
|
||||
.aff-classique-quai-arr__status {
|
||||
color: #116938;
|
||||
font-weight: 700;
|
||||
font-size: 32px;
|
||||
line-height: 1;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__status {
|
||||
color: #006330; /* Green theme status */
|
||||
.aff-classique-quai-arr__time--suppressed,
|
||||
.aff-classique-quai-arr__status--suppressed {
|
||||
color: #d32f2f !important;
|
||||
}
|
||||
|
||||
.aff-classique-quai-arr__time--delayed,
|
||||
.aff-classique-quai-arr__status--delayed {
|
||||
color: #f5a623 !important;
|
||||
}
|
||||
|
||||
/* Grande Destination / Gare Terminus */
|
||||
.aff-classique-quai-arr__destination {
|
||||
color: #116938;
|
||||
font-weight: 700;
|
||||
font-size: 2.4rem;
|
||||
line-height: 1;
|
||||
font-size: 82px;
|
||||
line-height: 1.05;
|
||||
margin-top: 14px;
|
||||
margin-bottom: 14px;
|
||||
z-index: 3;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__destination {
|
||||
color: #006330; /* Green theme destination (origin) */
|
||||
font-weight: 700;
|
||||
font-size: 5.5rem; /* Slightly smaller to fit 2 lines if needed */
|
||||
line-height: 1.1;
|
||||
margin-bottom: 5px;
|
||||
z-index: 2;
|
||||
white-space: normal; /* Allow wrapping */
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-height: 13rem; /* Prevent overflowing panel */
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__train-info {
|
||||
/* Info Train (Type + Numéro) */
|
||||
.aff-classique-quai-arr__train-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
z-index: 2;
|
||||
align-items: baseline;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__train-type {
|
||||
color: #006330; /* Green theme train type */
|
||||
.aff-classique-quai-arr__train-type {
|
||||
color: #116938;
|
||||
font-weight: 700;
|
||||
font-size: 2.2rem;
|
||||
font-size: 38px;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__train-number {
|
||||
color: #7e8a80; /* Grey/Green train number */
|
||||
.aff-classique-quai-arr__train-number {
|
||||
color: #7e859b;
|
||||
font-weight: 400;
|
||||
font-size: 2.2rem;
|
||||
font-size: 38px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__icons {
|
||||
/* Filigrane Vertical "arrivée" géant (orienté bas vers haut) */
|
||||
.aff-classique-quai-arr__watermark {
|
||||
position: absolute;
|
||||
right: -5px;
|
||||
bottom: 20px;
|
||||
left: 40px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__watermark {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%) rotate(-90deg);
|
||||
transform-origin: right center;
|
||||
font-size: 17rem; /* Massive size */
|
||||
color: #dbebdf; /* Light green/grey watermark */
|
||||
font-weight: 700;
|
||||
z-index: 1;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-end;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
letter-spacing: 1.5rem;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.aff-classique-quai-arr__watermark span {
|
||||
display: inline-block;
|
||||
transform: rotate(-90deg);
|
||||
transform-origin: 0 100%;
|
||||
font-size: 168px;
|
||||
font-weight: 700;
|
||||
color: #d5e5d8;
|
||||
line-height: 1;
|
||||
letter-spacing: 0.05em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
RIGHT PANEL
|
||||
RIGHT PANEL (VERT FORÊT - Conforme Image 2)
|
||||
========================================================= */
|
||||
.aff-quais-arrivees-redesign__right {
|
||||
.aff-classique-quai-arr__right {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 672px;
|
||||
right: 0;
|
||||
width: 65%;
|
||||
bottom: 80px;
|
||||
background-color: #006330; /* Green theme */
|
||||
bottom: 85px;
|
||||
background-color: #116938;
|
||||
box-sizing: border-box;
|
||||
padding: 30px 0 30px 0;
|
||||
padding: 42px 0 20px 42px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__provenance-title {
|
||||
font-size: 3.4rem;
|
||||
color: #dbeb1a; /* Yellow provenance header */
|
||||
margin-left: 60px;
|
||||
margin-bottom: 20px;
|
||||
font-weight: 700;
|
||||
.aff-classique-quai-arr__stops-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__stops-list {
|
||||
.aff-classique-quai-arr__stops-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 0 0 60px; /* Space from left edge */
|
||||
width: 100%;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px; /* Closer spacing between stops */
|
||||
gap: 12px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__stop {
|
||||
.aff-classique-quai-arr__stop-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 3.4rem;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
position: relative;
|
||||
min-height: 42px;
|
||||
padding-left: 50px; /* Space for rail and bullet */
|
||||
min-height: 56px;
|
||||
padding-left: 65px;
|
||||
}
|
||||
|
||||
/* Bullet styling */
|
||||
.aff-quais-arrivees-redesign__stop-bullet {
|
||||
/* Rail vertical vert sauge (#5c8b6b) */
|
||||
.aff-classique-quai-arr__stop-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0; /* Centered on 24px rail: (24-16)/2 = 4 */
|
||||
margin-left: 4px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 16px; /* Slightly larger bullet */
|
||||
height: 16px;
|
||||
background-color: #fbec22;
|
||||
left: 20px;
|
||||
width: 28px;
|
||||
background-color: #5c8b6b;
|
||||
top: -15px;
|
||||
bottom: -15px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Le rail monte jusqu'en haut au 1er arrêt */
|
||||
.aff-classique-quai-arr__stop-item:first-child::before {
|
||||
top: -600px;
|
||||
}
|
||||
|
||||
/* Le dernier arrêt n'a pas de rail qui continue en dessous */
|
||||
.aff-classique-quai-arr__stop-item:last-child::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Pastille Jaune (#ffe500 / #fbec22) */
|
||||
.aff-classique-quai-arr__bullet {
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #ffe500;
|
||||
border-radius: 50%;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__stop-text {
|
||||
position: relative;
|
||||
z-index: 4;
|
||||
/* Nom de la station */
|
||||
.aff-classique-quai-arr__stop-name {
|
||||
font-size: 42px;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
white-space: nowrap;
|
||||
letter-spacing: 0.5px;
|
||||
padding-left: 10px; /* Space from bullet */
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
/* The vertical rail segments drawn behind each bullet */
|
||||
.aff-quais-arrivees-redesign__stop::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 24px; /* Much wider rail */
|
||||
background-color: #8fa993; /* Light green-grey rail color */
|
||||
top: -10px;
|
||||
bottom: -10px;
|
||||
z-index: 1;
|
||||
/* Gare terminus / mise en avant */
|
||||
.aff-classique-quai-arr__stop-item--dest {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Rail starts at the first bullet's center */
|
||||
.aff-quais-arrivees-redesign__stop:first-child::before {
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
/* Last stop has no rail continuing below */
|
||||
.aff-quais-arrivees-redesign__stop:last-child::before {
|
||||
bottom: 50%;
|
||||
.aff-classique-quai-arr__stop-item--dest .aff-classique-quai-arr__stop-name {
|
||||
background-color: #5c8b6b;
|
||||
padding: 8px 32px 8px 65px;
|
||||
margin-left: -65px;
|
||||
border-radius: 6px;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
font-size: 44px;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
FOOTER
|
||||
FOOTER & HORLOGE (Conforme Image 2)
|
||||
========================================================= */
|
||||
.aff-quais-arrivees-redesign__footer {
|
||||
.aff-classique-quai-arr__footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
background-color: #006330; /* Green theme */
|
||||
width: 1920px;
|
||||
height: 85px;
|
||||
background-color: #116938;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
padding: 0 40px;
|
||||
z-index: 10;
|
||||
padding: 0 35px;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__footer-left {
|
||||
font-size: 3rem;
|
||||
.aff-classique-quai-arr__footer-track {
|
||||
font-size: 34px;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
font-style: italic;
|
||||
font-family: 'Achemine', 'Helvetica Neue', Arial, sans-serif;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__footer-right {
|
||||
.aff-classique-quai-arr__footer-clock {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__clock {
|
||||
border: 2px solid #ffffff;
|
||||
padding: 4px 14px;
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
.aff-classique-quai-arr__clock {
|
||||
background-color: #00337f;
|
||||
border: 2.5px solid #ffffff;
|
||||
padding: 4px 16px;
|
||||
border-radius: 3px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
align-items: baseline;
|
||||
gap: 4px;
|
||||
font-family: 'Achemine', 'Helvetica Neue', Arial, sans-serif;
|
||||
font-size: 42px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__clock-s {
|
||||
color: #f5a623;
|
||||
.aff-classique-quai-arr__clock-hm {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__time--long-text {
|
||||
font-size: 3.5rem !important;
|
||||
line-height: 1.2 !important;
|
||||
.aff-classique-quai-arr__clock-s {
|
||||
color: #ff8c00;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__time--suppressed,
|
||||
.aff-quais-arrivees-redesign__status--suppressed {
|
||||
color: #ff4c5b !important;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__time--delayed,
|
||||
.aff-quais-arrivees-redesign__status--delayed {
|
||||
color: #ff9e43 !important;
|
||||
}
|
||||
|
||||
/* Disrupted Stop styling */
|
||||
.aff-quais-arrivees-redesign__stop-text--suppressed {
|
||||
text-decoration: line-through;
|
||||
color: #ff4c5b;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__stop-text--delayed {
|
||||
color: #ff9e43;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__stop-status-badge {
|
||||
font-size: 2.2rem;
|
||||
font-weight: bold;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__stop-status-badge--suppressed {
|
||||
color: #ff4c5b;
|
||||
}
|
||||
|
||||
.aff-quais-arrivees-redesign__stop-status-badge--delayed {
|
||||
color: #ff9e43;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,344 +1,315 @@
|
||||
@font-face {
|
||||
font-family: 'Achemine';
|
||||
src: url('/public/fonts/achemine_regular.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Achemine';
|
||||
src: url('/public/fonts/achemine_bold.ttf') format('truetype');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #0b376d;
|
||||
background-color: #00337f;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
font-family: 'Achemine', 'Helvetica Neue', Arial, sans-serif;
|
||||
background-color: #0b376d;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__empty {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__empty-text {
|
||||
font-size: 6rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
LEFT PANEL
|
||||
CONTAINER (1920x1080)
|
||||
========================================================= */
|
||||
.aff-quais-departs-redesign__left {
|
||||
.aff-classique-quai-dep__container {
|
||||
position: relative;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
background-color: #00337f;
|
||||
color: #ffffff;
|
||||
font-family: 'Achemine', 'Avenir', 'Helvetica Neue', Arial, sans-serif;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
LEFT PANEL (BLANC - Conforme Image 1)
|
||||
========================================================= */
|
||||
.aff-classique-quai-dep__left {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 35%;
|
||||
bottom: 80px;
|
||||
width: 672px;
|
||||
bottom: 85px;
|
||||
background-color: #ffffff;
|
||||
box-sizing: border-box;
|
||||
padding: 30px 40px;
|
||||
padding: 42px 48px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__sncf-logo {
|
||||
width: 90px;
|
||||
height: auto;
|
||||
margin-bottom: 25px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__time-status {
|
||||
/* Logo Dynamique */
|
||||
.aff-classique-quai-dep__brand {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 24px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.aff-classique-quai-dep__brand-logo {
|
||||
height: 50px;
|
||||
max-width: 220px;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.aff-classique-quai-dep__sncf-voyageurs {
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
color: #00337f;
|
||||
letter-spacing: 2px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* Ligne Heure + Statut */
|
||||
.aff-classique-quai-dep__time-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 15px;
|
||||
margin-bottom: 5px;
|
||||
z-index: 2;
|
||||
margin-bottom: 8px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__time {
|
||||
color: #0b376d;
|
||||
.aff-classique-quai-dep__time {
|
||||
color: #00337f;
|
||||
font-weight: 700;
|
||||
font-size: 7.5rem;
|
||||
font-size: 105px;
|
||||
line-height: 0.92;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
|
||||
.aff-classique-quai-dep__status {
|
||||
color: #00337f;
|
||||
font-weight: 700;
|
||||
font-size: 32px;
|
||||
line-height: 1;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__status {
|
||||
color: #0b376d;
|
||||
.aff-classique-quai-dep__time--suppressed,
|
||||
.aff-classique-quai-dep__status--suppressed {
|
||||
color: #d32f2f !important;
|
||||
}
|
||||
|
||||
.aff-classique-quai-dep__time--delayed,
|
||||
.aff-classique-quai-dep__status--delayed {
|
||||
color: #f5a623 !important;
|
||||
}
|
||||
|
||||
/* Grande Destination */
|
||||
.aff-classique-quai-dep__destination {
|
||||
color: #00337f;
|
||||
font-weight: 700;
|
||||
font-size: 2.4rem;
|
||||
line-height: 1;
|
||||
font-size: 82px;
|
||||
line-height: 1.05;
|
||||
margin-top: 14px;
|
||||
margin-bottom: 14px;
|
||||
z-index: 3;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__destination {
|
||||
color: #0b376d;
|
||||
font-weight: 700;
|
||||
font-size: 5.5rem; /* Slightly smaller to fit 2 lines if needed */
|
||||
line-height: 1.1;
|
||||
margin-bottom: 5px;
|
||||
z-index: 2;
|
||||
white-space: normal; /* Allow wrapping */
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-height: 13rem; /* Prevent overflowing panel */
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__train-info {
|
||||
/* Info Train (Type + Numéro) */
|
||||
.aff-classique-quai-dep__train-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
z-index: 2;
|
||||
align-items: baseline;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__train-type {
|
||||
color: #0b376d;
|
||||
.aff-classique-quai-dep__train-type {
|
||||
color: #00337f;
|
||||
font-weight: 700;
|
||||
font-size: 2.2rem;
|
||||
font-size: 38px;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__train-number {
|
||||
color: #929bb0;
|
||||
.aff-classique-quai-dep__train-number {
|
||||
color: #7e859b;
|
||||
font-weight: 400;
|
||||
font-size: 2.2rem;
|
||||
font-size: 38px;
|
||||
letter-spacing: 0.5px;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__icons {
|
||||
/* Filigrane Vertical "départ" géant (orienté bas vers haut) */
|
||||
.aff-classique-quai-dep__watermark {
|
||||
position: absolute;
|
||||
right: -5px;
|
||||
bottom: 20px;
|
||||
left: 40px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__watermark {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%) rotate(-90deg);
|
||||
transform-origin: right center;
|
||||
font-size: 17rem; /* Massive size */
|
||||
color: #e5e8ed;
|
||||
font-weight: 700;
|
||||
z-index: 1;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-end;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
letter-spacing: 1.5rem;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.aff-classique-quai-dep__watermark span {
|
||||
display: inline-block;
|
||||
transform: rotate(-90deg);
|
||||
transform-origin: 0 100%;
|
||||
font-size: 168px;
|
||||
font-weight: 700;
|
||||
color: #e2e8f2;
|
||||
line-height: 1;
|
||||
letter-spacing: 0.05em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
RIGHT PANEL
|
||||
RIGHT PANEL (BLEU NUIT - Conforme Image 1)
|
||||
========================================================= */
|
||||
.aff-quais-departs-redesign__right {
|
||||
.aff-classique-quai-dep__right {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 672px;
|
||||
right: 0;
|
||||
width: 65%;
|
||||
bottom: 80px;
|
||||
background-color: #0b376d;
|
||||
bottom: 85px;
|
||||
background-color: #00337f;
|
||||
box-sizing: border-box;
|
||||
padding: 30px 0 30px 0;
|
||||
padding: 42px 0 20px 42px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__stops-list {
|
||||
.aff-classique-quai-dep__stops-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.aff-classique-quai-dep__stops-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 0 0 60px; /* Space from left edge */
|
||||
width: 100%;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px; /* Closer spacing between stops */
|
||||
gap: 12px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__stop {
|
||||
.aff-classique-quai-dep__stop-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 3.4rem;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
position: relative;
|
||||
min-height: 42px;
|
||||
padding-left: 50px; /* Space for rail and bullet */
|
||||
min-height: 56px;
|
||||
padding-left: 65px;
|
||||
}
|
||||
|
||||
/* Bullet styling */
|
||||
.aff-quais-departs-redesign__stop-bullet {
|
||||
/* Rail vertical violet/indigo (#5c538f) */
|
||||
.aff-classique-quai-dep__stop-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0; /* Centered on 24px rail: (24-16)/2 = 4 */
|
||||
margin-left: 4px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 16px; /* Slightly larger bullet */
|
||||
height: 16px;
|
||||
background-color: #fbec22;
|
||||
left: 20px;
|
||||
width: 28px;
|
||||
background-color: #5c538f;
|
||||
top: -15px;
|
||||
bottom: -15px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Le rail monte jusqu'en haut au 1er arrêt */
|
||||
.aff-classique-quai-dep__stop-item:first-child::before {
|
||||
top: -600px;
|
||||
}
|
||||
|
||||
/* Le dernier arrêt n'a pas de rail qui continue en dessous */
|
||||
.aff-classique-quai-dep__stop-item:last-child::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Pastille Jaune (#ffe500 / #fbec22) */
|
||||
.aff-classique-quai-dep__bullet {
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #ffe500;
|
||||
border-radius: 50%;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__stop-text {
|
||||
position: relative;
|
||||
z-index: 4;
|
||||
/* Nom de la station */
|
||||
.aff-classique-quai-dep__stop-name {
|
||||
font-size: 42px;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
white-space: nowrap;
|
||||
letter-spacing: 0.5px;
|
||||
padding-left: 10px; /* Space from bullet */
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
/* The vertical rail segments drawn behind each bullet */
|
||||
.aff-quais-departs-redesign__stop::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 24px; /* Much wider rail */
|
||||
background-color: #5c538f;
|
||||
top: -10px;
|
||||
bottom: -10px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Rail extends all the way to the top */
|
||||
.aff-quais-departs-redesign__stop:first-child::before {
|
||||
top: -1000px;
|
||||
}
|
||||
|
||||
/* Last stop has no rail continuing below */
|
||||
.aff-quais-departs-redesign__stop:last-child::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Highlighted Destination Stop */
|
||||
.aff-quais-departs-redesign__stop--dest {
|
||||
/* Gare terminus / mise en avant */
|
||||
.aff-classique-quai-dep__stop-item--dest {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__stop--dest .aff-quais-departs-redesign__stop-text {
|
||||
.aff-classique-quai-dep__stop-item--dest .aff-classique-quai-dep__stop-name {
|
||||
background-color: #5c538f;
|
||||
padding: 4px 20px 4px 60px; /* Increased left padding to cover bullet */
|
||||
margin-left: -60px; /* Pull back to exactly align with left:0 */
|
||||
border-radius: 4px;
|
||||
padding: 8px 32px 8px 65px;
|
||||
margin-left: -65px;
|
||||
border-radius: 6px;
|
||||
position: relative;
|
||||
z-index: 3; /* Behind the bullet (z-index 4) */
|
||||
z-index: 3;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
font-size: 44px;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
FOOTER
|
||||
FOOTER & HORLOGE (Conforme Image 1)
|
||||
========================================================= */
|
||||
.aff-quais-departs-redesign__footer {
|
||||
.aff-classique-quai-dep__footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
background-color: #0b376d;
|
||||
width: 1920px;
|
||||
height: 85px;
|
||||
background-color: #00337f;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
padding: 0 40px;
|
||||
z-index: 10;
|
||||
padding: 0 35px;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__footer-left {
|
||||
font-size: 3rem;
|
||||
.aff-classique-quai-dep__footer-track {
|
||||
font-size: 34px;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
font-style: italic;
|
||||
font-family: 'Achemine', 'Helvetica Neue', Arial, sans-serif;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__footer-right {
|
||||
.aff-classique-quai-dep__footer-clock {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__clock {
|
||||
border: 2px solid #ffffff;
|
||||
padding: 4px 14px;
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
.aff-classique-quai-dep__clock {
|
||||
background-color: #00337f;
|
||||
border: 2.5px solid #ffffff;
|
||||
padding: 4px 16px;
|
||||
border-radius: 3px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
align-items: baseline;
|
||||
gap: 4px;
|
||||
font-family: 'Achemine', 'Helvetica Neue', Arial, sans-serif;
|
||||
font-size: 42px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__clock-s {
|
||||
color: #f5a623;
|
||||
.aff-classique-quai-dep__clock-hm {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__time--long-text {
|
||||
font-size: 3.5rem !important;
|
||||
line-height: 1.2 !important;
|
||||
.aff-classique-quai-dep__clock-s {
|
||||
color: #ff8c00;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__time--suppressed,
|
||||
.aff-quais-departs-redesign__status--suppressed {
|
||||
color: #ff4c5b !important;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__time--delayed,
|
||||
.aff-quais-departs-redesign__status--delayed {
|
||||
color: #ff9e43 !important;
|
||||
}
|
||||
|
||||
/* Disrupted Stop styling */
|
||||
.aff-quais-departs-redesign__stop-text--suppressed {
|
||||
text-decoration: line-through;
|
||||
color: #ff4c5b;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__stop-text--delayed {
|
||||
color: #ff9e43;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__stop-status-badge {
|
||||
font-size: 2.2rem;
|
||||
font-weight: bold;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__stop-status-badge--suppressed {
|
||||
color: #ff4c5b;
|
||||
}
|
||||
|
||||
.aff-quais-departs-redesign__stop-status-badge--delayed {
|
||||
color: #ff9e43;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+15
-12
@@ -550,6 +550,14 @@ async function fetchGtfsStationTimetable(uic, mode = 'departs') {
|
||||
resultList = remainingToday;
|
||||
}
|
||||
|
||||
if (resultList.length === 0) {
|
||||
resultList = (enrichedToday.length > 0 ? enrichedToday : rawList.map((t, idx) => mapTrain(t, idx, false))).sort((a, b) => {
|
||||
const aHM = (mode === 'arrivees' ? a._arrHM : a._depHM) || 0;
|
||||
const bHM = (mode === 'arrivees' ? b._arrHM : b._depHM) || 0;
|
||||
return aHM - bHM;
|
||||
});
|
||||
}
|
||||
|
||||
return resultList;
|
||||
} catch (err) {
|
||||
console.warn('[sncfApi] Erreur de chargement GTFS station:', err);
|
||||
@@ -587,19 +595,14 @@ export async function getSncfTimetable({ gareName, mode = 'departs', quai = null
|
||||
finalTrains = [];
|
||||
}
|
||||
|
||||
// 3. Filtrage par quai si demandé
|
||||
// 3. Filtrage strict par quai si demandé
|
||||
if (quai) {
|
||||
const normQuai = String(quai).trim().toLowerCase();
|
||||
const matching = finalTrains.filter(t => String(t.quai || t.voie).trim().toLowerCase() === normQuai);
|
||||
if (matching.length > 0) {
|
||||
finalTrains = matching;
|
||||
} else if (finalTrains.length > 0) {
|
||||
finalTrains[0].quai = quai;
|
||||
finalTrains[0].voie = quai;
|
||||
finalTrains[0].quai_reel = quai;
|
||||
finalTrains[0]._displayPlatform = quai;
|
||||
finalTrains = [finalTrains[0]];
|
||||
}
|
||||
const cleanP = (p) => String(p || '').toLowerCase().replace(/^(?:voie|quai|track|platform)\s*/i, '').replace(/\s+/g, '').trim();
|
||||
const targetP = cleanP(quai);
|
||||
finalTrains = finalTrains.filter(t => {
|
||||
const q = cleanP(t.quai || t.voie || t.quai_reel || t._displayPlatform);
|
||||
return Boolean(q && q === targetP);
|
||||
});
|
||||
}
|
||||
|
||||
return { data: finalTrains, error: null };
|
||||
|
||||
Reference in new issue
Block a user