diff --git a/package.json b/package.json
index e42b156d..fac52329 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,6 @@
"react-hook-form": "^7.52.1",
"react-map-gl": "^8.0.4",
"react-redux": "^8.1.3",
- "react-router-dom": "^6.16.0",
"react-window": "^2.1.2",
"recharts": "^2.12.7",
"redux-persist": "^6.0.0",
@@ -105,7 +104,6 @@
"@types/react-dom": "^19.2.3",
"@types/react-google-recaptcha": "^2.1.8",
"@types/react-redux": "^7.1.27",
- "@types/react-router-dom": "^5.3.3",
"@types/react-window": "^2.0.0",
"@types/redux-saga": "^0.10.5",
"@typescript-eslint/eslint-plugin": "^6.7.0",
diff --git a/src/app/App.css b/src/app/App.css
deleted file mode 100644
index 8d474624..00000000
--- a/src/app/App.css
+++ /dev/null
@@ -1,48 +0,0 @@
-.App {
- text-align: center;
-}
-
-.App-logo {
- height: 40vmin;
- pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
- .App-logo {
- animation: App-logo-spin infinite 20s linear;
- }
-}
-
-.App-header {
- background-color: #282c34;
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: calc(10px + 2vmin);
- color: white;
-}
-
-.App-link {
- color: #61dafb;
-}
-
-@keyframes App-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
-
-
-#app-main-container {
- position: relative;
- /* 100vh - header margin - header - footer - footer padding */
- /* Not perfect, to revisit: for client loading state */
- min-height: calc(100vh - 32px - 64px - 302px - 48px);
-
- box-sizing: border-box;
-}
diff --git a/src/app/App.tsx b/src/app/App.tsx
deleted file mode 100644
index 721ebb0c..00000000
--- a/src/app/App.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-'use client';
-
-import './App.css';
-import AppRouter from './router/Router';
-import { MemoryRouter } from 'react-router-dom';
-import { Suspense } from 'react';
-import { useAuthSession } from './components/AuthSessionProvider';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import AppContainer from './AppContainer';
-import { usePathname, useSearchParams } from 'next/navigation';
-
-interface AppProps {
- locale?: string;
-}
-
-// Helper function to construct the full path from Next.js routing
-function buildPathFromNextRouter(
- pathname: string,
- searchParams: URLSearchParams,
- locale?: string,
-): string {
- const cleanPath =
- locale != null && locale !== 'en'
- ? (pathname.replace(`/${locale}`, '') ?? '/')
- : pathname;
-
- const searchString = searchParams.toString();
- return searchString !== '' ? `${cleanPath}?${searchString}` : cleanPath;
-}
-
-function App({ locale }: AppProps): React.ReactElement {
- const { isAuthReady: isAppReady } = useAuthSession();
-
- const pathname = usePathname();
- const searchParams = useSearchParams();
-
- const initialPath = buildPathFromNextRouter(pathname, searchParams, locale);
-
- return (
-
-
- {/* MemoryRouter will be deprecated in favor of Next AppRouter */}
- {/* MemoryRouter synced with Next.js routing via RouterSync component */}
-
- {isAppReady ? : null}
-
-
-
- );
-}
-
-export default App;
diff --git a/src/app/AppContainer.tsx b/src/app/AppContainer.tsx
deleted file mode 100644
index 3aab16eb..00000000
--- a/src/app/AppContainer.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-'use client';
-
-import * as React from 'react';
-import { Box, LinearProgress } from '@mui/material';
-import type ContextProviderProps from './interface/ContextProviderProps';
-import { usePathname } from 'next/navigation';
-import { selectLoadingApp } from './store/selectors';
-import { useSelector } from 'react-redux';
-
-const AppContainer: React.FC = ({ children }) => {
- const isAppLoading = useSelector(selectLoadingApp);
- const pathname = usePathname();
-
- React.useLayoutEffect(() => {
- window.scrollTo({ top: 0, left: 0, behavior: 'instant' });
- }, [pathname]);
-
- return (
- <>
-
- {isAppLoading ? (
-
-
-
- ) : (
- <>{children}>
- )}
-
- >
- );
-};
-
-export default AppContainer;
diff --git a/src/app/[locale]/[...slug]/page.tsx b/src/app/[locale]/[...slug]/page.tsx
deleted file mode 100644
index 31438948..00000000
--- a/src/app/[locale]/[...slug]/page.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-'use client';
-
-// This page is temporary to ease the migration to Next.js App Router
-// It will be deprecated once the migration is fully complete
-import { type ReactNode, use, useEffect } from 'react';
-import dynamic from 'next/dynamic';
-import { PersistGate } from 'redux-persist/integration/react';
-import { persistor } from '../../store/store';
-import { useAppDispatch } from '../../hooks';
-import { resetProfileErrors } from '../../store/profile-reducer';
-
-const App = dynamic(async () => await import('../../App'), { ssr: false });
-
-interface PageProps {
- params: Promise<{
- locale: string;
- slug: string[];
- }>;
-}
-
-export default function Page({ params }: PageProps): ReactNode {
- const { locale } = use(params);
- const pathKey = use(params).slug?.join('/') ?? '/';
- const dispatch = useAppDispatch();
-
- useEffect(() => {
- // Clean errors from previous session
- dispatch(resetProfileErrors());
- }, [dispatch]);
-
- // Pass locale to App so BrowserRouter can use correct basename
- return (
-
- ;
-
- );
-}
diff --git a/src/app/[locale]/feeds/[feedDataType]/[feedId]/static/layout.tsx b/src/app/[locale]/feeds/[feedDataType]/[feedId]/static/layout.tsx
index d5e52c5f..2beedda2 100644
--- a/src/app/[locale]/feeds/[feedDataType]/[feedId]/static/layout.tsx
+++ b/src/app/[locale]/feeds/[feedDataType]/[feedId]/static/layout.tsx
@@ -22,8 +22,7 @@ interface Props {
* SECURITY: Direct access to /static/ routes is blocked at the proxy level
* (middleware returns 404). This route is only accessible via proxy rewrite
* from the clean URLs like /feeds/gtfs/mdb-123.
- * NOTE: In the future we will use private route `_static` but due to our legacy handler `[...slug]` catching all routes, we need to use a public route and block access at the proxy for now.
- *
+ * TODO: Now that legacy catch-all route is removed, change this to a private route `_static` and update proxy and links accordingly.
*/
export default async function StaticFeedLayout({
children,
diff --git a/src/app/components/AuthBroadcastChannelSync.tsx b/src/app/components/AuthBroadcastChannelSync.tsx
index 3aa7cc4e..0e2db8f4 100644
--- a/src/app/components/AuthBroadcastChannelSync.tsx
+++ b/src/app/components/AuthBroadcastChannelSync.tsx
@@ -13,7 +13,6 @@ import {
/**
* Registers the cross-tab auth broadcast channels once for the App Router tree.
- * This replaces the legacy BrowserRouter-based registration in Router.tsx.
*/
export function AuthBroadcastChannelSync(): ReactElement | null {
const router = useRouter();
diff --git a/src/app/components/Context.tsx b/src/app/components/Context.tsx
index 672f3a59..012972db 100644
--- a/src/app/components/Context.tsx
+++ b/src/app/components/Context.tsx
@@ -8,7 +8,8 @@ import { store } from '../store/store';
/**
* This component is used to wrap the entire application with Redux Provider
* It provides the Redux store to all components in the app
- * IMPORTANT: This does not include the PersistGate, which is used in the page component to delay rendering until the store is rehydrated
+ * IMPORTANT: This does not include the PersistGate, which is applied by
+ * route-level wrappers where delayed rendering is required.
* This allows for a fast initial render, but makes it possible for components to access the store before it's fully rehydrated.
* This also allows for us to have SSG pages that use Redux. It also allows for these pages to be rendered purely in HTML on the server side without waiting for Redux Persist to rehydrate the store.
* Use the `useRehydrated` hook to check rehydration status if needed.
diff --git a/src/app/components/ProtectedPageWrapper.tsx b/src/app/components/ProtectedPageWrapper.tsx
index 8de3a825..9b8b2c35 100644
--- a/src/app/components/ProtectedPageWrapper.tsx
+++ b/src/app/components/ProtectedPageWrapper.tsx
@@ -1,7 +1,7 @@
'use client';
-// TODO: Once the [...slug] catch-all route is removed, replace this wrapper
-// with a (protected) route group layout that provides auth guarding at the layout level.
+// TODO: Replace this wrapper with a (protected) route group layout that
+// provides auth guarding at the layout level.
// targetStatus can be used to scope groups further (e.g. (authenticated), (unverified)).
import { useEffect } from 'react';
import { useSelector } from 'react-redux';
diff --git a/src/app/components/ReduxGateWrapper.tsx b/src/app/components/ReduxGateWrapper.tsx
index b4b8b5b6..c800de9e 100644
--- a/src/app/components/ReduxGateWrapper.tsx
+++ b/src/app/components/ReduxGateWrapper.tsx
@@ -1,7 +1,7 @@
'use client';
-// TODO: Once the [...slug] catch-all route is removed, replace this wrapper
-// with a (store) route group layout that provides PersistGate at the layout level.
+// TODO: Replace this wrapper with a (store) route group layout that provides
+// PersistGate at the layout level.
import { Suspense } from 'react';
import { PersistGate } from 'redux-persist/integration/react';
import { persistor } from '../store/store';
diff --git a/src/app/router/Router.tsx b/src/app/router/Router.tsx
deleted file mode 100644
index 1a12816b..00000000
--- a/src/app/router/Router.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import type React from 'react';
-
-export const AppRouter: React.FC = () => null;
-
-export default AppRouter;
diff --git a/src/app/screens/Feeds/SearchTable.spec.tsx b/src/app/screens/Feeds/SearchTable.spec.tsx
index 53453aae..1ae29840 100644
--- a/src/app/screens/Feeds/SearchTable.spec.tsx
+++ b/src/app/screens/Feeds/SearchTable.spec.tsx
@@ -1,6 +1,5 @@
import SearchTable, { getDataTypeElement } from './SearchTable';
import { render, cleanup, screen, within } from '@testing-library/react';
-import { MemoryRouter } from 'react-router-dom';
import { type AllFeedsType } from '../../services/feeds/utils';
import { ThemeProvider } from '@mui/material/styles';
import { theme } from '../../Theme';
@@ -140,15 +139,13 @@ const mockFeedsData: AllFeedsType = {
],
};
-describe.only('getProviderElement', () => {
+describe('getProviderElement', () => {
afterEach(cleanup);
it('should display the correct number of transit providers in table row', () => {
render(
-
-
-
+
,
);
diff --git a/src/app/store/saga/auth-saga.ts b/src/app/store/saga/auth-saga.ts
index 295659e5..7a65177a 100644
--- a/src/app/store/saga/auth-saga.ts
+++ b/src/app/store/saga/auth-saga.ts
@@ -98,8 +98,7 @@ function* logoutSaga({
try {
broadcastMessage(LOGOUT_CHANNEL);
} catch {
- // Broadcast channels may not be initialised if no
- // legacy [...slug] page has been rendered yet.
+ // Broadcast channels may not be initialised yet.
}
}
navigateTo(redirectScreen);
diff --git a/src/app/store/store.ts b/src/app/store/store.ts
index a7163721..be329deb 100644
--- a/src/app/store/store.ts
+++ b/src/app/store/store.ts
@@ -85,8 +85,7 @@ if (typeof window !== 'undefined' && (window as any).Cypress) {
sagaMiddleware.run(rootSaga);
// Create the persistor at the store level so rehydration and
-// state-persistence happen on every page load, not just on the
-// legacy catch-all route.
+// state-persistence can be shared by route-level gate wrappers.
export const persistor = persistStore(store);
export type RootState = ReturnType;
diff --git a/src/proxy.ts b/src/proxy.ts
index 088be3a8..2bfbf3c7 100644
--- a/src/proxy.ts
+++ b/src/proxy.ts
@@ -10,11 +10,6 @@ import {
DEFAULT_LOCALE,
} from './app/utils/proxy-helpers';
-/**
- * IMPORTANT: The logic of this proxy will be tested once the [...slug] route is removed
- * Reasoning: [...slug] will catch all routes including those with wrong locale prefixes
- */
-
/**
* Internationalization and auth-routing proxy following the Next.js i18n guide.
* @see https://nextjs.org/docs/app/guides/internationalization
diff --git a/yarn.lock b/yarn.lock
index 2e1c9eb7..b234dbb3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3006,11 +3006,6 @@
redux-thunk "^2.4.2"
reselect "^4.1.8"
-"@remix-run/router@1.23.2":
- version "1.23.2"
- resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.23.2.tgz#156c4b481c0bee22a19f7924728a67120de06971"
- integrity sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==
-
"@rollup/plugin-commonjs@28.0.1":
version "28.0.1"
resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.1.tgz#e2138e31cc0637676dc3d5cae7739131f7cd565e"
@@ -3817,11 +3812,6 @@
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a"
integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==
-"@types/history@^4.7.11":
- version "4.7.11"
- resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64"
- integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==
-
"@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@^3.3.1":
version "3.3.7"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz#306e3a3a73828522efa1341159da4846e7573a6c"
@@ -4016,23 +4006,6 @@
hoist-non-react-statics "^3.3.0"
redux "^4.0.0"
-"@types/react-router-dom@^5.3.3":
- version "5.3.3"
- resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83"
- integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==
- dependencies:
- "@types/history" "^4.7.11"
- "@types/react" "*"
- "@types/react-router" "*"
-
-"@types/react-router@*":
- version "5.1.20"
- resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.20.tgz#88eccaa122a82405ef3efbcaaa5dcdd9f021387c"
- integrity sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==
- dependencies:
- "@types/history" "^4.7.11"
- "@types/react" "*"
-
"@types/react-transition-group@^4.4.12":
version "4.4.12"
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.12.tgz#b5d76568485b02a307238270bfe96cb51ee2a044"
@@ -11447,21 +11420,6 @@ react-redux@^8.1.3:
react-is "^18.0.0"
use-sync-external-store "^1.0.0"
-react-router-dom@^6.16.0:
- version "6.30.3"
- resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.30.3.tgz#42ae6dc4c7158bfb0b935f162b9621b29dddf740"
- integrity sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==
- dependencies:
- "@remix-run/router" "1.23.2"
- react-router "6.30.3"
-
-react-router@6.30.3:
- version "6.30.3"
- resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.30.3.tgz#994b3ccdbe0e81fe84d4f998100f62584dfbf1cf"
- integrity sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==
- dependencies:
- "@remix-run/router" "1.23.2"
-
react-smooth@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-4.0.4.tgz#a5875f8bb61963ca61b819cedc569dc2453894b4"