RELEASE V0.0.1.2 : Insertion des données de la BDD + Suppression des données mockées
This commit is contained in:
1 parent
3eed2b9cd4
commit
9b7ff6e295
8 files changed
+1273
-658
No files matched your search
@@ -0,0 +1,24 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="sncf-grad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stop-color="#0066a4"/>
|
||||||
|
<stop offset="100%" stop-color="#004b7a"/>
|
||||||
|
</linearGradient>
|
||||||
|
<filter id="shadow" x="-10%" y="-10%" width="120%" height="120%">
|
||||||
|
<feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#000" flood-opacity="0.2"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<rect width="512" height="512" rx="108" fill="url(#sncf-grad)"/>
|
||||||
|
|
||||||
|
<!-- SNCF Red Badge -->
|
||||||
|
<rect x="80" y="80" width="160" height="70" rx="8" fill="#cd0037" filter="url(#shadow)"/>
|
||||||
|
<text x="160" y="130" fill="#ffffff" font-family="Avenir, sans-serif" font-weight="900" font-size="44" text-anchor="middle" letter-spacing="2">SNCF</text>
|
||||||
|
|
||||||
|
<!-- Train Icon -->
|
||||||
|
<g transform="translate(136, 170)" fill="#ffffff">
|
||||||
|
<path d="M120 0C53.7 0 0 53.7 0 120v100c0 33.1 26.9 60 60 60v20c0 11 9 20 20 20s20-9 20-20v-20h80v20c0 11 9 20 20 20s20-9 20-20v-20c33.1 0 60-26.9 60-60V120C240 53.7 186.3 0 120 0zm-80 60h160v60H40V60zm30 150c-11 0-20-9-20-20s9-20 20-20 20 9 20 20-9 20-20 20zm100 0c-11 0-20-9-20-20s9-20 20-20 20 9 20 20-9 20-20 20z"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- TER ZOU text / Tag -->
|
||||||
|
<text x="256" y="440" fill="#ffffff" font-family="Avenir, sans-serif" font-weight="800" font-size="34" text-anchor="middle" letter-spacing="1">FERROVIA RÉGIONS</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "FERROVIA - Sites TER Régionaux",
|
||||||
|
"short_name": "FERROVIA",
|
||||||
|
"description": "Consultez les horaires, l'info trafic et achetez vos billets TER dans toutes les régions de France.",
|
||||||
|
"start_url": "/",
|
||||||
|
"id": "/",
|
||||||
|
"display": "standalone",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"theme_color": "#0066a4",
|
||||||
|
"orientation": "portrait-primary",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/icon.svg",
|
||||||
|
"sizes": "any",
|
||||||
|
"type": "image/svg+xml",
|
||||||
|
"purpose": "any maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/icon.svg",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/svg+xml"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/icon.svg",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/svg+xml"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
"travel",
|
||||||
|
"transportation"
|
||||||
|
],
|
||||||
|
"lang": "fr-FR",
|
||||||
|
"dir": "ltr",
|
||||||
|
"prefer_related_applications": false
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
const CACHE_NAME = 'ferrovia-pwa-v2';
|
||||||
|
|
||||||
|
self.addEventListener('install', (event) => {
|
||||||
|
self.skipWaiting();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('activate', (event) => {
|
||||||
|
event.waitUntil(
|
||||||
|
caches.keys().then((keys) => {
|
||||||
|
return Promise.all(
|
||||||
|
keys.map((key) => {
|
||||||
|
if (key !== CACHE_NAME) {
|
||||||
|
return caches.delete(key);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}).then(() => self.clients.claim())
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Network-First strategy: Always try network first to guarantee live updates
|
||||||
|
self.addEventListener('fetch', (event) => {
|
||||||
|
if (event.request.method !== 'GET') return;
|
||||||
|
|
||||||
|
const url = new URL(event.request.url);
|
||||||
|
|
||||||
|
// Do not cache API or Supabase requests
|
||||||
|
if (url.pathname.startsWith('/api') || url.hostname.includes('supabase')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.respondWith(
|
||||||
|
fetch(event.request)
|
||||||
|
.then((networkResponse) => {
|
||||||
|
if (networkResponse && networkResponse.status === 200 && networkResponse.type === 'basic') {
|
||||||
|
const responseToCache = networkResponse.clone();
|
||||||
|
caches.open(CACHE_NAME).then((cache) => {
|
||||||
|
cache.put(event.request, responseToCache);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return networkResponse;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
return caches.match(event.request);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { supabase } from '@/lib/supabase';
|
import { supabase } from '@/lib/supabase';
|
||||||
import RegionContent from '@/components/RegionContent';
|
import RegionContent, { InfoTraficItem, ActualiteItem, HoraireItem } from '@/components/RegionContent';
|
||||||
|
|
||||||
interface RegionData {
|
interface RegionData {
|
||||||
nom_site: string;
|
nom_site: string;
|
||||||
@@ -8,12 +8,8 @@ interface RegionData {
|
|||||||
description_site: string;
|
description_site: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GeneralParams {
|
export const dynamic = 'force-dynamic';
|
||||||
region: string;
|
export const revalidate = 0;
|
||||||
regions: Record<string, RegionData>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const revalidate = 60; // Revalidate every 60s
|
|
||||||
|
|
||||||
export default async function RegionPage({
|
export default async function RegionPage({
|
||||||
params,
|
params,
|
||||||
@@ -22,7 +18,8 @@ export default async function RegionPage({
|
|||||||
}) {
|
}) {
|
||||||
const { region } = await params;
|
const { region } = await params;
|
||||||
|
|
||||||
const { data, error } = await supabase
|
// 1. Fetch general settings
|
||||||
|
const { data } = await supabase
|
||||||
.from('parametres')
|
.from('parametres')
|
||||||
.select('valeur')
|
.select('valeur')
|
||||||
.eq('cle', 'general')
|
.eq('cle', 'general')
|
||||||
@@ -69,5 +66,79 @@ export default async function RegionPage({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return <RegionContent regionSlug={region} regionData={regionData} />;
|
// 2. Fetch info trafic from Supabase table "info_trafic"
|
||||||
|
let infoTraficList: InfoTraficItem[] = [];
|
||||||
|
try {
|
||||||
|
const { data: trafficData } = await supabase
|
||||||
|
.from('info_trafic')
|
||||||
|
.select('*')
|
||||||
|
.eq('actif', true)
|
||||||
|
.is('deleted_at', null)
|
||||||
|
.order('created_at', { ascending: false });
|
||||||
|
if (trafficData) {
|
||||||
|
infoTraficList = trafficData as InfoTraficItem[];
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error fetching info_trafic:', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Fetch actualites from Supabase table "actualites"
|
||||||
|
let actualitesList: ActualiteItem[] = [];
|
||||||
|
try {
|
||||||
|
const { data: actusData } = await supabase
|
||||||
|
.from('actualites')
|
||||||
|
.select('*')
|
||||||
|
.eq('actif', true)
|
||||||
|
.is('deleted_at', null)
|
||||||
|
.order('date_publication', { ascending: false })
|
||||||
|
.order('created_at', { ascending: false });
|
||||||
|
if (actusData) {
|
||||||
|
actualitesList = actusData as ActualiteItem[];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error fetching actualites:', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Fetch gares and horaires from Supabase table "horaires"
|
||||||
|
let horairesList: HoraireItem[] = [];
|
||||||
|
try {
|
||||||
|
const { data: garesData } = await supabase
|
||||||
|
.from('gares')
|
||||||
|
.select('id, nom');
|
||||||
|
|
||||||
|
const garesMap: Record<string, string> = {};
|
||||||
|
if (garesData) {
|
||||||
|
garesData.forEach((g: any) => {
|
||||||
|
garesMap[g.id] = g.nom;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: rawHoraires } = await supabase
|
||||||
|
.from('horaires')
|
||||||
|
.select('*')
|
||||||
|
.eq('actif', true)
|
||||||
|
.is('deleted_at', null)
|
||||||
|
.order('heure_depart', { ascending: true });
|
||||||
|
|
||||||
|
if (rawHoraires) {
|
||||||
|
horairesList = rawHoraires.map((h: any) => ({
|
||||||
|
...h,
|
||||||
|
gare_depart_nom: garesMap[h.gare_depart_id] || '',
|
||||||
|
gare_arrivee_nom: garesMap[h.gare_arrivee_id] || '',
|
||||||
|
})) as HoraireItem[];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Error fetching horaires:', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RegionContent
|
||||||
|
regionSlug={region}
|
||||||
|
regionData={regionData}
|
||||||
|
initialInfoTrafic={infoTraficList}
|
||||||
|
initialActualites={actualitesList}
|
||||||
|
initialHoraires={horairesList}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -145,3 +145,27 @@ body {
|
|||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideInLeftDrawer {
|
||||||
|
from {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fadeIn {
|
||||||
|
animation: fadeIn 0.2s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-slideInLeftDrawer {
|
||||||
|
animation: slideInLeftDrawer 0.28s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+51
-10
@@ -1,6 +1,7 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata, Viewport } from "next";
|
||||||
import { Geist, Geist_Mono } from "next/font/google";
|
import { Geist, Geist_Mono } from "next/font/google";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
const geistSans = Geist({
|
const geistSans = Geist({
|
||||||
variable: "--font-geist-sans",
|
variable: "--font-geist-sans",
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
@@ -12,20 +13,60 @@ const geistMono = Geist_Mono({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Create Next App",
|
title: "FERROVIA - Sites TER Régionaux",
|
||||||
description: "Generated by create next app",
|
description: "Consultez les horaires, l'info trafic et achetez vos billets TER dans toutes les régions de France.",
|
||||||
|
manifest: "/manifest.json",
|
||||||
|
appleWebApp: {
|
||||||
|
capable: true,
|
||||||
|
statusBarStyle: "default",
|
||||||
|
title: "FERROVIA",
|
||||||
|
},
|
||||||
|
icons: {
|
||||||
|
icon: "/icon.svg",
|
||||||
|
apple: "/icon.svg",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export default function RootLayout({ children }: { children: React.ReactNode })
|
|
||||||
{
|
|
||||||
return (
|
|
||||||
|
|
||||||
|
export const viewport: Viewport = {
|
||||||
|
themeColor: "#0066a4",
|
||||||
|
width: "device-width",
|
||||||
|
initialScale: 1,
|
||||||
|
maximumScale: 1,
|
||||||
|
userScalable: false,
|
||||||
|
viewportFit: "cover",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
<html
|
<html
|
||||||
lang="en"
|
lang="fr"
|
||||||
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
|
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
|
||||||
>
|
>
|
||||||
<body className="sncf-voyageurs">{children}
|
<head>
|
||||||
|
<link rel="manifest" href="/manifest.json" />
|
||||||
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||||
|
<meta name="apple-mobile-web-app-title" content="FERROVIA" />
|
||||||
|
<link rel="apple-touch-icon" href="/icon.svg" />
|
||||||
|
</head>
|
||||||
|
<body className="sncf-voyageurs min-h-full">
|
||||||
|
{children}
|
||||||
|
<script
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
navigator.serviceWorker.register('/sw.js').then(function(reg) {
|
||||||
|
reg.update();
|
||||||
|
}).catch(function(err) {
|
||||||
|
console.log('ServiceWorker registration failed: ', err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
+11
-18
@@ -1,31 +1,24 @@
|
|||||||
import React from 'react';
|
import { redirect } from 'next/navigation';
|
||||||
import { supabase } from '@/lib/supabase';
|
import { supabase } from '@/lib/supabase';
|
||||||
import HomeContent from '@/components/HomeContent';
|
|
||||||
|
|
||||||
interface RegionData {
|
export const dynamic = 'force-dynamic';
|
||||||
nom_site: string;
|
export const revalidate = 0;
|
||||||
logo_header_url: string;
|
|
||||||
description_site: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GeneralParams {
|
|
||||||
region: string;
|
|
||||||
regions: Record<string, RegionData>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const revalidate = 60; // Revalidate every 60s
|
|
||||||
|
|
||||||
export default async function HomePage() {
|
export default async function HomePage() {
|
||||||
const { data, error } = await supabase
|
const { data } = await supabase
|
||||||
.from('parametres')
|
.from('parametres')
|
||||||
.select('valeur')
|
.select('valeur')
|
||||||
.eq('cle', 'general')
|
.eq('cle', 'general')
|
||||||
.single();
|
.single();
|
||||||
|
|
||||||
let general: GeneralParams | null = null;
|
let targetRegion = 'bourgogne-franche-comte';
|
||||||
if (data && data.valeur) {
|
if (data && data.valeur) {
|
||||||
general = data.valeur as GeneralParams;
|
const val = data.valeur as any;
|
||||||
|
if (val.region) {
|
||||||
|
targetRegion = val.region;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <HomeContent general={general} />;
|
redirect(`/${targetRegion}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
+999
-621
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user