Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/preview-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ jobs:
VERCEL_PROJECT_ID: ${{ env.VERCEL_PROJECT_ID }}

- name: Cypress test
uses: cypress-io/github-action@v6
uses: cypress-io/github-action@v7
with:
start: yarn e2e:setup
command: yarn e2e:run
Expand Down
42 changes: 40 additions & 2 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@
"metricsAdminOnly": "Metrics - Admin Only",
"languageSelect": "Language select",
"transitFeedsRedirectTitle": "You've been redirected from TransitFeeds",
"transitFeedsRedirectBody": "This page now lives on MobilityDatabase.org, where you'll find the most up-to-date transit data."
"transitFeedsRedirectBody": "This page now lives on MobilityDatabase.org, where you'll find the most up-to-date transit data.",
"locations": "Locations",
"feedsMenu": "Feeds menu"
},
"emailVerification": {
"loadingTitle": "Verifying your email",
Expand Down Expand Up @@ -1254,13 +1256,49 @@
"contactUs": "Contact Us",
"shareFeedback": "Share Feedback",
"privacyPolicy": "Privacy Policy",
"termsAndConditions": "Terms and Conditions"
"termsAndConditions": "Terms and Conditions",
"locations": "Locations"
},
"aria": {
"github": "GitHub",
"slack": "Slack",
"linkedin": "LinkedIn",
"logo": "Mobility Database logo"
}
},
"locations": {
"root": "Locations",
"title": "Feeds by location",
"rootIntro": "Browse open GTFS Schedule, GTFS Realtime and GBFS feeds by location, from continents down to cities.",
"nodeIntro": "{total, plural, =0 {No feeds are} one {# feed is} other {# feeds are}} located in {place}.",
"feedCountsAria": "Feed counts by data type",
"shortLabels": {
"gtfs": "GTFS",
"gtfs_rt": "GTFS-RT",
"gbfs": "GBFS"
},
"childrenHeading": {
"continents": "Continents",
"countries": "Countries",
"places": "Places"
},
"childFeedTotal": "{count, plural, one {<b>#</b> feed} other {<b>#</b> feeds}}",
"childrenSearchPlaceholder": "Search locations",
"childrenSearchAria": "Filter the locations below by name",
"childLoadingAria": "Loading {name}",
"childrenSearchResults": "{count, plural, =0 {No matching locations} one {# matching location} other {# matching locations}}",
"childrenSearchEmpty": "No location matches “{query}”.",
"feedsHeading": "Feeds in {place}",
"allFeedsHeading": "All feeds",
"resultsRange": "Showing {start}–{end} of {total} feeds",
"noFeeds": "No feeds are listed for this location yet.",
"paginationAria": "Feed list pages",
"meta": {
"rootTitle": "Transit Feeds by Location | Mobility Database",
"rootDescription": "Browse open GTFS Schedule, GTFS Realtime and GBFS transit and mobility feeds by location, from continents down to cities.",
"nodeTitle": "{place} Transit Feeds | Mobility Database",
"nodeTitlePaged": "{place} Transit Feeds, Page {page} | Mobility Database",
"nodeDescription": "Browse {total} open transit and mobility feeds located in {place}: {gtfs} GTFS Schedule, {gtfs_rt} GTFS Realtime and {gbfs} GBFS."
}
}
}
42 changes: 40 additions & 2 deletions messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@
"metricsAdminOnly": "Métriques - Admin uniquement",
"languageSelect": "Sélection de la langue",
"transitFeedsRedirectTitle": "Vous avez été redirigé depuis TransitFeeds",
"transitFeedsRedirectBody": "Cette page se trouve désormais sur MobilityDatabase.org, où vous trouverez les données de transit les plus récentes."
"transitFeedsRedirectBody": "Cette page se trouve désormais sur MobilityDatabase.org, où vous trouverez les données de transit les plus récentes.",
"locations": "Lieux",
"feedsMenu": "Menu des flux"
},
"emailVerification": {
"loadingTitle": "Vérification de votre e-mail",
Expand Down Expand Up @@ -1254,13 +1256,49 @@
"contactUs": "Contactez-nous",
"shareFeedback": "Donner un avis",
"privacyPolicy": "Politique de confidentialité",
"termsAndConditions": "Conditions d'utilisation"
"termsAndConditions": "Conditions d'utilisation",
"locations": "Lieux"
},
"aria": {
"github": "GitHub",
"slack": "Slack",
"linkedin": "LinkedIn",
"logo": "Logo Mobility Database"
}
},
"locations": {
"root": "Lieux",
"title": "Flux par lieu",
"rootIntro": "Parcourez les flux ouverts GTFS Schedule, GTFS Realtime et GBFS par lieu, des continents jusqu’aux villes.",
"nodeIntro": "{total, plural, =0 {Aucun flux n’est situé} one {# flux est situé} other {# flux sont situés}} dans : {place}.",
"feedCountsAria": "Nombre de flux par type de données",
"shortLabels": {
"gtfs": "GTFS",
"gtfs_rt": "GTFS-RT",
"gbfs": "GBFS"
},
"childrenHeading": {
"continents": "Continents",
"countries": "Pays",
"places": "Lieux"
},
"childFeedTotal": "{count, plural, one {<b>#</b> flux} other {<b>#</b> flux}}",
"childrenSearchPlaceholder": "Rechercher un lieu",
"childrenSearchAria": "Filtrer les lieux ci-dessous par nom",
"childLoadingAria": "Chargement de {name}",
"childrenSearchResults": "{count, plural, =0 {Aucun lieu correspondant} one {# lieu correspondant} other {# lieux correspondants}}",
"childrenSearchEmpty": "Aucun lieu ne correspond à « {query} ».",
"feedsHeading": "Flux dans : {place}",
"allFeedsHeading": "Tous les flux",
"resultsRange": "{start}–{end} sur {total} flux",
"noFeeds": "Aucun flux n’est encore répertorié pour ce lieu.",
"paginationAria": "Pages de la liste des flux",
"meta": {
"rootTitle": "Flux de transport par lieu | Mobility Database",
"rootDescription": "Parcourez les flux ouverts de transport et de mobilité GTFS Schedule, GTFS Realtime et GBFS par lieu, des continents jusqu’aux villes.",
"nodeTitle": "Flux de transport : {place} | Mobility Database",
"nodeTitlePaged": "Flux de transport : {place}, page {page} | Mobility Database",
"nodeDescription": "Parcourez {total} flux ouverts de transport et de mobilité situés dans : {place}. {gtfs} GTFS Schedule, {gtfs_rt} GTFS Realtime et {gbfs} GBFS."
}
}
}
99 changes: 99 additions & 0 deletions src/app/[locale]/locations/[[...location]]/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { type ReactElement } from 'react';
import { Box, Container, Skeleton } from '@mui/material';
import SectionContainer from '../../../components/SectionContainer';

const CARD_COUNT = 8;
const ROW_COUNT = 8;

/**
* Shown while a location page streams in, e.g. after clicking a child
* location; same layout as page.tsx so nothing jumps when it resolves.
* ref: https://nextjs.org/docs/app/api-reference/file-conventions/loading
*/
export default function Loading(): ReactElement {
return (
<Container
component='main'
maxWidth='xl'
aria-busy='true'
sx={{ width: '100%', m: 'auto', px: 0 }}
>
<SectionContainer maxWidth='xl'>
{/* Back button and breadcrumb */}
<Skeleton
animation='wave'
variant='text'
sx={{ fontSize: '1rem', width: 240 }}
/>
{/* Title and intro */}
<Skeleton
animation='wave'
variant='text'
sx={{ fontSize: '3rem', width: { xs: '80%', sm: 360 }, mt: 1 }}
/>
<Skeleton
animation='wave'
variant='text'
sx={{ fontSize: '1.2rem', width: { xs: '100%', sm: 560 }, mb: 3 }}
/>
{/* Feed count chips */}
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1 }}>
{[150, 140, 100].map((width) => (
<Skeleton
key={width}
animation='wave'
variant='rounded'
width={width}
height={32}
sx={{ borderRadius: 4 }}
/>
))}
</Box>

{/* Child locations */}
<Skeleton
animation='wave'
variant='text'
sx={{ fontSize: '1.5rem', width: 200, mt: { xs: 4, md: 5 }, mb: 2 }}
/>
<Box
sx={{
display: 'grid',
gridTemplateColumns: {
xs: 'minmax(0, 1fr)',
sm: 'repeat(2, minmax(0, 1fr))',
md: 'repeat(3, minmax(0, 1fr))',
lg: 'repeat(4, minmax(0, 1fr))',
},
gap: 2,
}}
>
{Array.from({ length: CARD_COUNT }, (_, index) => (
<Skeleton
key={index}
animation='wave'
variant='rounded'
height={84}
/>
))}
</Box>

{/* Feeds table */}
<Skeleton
animation='wave'
variant='text'
sx={{ fontSize: '1.5rem', width: 260, mt: { xs: 4, md: 5 }, mb: 2 }}
/>
{Array.from({ length: ROW_COUNT }, (_, index) => (
<Skeleton
key={index}
animation='wave'
variant='rectangular'
height={48}
sx={{ mb: 0.5 }}
/>
))}
</SectionContainer>
</Container>
);
}
Loading
Loading