From 6c63a9bb602e932f96519fed67ddc850d967d449 Mon Sep 17 00:00:00 2001 From: Maurice <61554723+mauriceboe@users.noreply.github.com> Date: Thu, 6 Aug 2026 23:01:58 +0200 Subject: [PATCH] fix(client): move to react-router 7.18.2 (#1804) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(client): opt into the v7 router behaviour while still on v6 Turning the behaviour on separately from the version bump keeps the two failure modes apart: red here means a behaviour change, red on the bump means the import rewrite. The suite is unchanged either way — 527 files, 11099 tests. Only the two flags a non-data router understands are set; the rest belong to createBrowserRouter, which this app doesn't use. Both are applied at all six router mounts, so the tests exercise the same behaviour as production rather than validating v6 while prod runs v7. * fix(client): move to react-router 7.18.2 6.30.4 is affected by GHSA-wrjc-x8rr-h8h6 — open redirect through a backslash in Link and useNavigate, which this app uses in 41 places — and the 6.x line has no fix: react-router-dom 6.30.2 to 6.30.4 carries GHSA-jjmj-jmhj-qwj2 with no patched version at all. Staying is not an option, and 7.0 to 7.17 only swaps it for GHSA-chx6-hx7r-mcp5. The package rename comes with it: react-router-dom is a re-export shim in v7, so using it would only defer the same rewrite to the v8 jump. 77 occurrences across 60 files, all of them import specifiers and vi.mock strings. The surface is small — useNavigate, useParams, useSearchParams, useLocation, Routes, Route, Link, Navigate, useMatch, MemoryRouter, BrowserRouter — no data router, no loaders or actions. Nothing else had to change; the future flags from the previous commit are simply how v7 behaves, so they come back out. npm audit still reports GHSA-qwww-vcr4-c8h2 on react-router (RSC mode CSRF, fixed in 8.3.0). It needs RSC mode, which needs a server; this is a static SPA. Closing it means the v8 major, which is its own piece of work. --- client/package.json | 2 +- client/src/App.test.tsx | 2 +- client/src/App.tsx | 2 +- .../BackgroundTasksWidget.extra.test.tsx | 4 +- .../BackgroundTasks/BackgroundTasksWidget.tsx | 2 +- client/src/components/Budget/CostsPanel.tsx | 2 +- .../MSaveToCollectionSheet.test.tsx | 4 +- .../Collections/MSaveToCollectionSheet.tsx | 2 +- .../SaveToCollectionModal.test.tsx | 4 +- .../Collections/SaveToCollectionModal.tsx | 2 +- .../Dashboard/CollectionsWidget.tsx | 2 +- .../JourneyDetailPageSettingsDialog.test.tsx | 4 +- .../JourneyDetailPageSettingsDialog.tsx | 2 +- .../src/components/Layout/BottomNav.test.tsx | 4 +- client/src/components/Layout/BottomNav.tsx | 2 +- .../Layout/InAppNotificationBell.tsx | 2 +- .../components/Layout/MobileTopBar.test.tsx | 4 +- client/src/components/Layout/MobileTopBar.tsx | 2 +- client/src/components/Layout/Navbar.tsx | 2 +- .../Notifications/InAppNotificationItem.tsx | 2 +- .../Planner/ReservationModal.test.tsx | 6 +- .../components/Planner/ReservationModal.tsx | 2 +- .../Planner/TransportModal.test.tsx | 4 +- .../src/components/Planner/TransportModal.tsx | 2 +- .../components/Plugins/PluginFrame.test.tsx | 2 +- client/src/components/Plugins/PluginFrame.tsx | 2 +- client/src/components/Settings/AccountTab.tsx | 2 +- .../components/Settings/NotificationsTab.tsx | 2 +- .../SystemNoticeBanner.extra.test.tsx | 4 +- .../SystemNotices/SystemNoticeBanner.tsx | 2 +- .../SystemNotices/SystemNoticeModal.test.tsx | 4 +- .../SystemNotices/SystemNoticeModal.tsx | 2 +- .../SystemNotices/noticeActions.test.ts | 2 +- .../components/SystemNotices/noticeActions.ts | 2 +- client/src/main.tsx | 2 +- client/src/mobile/MobileShell.tsx | 2 +- client/src/mobile/components/MBottomNav.tsx | 2 +- client/src/mobile/screens/atlas/MAtlas.tsx | 2 +- .../screens/collections/MCollections.tsx | 2 +- .../mobile/screens/dashboard/MDashWidgets.tsx | 2 +- .../mobile/screens/dashboard/MUserMenu.tsx | 2 +- .../screens/journey/MJourneySettingsSheet.tsx | 2 +- .../notifications/MNotificationRow.tsx | 2 +- .../screens/notifications/MNotifications.tsx | 2 +- .../src/mobile/screens/settings/MSettings.tsx | 2 +- .../screens/settings/MSettingsAccount.tsx | 2 +- .../settings/MSettingsNotifications.tsx | 2 +- client/src/mobile/screens/vacay/useMVacay.ts | 2 +- client/src/pages/FilesPage.test.tsx | 2 +- client/src/pages/FilesPage.tsx | 2 +- client/src/pages/HelpPage.tsx | 2 +- client/src/pages/JourneyDetailPage.test.tsx | 4 +- client/src/pages/JourneyPage.test.tsx | 4 +- client/src/pages/JourneyPublicPage.test.tsx | 6 +- .../pages/LoginPage.oidc-redirect.test.tsx | 4 +- client/src/pages/PluginPage.tsx | 2 +- client/src/pages/SharedTripPage.test.tsx | 2 +- client/src/pages/TripPlannerPage.test.tsx | 2 +- client/src/pages/TripPlannerPage.tsx | 2 +- client/src/pages/admin/useAdmin.test.tsx | 2 +- client/src/pages/admin/useAdmin.ts | 2 +- client/src/pages/atlas/useAtlas.ts | 2 +- .../pages/collections/useCollections.test.tsx | 2 +- .../src/pages/collections/useCollections.ts | 2 +- .../src/pages/dashboard/useDashboard.test.tsx | 2 +- client/src/pages/dashboard/useDashboard.ts | 2 +- client/src/pages/files/useFiles.ts | 2 +- .../forgotPassword/useForgotPassword.test.ts | 2 +- .../pages/forgotPassword/useForgotPassword.ts | 2 +- client/src/pages/help/useHelp.test.ts | 2 +- client/src/pages/help/useHelp.ts | 2 +- client/src/pages/join/useJoinTrip.test.ts | 2 +- client/src/pages/join/useJoinTrip.ts | 2 +- client/src/pages/journey/useJourney.ts | 2 +- .../journeyDetail/useJourneyDetail.test.tsx | 6 +- .../pages/journeyDetail/useJourneyDetail.ts | 2 +- .../pages/journeyPublic/useJourneyPublic.ts | 2 +- client/src/pages/login/useLogin.test.tsx | 6 +- client/src/pages/login/useLogin.ts | 2 +- .../resetPassword/useResetPassword.test.ts | 2 +- .../pages/resetPassword/useResetPassword.ts | 2 +- client/src/pages/settings/useSettings.ts | 2 +- client/src/pages/sharedTrip/useSharedTrip.ts | 2 +- .../pages/tripPlanner/useTripPlanner.test.tsx | 2 +- .../src/pages/tripPlanner/useTripPlanner.ts | 2 +- client/tests/helpers/render.tsx | 2 +- client/tests/unit/mobile/MBottomNav.test.tsx | 2 +- .../tests/unit/mobile/admin/MAdmin.test.tsx | 2 +- .../mobile/dashboard/MDashWidgets.test.tsx | 2 +- .../journey/MJourneySettingsSheet.test.tsx | 4 +- .../mobile/settings/MSettingsAccount.test.tsx | 4 +- .../settings/MSettingsNotifications.test.tsx | 2 +- .../unit/mobile/vacay/useMVacay.test.tsx | 4 +- package-lock.json | 84 +++++++++---------- 94 files changed, 158 insertions(+), 158 deletions(-) diff --git a/client/package.json b/client/package.json index 5881a24d8..06f600acd 100644 --- a/client/package.json +++ b/client/package.json @@ -50,7 +50,7 @@ "react-leaflet": "^5.0.0", "react-leaflet-cluster": "^4.1.3", "react-markdown": "^10.1.0", - "react-router-dom": "^6.22.2", + "react-router": "^7.18.2", "rehype-sanitize": "^6.0.0", "remark-breaks": "^4.0.0", "remark-gfm": "^4.0.1", diff --git a/client/src/App.test.tsx b/client/src/App.test.tsx index 9062f7938..610bd05dd 100644 --- a/client/src/App.test.tsx +++ b/client/src/App.test.tsx @@ -1,6 +1,6 @@ import React from 'react' import { render, screen, waitFor } from '@testing-library/react' -import { MemoryRouter } from 'react-router-dom' +import { MemoryRouter } from 'react-router' import { describe, it, expect, beforeEach, vi } from 'vitest' import { http, HttpResponse } from 'msw' import { server } from '../tests/helpers/msw/server' diff --git a/client/src/App.tsx b/client/src/App.tsx index d73be86a7..4e01bb20c 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,5 +1,5 @@ import React, { useEffect, ReactNode } from 'react' -import { Routes, Route, Navigate, useLocation } from 'react-router-dom' +import { Routes, Route, Navigate, useLocation } from 'react-router' import { useAuthStore } from './store/authStore' import { useSettingsStore } from './store/settingsStore' import { applyAppearance } from './theme/applyAppearance' diff --git a/client/src/components/BackgroundTasks/BackgroundTasksWidget.extra.test.tsx b/client/src/components/BackgroundTasks/BackgroundTasksWidget.extra.test.tsx index 6b708ba38..b9ffcf8eb 100644 --- a/client/src/components/BackgroundTasks/BackgroundTasksWidget.extra.test.tsx +++ b/client/src/components/BackgroundTasks/BackgroundTasksWidget.extra.test.tsx @@ -8,8 +8,8 @@ import { useBackgroundTasksStore, type BackgroundImportTask } from '../../store/ import BackgroundTasksWidget from './BackgroundTasksWidget' const navigate = vi.fn() -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom') +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router') return { ...actual, useNavigate: () => navigate } }) vi.mock('../../api/websocket', () => ({ addListener: vi.fn(), removeListener: vi.fn() })) diff --git a/client/src/components/BackgroundTasks/BackgroundTasksWidget.tsx b/client/src/components/BackgroundTasks/BackgroundTasksWidget.tsx index 980fd633c..062841c78 100644 --- a/client/src/components/BackgroundTasks/BackgroundTasksWidget.tsx +++ b/client/src/components/BackgroundTasks/BackgroundTasksWidget.tsx @@ -1,6 +1,6 @@ import ReactDOM from 'react-dom' import { useEffect, useRef, useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { Loader2, CheckCircle2, AlertCircle, X } from 'lucide-react' import { useTranslation } from '../../i18n' import { addListener, removeListener } from '../../api/websocket' diff --git a/client/src/components/Budget/CostsPanel.tsx b/client/src/components/Budget/CostsPanel.tsx index 9eb5183d8..e9262393f 100644 --- a/client/src/components/Budget/CostsPanel.tsx +++ b/client/src/components/Budget/CostsPanel.tsx @@ -1,5 +1,5 @@ import { useState, useEffect, useMemo, useCallback } from 'react' -import { useSearchParams } from 'react-router-dom' +import { useSearchParams } from 'react-router' import { ArrowDown, ArrowUp, BarChart3, Plus, Search, ArrowRight, ArrowLeftRight, Check, RotateCcw, Pencil, Trash2, AlertCircle, Download } from 'lucide-react' import { useTripStore } from '../../store/tripStore' import { useAuthStore } from '../../store/authStore' diff --git a/client/src/components/Collections/MSaveToCollectionSheet.test.tsx b/client/src/components/Collections/MSaveToCollectionSheet.test.tsx index f45983261..19b2940d4 100644 --- a/client/src/components/Collections/MSaveToCollectionSheet.test.tsx +++ b/client/src/components/Collections/MSaveToCollectionSheet.test.tsx @@ -9,8 +9,8 @@ import type { SaveToCollectionTarget } from '../../store/saveToCollectionStore'; import MSaveToCollectionSheet from './MSaveToCollectionSheet'; const mockNavigate = vi.fn(); -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useNavigate: () => mockNavigate }; }); diff --git a/client/src/components/Collections/MSaveToCollectionSheet.tsx b/client/src/components/Collections/MSaveToCollectionSheet.tsx index 621e2b0ce..b5ddadf76 100644 --- a/client/src/components/Collections/MSaveToCollectionSheet.tsx +++ b/client/src/components/Collections/MSaveToCollectionSheet.tsx @@ -1,5 +1,5 @@ import { useEffect, useMemo, useState, useCallback } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { Bookmark, BookmarkCheck, Check, Loader2, Plus, X } from 'lucide-react' import MSheet from '../../mobile/components/MSheet' import MIconBtn from '../../mobile/components/MIconBtn' diff --git a/client/src/components/Collections/SaveToCollectionModal.test.tsx b/client/src/components/Collections/SaveToCollectionModal.test.tsx index e3487b8cc..97e0ae248 100644 --- a/client/src/components/Collections/SaveToCollectionModal.test.tsx +++ b/client/src/components/Collections/SaveToCollectionModal.test.tsx @@ -9,8 +9,8 @@ import type { SaveToCollectionTarget } from '../../store/saveToCollectionStore'; import SaveToCollectionModal from './SaveToCollectionModal'; const mockNavigate = vi.fn(); -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useNavigate: () => mockNavigate }; }); diff --git a/client/src/components/Collections/SaveToCollectionModal.tsx b/client/src/components/Collections/SaveToCollectionModal.tsx index 77d3bc476..ed06ac991 100644 --- a/client/src/components/Collections/SaveToCollectionModal.tsx +++ b/client/src/components/Collections/SaveToCollectionModal.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useMemo, useState, useCallback } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { Bookmark, BookmarkCheck, Check, Loader2, Plus } from 'lucide-react' import Modal from '../shared/Modal' import { useToast } from '../shared/Toast' diff --git a/client/src/components/Dashboard/CollectionsWidget.tsx b/client/src/components/Dashboard/CollectionsWidget.tsx index 7cf9af9d2..e71ce152a 100644 --- a/client/src/components/Dashboard/CollectionsWidget.tsx +++ b/client/src/components/Dashboard/CollectionsWidget.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react' import { Bookmark, ArrowRight, MapPin } from 'lucide-react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { useTranslation } from '../../i18n' import { collectionsApi } from '../../api/collections' import { entityGradient } from '../../utils/gradients' diff --git a/client/src/components/Journey/JourneyDetailPageSettingsDialog.test.tsx b/client/src/components/Journey/JourneyDetailPageSettingsDialog.test.tsx index 481063e24..e65da098f 100644 --- a/client/src/components/Journey/JourneyDetailPageSettingsDialog.test.tsx +++ b/client/src/components/Journey/JourneyDetailPageSettingsDialog.test.tsx @@ -11,8 +11,8 @@ import { JourneySettingsDialog } from './JourneyDetailPageSettingsDialog' type ToastKind = 'success' | 'error' | 'warning' | 'info' const mockNavigate = vi.fn() -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom') +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router') return { ...actual, useNavigate: () => mockNavigate } }) diff --git a/client/src/components/Journey/JourneyDetailPageSettingsDialog.tsx b/client/src/components/Journey/JourneyDetailPageSettingsDialog.tsx index 22f893045..c79772298 100644 --- a/client/src/components/Journey/JourneyDetailPageSettingsDialog.tsx +++ b/client/src/components/Journey/JourneyDetailPageSettingsDialog.tsx @@ -1,5 +1,5 @@ import { useState, useRef } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { X, ImagePlus, Plus, Trash2, UserPlus, Archive, ArchiveRestore } from 'lucide-react' import { useJourneyStore } from '../../store/journeyStore' import { useTranslation } from '../../i18n' diff --git a/client/src/components/Layout/BottomNav.test.tsx b/client/src/components/Layout/BottomNav.test.tsx index a4d751f45..ad20d4bd1 100644 --- a/client/src/components/Layout/BottomNav.test.tsx +++ b/client/src/components/Layout/BottomNav.test.tsx @@ -11,8 +11,8 @@ vi.mock('../../api/websocket', () => ({ })); const mockNavigate = vi.fn(); -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useNavigate: () => mockNavigate }; }); diff --git a/client/src/components/Layout/BottomNav.tsx b/client/src/components/Layout/BottomNav.tsx index 3d318571f..182f1b148 100644 --- a/client/src/components/Layout/BottomNav.tsx +++ b/client/src/components/Layout/BottomNav.tsx @@ -1,4 +1,4 @@ -import { useNavigate, useLocation, useMatch } from 'react-router-dom' +import { useNavigate, useLocation, useMatch } from 'react-router' import { useAddonStore } from '../../store/addonStore' import { usePluginStore } from '../../store/pluginStore' import { useSettingsStore } from '../../store/settingsStore' diff --git a/client/src/components/Layout/InAppNotificationBell.tsx b/client/src/components/Layout/InAppNotificationBell.tsx index fff567696..680cd64b1 100644 --- a/client/src/components/Layout/InAppNotificationBell.tsx +++ b/client/src/components/Layout/InAppNotificationBell.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react' import ReactDOM from 'react-dom' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { Bell, Trash2, CheckCheck } from 'lucide-react' import { useTranslation } from '../../i18n' import { useInAppNotificationStore } from '../../store/inAppNotificationStore.ts' diff --git a/client/src/components/Layout/MobileTopBar.test.tsx b/client/src/components/Layout/MobileTopBar.test.tsx index c556f62f1..1782caf23 100644 --- a/client/src/components/Layout/MobileTopBar.test.tsx +++ b/client/src/components/Layout/MobileTopBar.test.tsx @@ -3,8 +3,8 @@ vi.mock('./InAppNotificationBell', () => ({ default: () => null })); const mockNavigate = vi.fn(); -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useNavigate: () => mockNavigate }; }); diff --git a/client/src/components/Layout/MobileTopBar.tsx b/client/src/components/Layout/MobileTopBar.tsx index 89a899151..4c8851974 100644 --- a/client/src/components/Layout/MobileTopBar.tsx +++ b/client/src/components/Layout/MobileTopBar.tsx @@ -1,6 +1,6 @@ import { useState, useEffect } from 'react' import { createPortal } from 'react-dom' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { useAuthStore } from '../../store/authStore' import { useInAppNotificationStore } from '../../store/inAppNotificationStore' import { useTranslation } from '../../i18n' diff --git a/client/src/components/Layout/Navbar.tsx b/client/src/components/Layout/Navbar.tsx index 02e0b03bf..fd82ceb5f 100644 --- a/client/src/components/Layout/Navbar.tsx +++ b/client/src/components/Layout/Navbar.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef } from 'react' import ReactDOM from 'react-dom' -import { Link, useNavigate, useLocation } from 'react-router-dom' +import { Link, useNavigate, useLocation } from 'react-router' import { useAuthStore } from '../../store/authStore' import { useSettingsStore } from '../../store/settingsStore' import { useAddonStore } from '../../store/addonStore' diff --git a/client/src/components/Notifications/InAppNotificationItem.tsx b/client/src/components/Notifications/InAppNotificationItem.tsx index 074558b97..369af6cdc 100644 --- a/client/src/components/Notifications/InAppNotificationItem.tsx +++ b/client/src/components/Notifications/InAppNotificationItem.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { User, Check, X, ArrowRight, Trash2, CheckCheck } from 'lucide-react' import { useTranslation } from '../../i18n' import { useInAppNotificationStore, InAppNotification } from '../../store/inAppNotificationStore' diff --git a/client/src/components/Planner/ReservationModal.test.tsx b/client/src/components/Planner/ReservationModal.test.tsx index 06633fb32..62e51f2f8 100644 --- a/client/src/components/Planner/ReservationModal.test.tsx +++ b/client/src/components/Planner/ReservationModal.test.tsx @@ -20,9 +20,9 @@ import { ReservationModal } from './ReservationModal'; import type { BookingReviewDraft } from './parsedItemToDraft'; import type { TripMember } from '../Budget/BudgetPanelMemberChips'; -// Mock react-router-dom useParams -vi.mock('react-router-dom', async (importActual) => { - const actual = await importActual(); +// Mock react-router useParams +vi.mock('react-router', async (importActual) => { + const actual = await importActual(); return { ...actual, useParams: () => ({ id: '1' }) }; }); diff --git a/client/src/components/Planner/ReservationModal.tsx b/client/src/components/Planner/ReservationModal.tsx index 8163dfde7..afdce5911 100644 --- a/client/src/components/Planner/ReservationModal.tsx +++ b/client/src/components/Planner/ReservationModal.tsx @@ -1,5 +1,5 @@ import { useState, useEffect, useRef, useMemo } from 'react' -import { useParams } from 'react-router-dom' +import { useParams } from 'react-router' import apiClient from '../../api/client' import { useTripStore } from '../../store/tripStore' import { useAddonStore } from '../../store/addonStore' diff --git a/client/src/components/Planner/TransportModal.test.tsx b/client/src/components/Planner/TransportModal.test.tsx index 9f6ca6fd2..b519daa08 100644 --- a/client/src/components/Planner/TransportModal.test.tsx +++ b/client/src/components/Planner/TransportModal.test.tsx @@ -21,8 +21,8 @@ import type { Day, Reservation } from '../../types'; import type { BookingReviewDraft } from './parsedItemToDraft'; import type { TripMember } from '../Budget/BudgetPanelMemberChips'; -vi.mock('react-router-dom', async (importActual) => { - const actual = await importActual(); +vi.mock('react-router', async (importActual) => { + const actual = await importActual(); return { ...actual, useParams: () => ({ id: '1' }) }; }); diff --git a/client/src/components/Planner/TransportModal.tsx b/client/src/components/Planner/TransportModal.tsx index 9dadfb963..6ccc3b175 100644 --- a/client/src/components/Planner/TransportModal.tsx +++ b/client/src/components/Planner/TransportModal.tsx @@ -1,5 +1,5 @@ import { useState, useEffect, useRef } from 'react' -import { useParams } from 'react-router-dom' +import { useParams } from 'react-router' import { Plane, Train, Car, Ship, Bus, Sailboat, Bike, CarTaxiFront, Route, TramFront, Paperclip, FileText, X, ExternalLink, Link2, Plus, Trash2 } from 'lucide-react' import Modal from '../shared/Modal' import CustomSelect from '../shared/CustomSelect' diff --git a/client/src/components/Plugins/PluginFrame.test.tsx b/client/src/components/Plugins/PluginFrame.test.tsx index ceca9c4ea..9aea91891 100644 --- a/client/src/components/Plugins/PluginFrame.test.tsx +++ b/client/src/components/Plugins/PluginFrame.test.tsx @@ -18,7 +18,7 @@ const host = vi.hoisted(() => ({ trip: null as Record | null, })); -vi.mock('react-router-dom', () => ({ useNavigate: () => navigate })); +vi.mock('react-router', () => ({ useNavigate: () => navigate })); vi.mock('../shared/Toast', () => ({ useToast: () => toast })); vi.mock('../../i18n', () => ({ useTranslation: () => ({ locale: 'en', t: (k: string) => k }) })); vi.mock('../../store/authStore', () => ({ useAuthStore: (sel: (s: unknown) => unknown) => sel({ user: host.user }) })); diff --git a/client/src/components/Plugins/PluginFrame.tsx b/client/src/components/Plugins/PluginFrame.tsx index 582a2c0ba..56a62a5e0 100644 --- a/client/src/components/Plugins/PluginFrame.tsx +++ b/client/src/components/Plugins/PluginFrame.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useRef, useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { useTranslation } from '../../i18n' import { useAuthStore } from '../../store/authStore' import { useSettingsStore } from '../../store/settingsStore' diff --git a/client/src/components/Settings/AccountTab.tsx b/client/src/components/Settings/AccountTab.tsx index 59c601394..e9a2488b6 100644 --- a/client/src/components/Settings/AccountTab.tsx +++ b/client/src/components/Settings/AccountTab.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from 'react' import { User, Save, Lock, KeyRound, AlertTriangle, Shield, Camera, Trash2, Copy, Download, Printer } from 'lucide-react' -import { useNavigate, useSearchParams } from 'react-router-dom' +import { useNavigate, useSearchParams } from 'react-router' import { useTranslation } from '../../i18n' import { useAuthStore } from '../../store/authStore' import { useToast } from '../shared/Toast' diff --git a/client/src/components/Settings/NotificationsTab.tsx b/client/src/components/Settings/NotificationsTab.tsx index 35f0d22f0..56d34ca39 100644 --- a/client/src/components/Settings/NotificationsTab.tsx +++ b/client/src/components/Settings/NotificationsTab.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react' -import { Link } from 'react-router-dom' +import { Link } from 'react-router' import { Lock } from 'lucide-react' import { useTranslation } from '../../i18n' import { notificationsApi, settingsApi } from '../../api/client' diff --git a/client/src/components/SystemNotices/SystemNoticeBanner.extra.test.tsx b/client/src/components/SystemNotices/SystemNoticeBanner.extra.test.tsx index 14efa10a6..19c0c1d23 100644 --- a/client/src/components/SystemNotices/SystemNoticeBanner.extra.test.tsx +++ b/client/src/components/SystemNotices/SystemNoticeBanner.extra.test.tsx @@ -7,8 +7,8 @@ import { registerNoticeAction } from './noticeActions' import { BannerRenderer, ToastRenderer } from './SystemNoticeBanner' const navigate = vi.fn() -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom') +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router') return { ...actual, useNavigate: () => navigate } }) diff --git a/client/src/components/SystemNotices/SystemNoticeBanner.tsx b/client/src/components/SystemNotices/SystemNoticeBanner.tsx index 5bfb41774..98551f57f 100644 --- a/client/src/components/SystemNotices/SystemNoticeBanner.tsx +++ b/client/src/components/SystemNotices/SystemNoticeBanner.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect, useRef } from 'react'; -import { useNavigate } from 'react-router-dom'; +import { useNavigate } from 'react-router'; import { Info, AlertTriangle, AlertOctagon, X } from 'lucide-react'; import { useSystemNoticeStore } from '../../store/systemNoticeStore.js'; import type { SystemNoticeDTO } from '../../store/systemNoticeStore.js'; diff --git a/client/src/components/SystemNotices/SystemNoticeModal.test.tsx b/client/src/components/SystemNotices/SystemNoticeModal.test.tsx index 74ac18938..5e9f1d766 100644 --- a/client/src/components/SystemNotices/SystemNoticeModal.test.tsx +++ b/client/src/components/SystemNotices/SystemNoticeModal.test.tsx @@ -10,8 +10,8 @@ import { ModalRenderer } from './SystemNoticeModal'; import type { SystemNoticeDTO } from '../../store/systemNoticeStore'; const routerMocks = vi.hoisted(() => ({ navigate: vi.fn((_to: string) => {}) })); -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useNavigate: () => routerMocks.navigate }; }); diff --git a/client/src/components/SystemNotices/SystemNoticeModal.tsx b/client/src/components/SystemNotices/SystemNoticeModal.tsx index 293f247f2..34b058e62 100644 --- a/client/src/components/SystemNotices/SystemNoticeModal.tsx +++ b/client/src/components/SystemNotices/SystemNoticeModal.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef } from 'react'; import { flushSync } from 'react-dom'; -import { useNavigate } from 'react-router-dom'; +import { useNavigate } from 'react-router'; import { Info, AlertTriangle, AlertOctagon, X, ChevronLeft, ChevronRight, Coffee } from 'lucide-react'; import * as LucideIcons from 'lucide-react'; import remarkGfm from 'remark-gfm'; diff --git a/client/src/components/SystemNotices/noticeActions.test.ts b/client/src/components/SystemNotices/noticeActions.test.ts index 75259a876..778521af6 100644 --- a/client/src/components/SystemNotices/noticeActions.test.ts +++ b/client/src/components/SystemNotices/noticeActions.test.ts @@ -1,6 +1,6 @@ // FE-W4SNA-001 to FE-W4SNA-005 import { describe, it, expect, vi, afterEach } from 'vitest' -import type { NavigateFunction } from 'react-router-dom' +import type { NavigateFunction } from 'react-router' import { registerNoticeAction, runNoticeAction } from './noticeActions' const navigate = vi.fn() as unknown as NavigateFunction diff --git a/client/src/components/SystemNotices/noticeActions.ts b/client/src/components/SystemNotices/noticeActions.ts index 1369bdb90..0a46a9c82 100644 --- a/client/src/components/SystemNotices/noticeActions.ts +++ b/client/src/components/SystemNotices/noticeActions.ts @@ -1,4 +1,4 @@ -import type { NavigateFunction } from 'react-router-dom'; +import type { NavigateFunction } from 'react-router'; export interface NoticeActionContext { navigate: NavigateFunction; diff --git a/client/src/main.tsx b/client/src/main.tsx index 60cea2ff8..d5dca1a7d 100644 --- a/client/src/main.tsx +++ b/client/src/main.tsx @@ -1,6 +1,6 @@ import React from 'react' import ReactDOM from 'react-dom/client' -import { BrowserRouter } from 'react-router-dom' +import { BrowserRouter } from 'react-router' import App from './App' // Self-hosted Poppins (bundled, same-origin) so the app font can't be blocked by // ad/tracker blockers the way the Google Fonts CDN can. diff --git a/client/src/mobile/MobileShell.tsx b/client/src/mobile/MobileShell.tsx index 0642676c1..fc1bfd7e3 100644 --- a/client/src/mobile/MobileShell.tsx +++ b/client/src/mobile/MobileShell.tsx @@ -1,5 +1,5 @@ import { ReactNode } from 'react' -import { useMatch } from 'react-router-dom' +import { useMatch } from 'react-router' import BottomNav from '../components/Layout/BottomNav' import MBottomNav from './components/MBottomNav' import MToastHost from './components/MToastHost' diff --git a/client/src/mobile/components/MBottomNav.tsx b/client/src/mobile/components/MBottomNav.tsx index 460ce5b43..5c1538975 100644 --- a/client/src/mobile/components/MBottomNav.tsx +++ b/client/src/mobile/components/MBottomNav.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react' -import { useNavigate, useLocation, useMatch } from 'react-router-dom' +import { useNavigate, useLocation, useMatch } from 'react-router' import { useSettingsStore } from '../../store/settingsStore' import { useTranslation } from '../../i18n' import { ChevronRight, MoreHorizontal, Plus, Search } from 'lucide-react' diff --git a/client/src/mobile/screens/atlas/MAtlas.tsx b/client/src/mobile/screens/atlas/MAtlas.tsx index afddbf044..19c589d53 100644 --- a/client/src/mobile/screens/atlas/MAtlas.tsx +++ b/client/src/mobile/screens/atlas/MAtlas.tsx @@ -1,5 +1,5 @@ import { useEffect, useMemo, useState } from 'react' -import { useSearchParams } from 'react-router-dom' +import { useSearchParams } from 'react-router' import { X } from 'lucide-react' import { useAtlas } from '../../../pages/atlas/useAtlas' import MIconBtn from '../../components/MIconBtn' diff --git a/client/src/mobile/screens/collections/MCollections.tsx b/client/src/mobile/screens/collections/MCollections.tsx index 1b15c24b5..398f85912 100644 --- a/client/src/mobile/screens/collections/MCollections.tsx +++ b/client/src/mobile/screens/collections/MCollections.tsx @@ -1,5 +1,5 @@ import { ReactNode, useEffect, useState } from 'react' -import { useSearchParams } from 'react-router-dom' +import { useSearchParams } from 'react-router' import { Bookmark, Check, CheckCheck, CheckSquare, ChevronDown, Copy, CopyPlus, FolderInput, Layers, List, Loader2, Map as MapIcon, Pencil, Plus, Search, Share2, diff --git a/client/src/mobile/screens/dashboard/MDashWidgets.tsx b/client/src/mobile/screens/dashboard/MDashWidgets.tsx index 1cfc7e59f..13ced7f83 100644 --- a/client/src/mobile/screens/dashboard/MDashWidgets.tsx +++ b/client/src/mobile/screens/dashboard/MDashWidgets.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useEffect, useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { ArrowRight, ArrowRightLeft, Bookmark, Calendar, ChevronDown, ChevronRight, Clock, Hotel, MapPin, Plane, Plus, RefreshCw, Ticket, Utensils, X, diff --git a/client/src/mobile/screens/dashboard/MUserMenu.tsx b/client/src/mobile/screens/dashboard/MUserMenu.tsx index d23ff2834..72e577e30 100644 --- a/client/src/mobile/screens/dashboard/MUserMenu.tsx +++ b/client/src/mobile/screens/dashboard/MUserMenu.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { LogOut, Moon, Settings2, Shield, Sun, SunMoon } from 'lucide-react' import type { LucideIcon } from 'lucide-react' import { useTranslation } from '../../../i18n' diff --git a/client/src/mobile/screens/journey/MJourneySettingsSheet.tsx b/client/src/mobile/screens/journey/MJourneySettingsSheet.tsx index ab0f649cb..db7df0769 100644 --- a/client/src/mobile/screens/journey/MJourneySettingsSheet.tsx +++ b/client/src/mobile/screens/journey/MJourneySettingsSheet.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { X, Image, Plus, Trash2, UserPlus, Link as LinkIcon, List, Grid3x3, MapPin, Archive, ArchiveRestore, diff --git a/client/src/mobile/screens/notifications/MNotificationRow.tsx b/client/src/mobile/screens/notifications/MNotificationRow.tsx index 407190e27..edb573ce1 100644 --- a/client/src/mobile/screens/notifications/MNotificationRow.tsx +++ b/client/src/mobile/screens/notifications/MNotificationRow.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { ArrowRight, Bell, Check, Trash2, X } from 'lucide-react' import { useTranslation } from '../../../i18n' import { useInAppNotificationStore, InAppNotification } from '../../../store/inAppNotificationStore' diff --git a/client/src/mobile/screens/notifications/MNotifications.tsx b/client/src/mobile/screens/notifications/MNotifications.tsx index 91c972db6..74617f32a 100644 --- a/client/src/mobile/screens/notifications/MNotifications.tsx +++ b/client/src/mobile/screens/notifications/MNotifications.tsx @@ -1,4 +1,4 @@ -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { ArrowLeft, CheckCheck, Trash2 } from 'lucide-react' import MDancingTrek from '../../components/MDancingTrek' import { useTranslation } from '../../../i18n' diff --git a/client/src/mobile/screens/settings/MSettings.tsx b/client/src/mobile/screens/settings/MSettings.tsx index b867c1863..305d7908d 100644 --- a/client/src/mobile/screens/settings/MSettings.tsx +++ b/client/src/mobile/screens/settings/MSettings.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { Bell, ChevronDown, diff --git a/client/src/mobile/screens/settings/MSettingsAccount.tsx b/client/src/mobile/screens/settings/MSettingsAccount.tsx index 2b14ed887..098245ed5 100644 --- a/client/src/mobile/screens/settings/MSettingsAccount.tsx +++ b/client/src/mobile/screens/settings/MSettingsAccount.tsx @@ -16,7 +16,7 @@ import { User, X, } from 'lucide-react' -import { useNavigate, useSearchParams } from 'react-router-dom' +import { useNavigate, useSearchParams } from 'react-router' import { startRegistration } from '@simplewebauthn/browser' import { useTranslation } from '../../../i18n' import { useAuthStore } from '../../../store/authStore' diff --git a/client/src/mobile/screens/settings/MSettingsNotifications.tsx b/client/src/mobile/screens/settings/MSettingsNotifications.tsx index 03885ca17..b274b40e0 100644 --- a/client/src/mobile/screens/settings/MSettingsNotifications.tsx +++ b/client/src/mobile/screens/settings/MSettingsNotifications.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { Bell, Link2, Send } from 'lucide-react' import { useTranslation } from '../../../i18n' import { notificationsApi, settingsApi } from '../../../api/client' diff --git a/client/src/mobile/screens/vacay/useMVacay.ts b/client/src/mobile/screens/vacay/useMVacay.ts index f88c97562..e3415415e 100644 --- a/client/src/mobile/screens/vacay/useMVacay.ts +++ b/client/src/mobile/screens/vacay/useMVacay.ts @@ -1,5 +1,5 @@ import { useCallback, useEffect, useMemo, useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { useVacay } from '../../../pages/vacay/useVacay' import { useVacayStore } from '../../../store/vacayStore' import { useAuthStore } from '../../../store/authStore' diff --git a/client/src/pages/FilesPage.test.tsx b/client/src/pages/FilesPage.test.tsx index da8f25fa7..22d18769a 100644 --- a/client/src/pages/FilesPage.test.tsx +++ b/client/src/pages/FilesPage.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { describe, it, expect, beforeEach, vi } from 'vitest'; import { render, screen, waitFor, act } from '../../tests/helpers/render'; -import { Route, Routes } from 'react-router-dom'; +import { Route, Routes } from 'react-router'; import { http, HttpResponse } from 'msw'; import { server } from '../../tests/helpers/msw/server'; import { resetAllStores, seedStore } from '../../tests/helpers/store'; diff --git a/client/src/pages/FilesPage.tsx b/client/src/pages/FilesPage.tsx index 352164f60..d62f79380 100644 --- a/client/src/pages/FilesPage.tsx +++ b/client/src/pages/FilesPage.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { Link } from 'react-router-dom' +import { Link } from 'react-router' import PageShell from '../components/Layout/PageShell' import { PageSpinner } from '../components/shared/Spinner' import FileManager from '../components/Files/FileManager' diff --git a/client/src/pages/HelpPage.tsx b/client/src/pages/HelpPage.tsx index 7bcf31b13..12018ebab 100644 --- a/client/src/pages/HelpPage.tsx +++ b/client/src/pages/HelpPage.tsx @@ -1,5 +1,5 @@ import { Children, type ReactNode } from 'react' -import { Link } from 'react-router-dom' +import { Link } from 'react-router' import Markdown from 'react-markdown' import remarkGfm from 'remark-gfm' import { Search, ChevronRight, Loader2, AlertCircle, BookOpen, PanelLeft, X } from 'lucide-react' diff --git a/client/src/pages/JourneyDetailPage.test.tsx b/client/src/pages/JourneyDetailPage.test.tsx index ffc8c39e9..4e54ca9b5 100644 --- a/client/src/pages/JourneyDetailPage.test.tsx +++ b/client/src/pages/JourneyDetailPage.test.tsx @@ -68,8 +68,8 @@ vi.mock('../components/shared/ConfirmDialog', () => ({ })); const mockNavigate = vi.fn(); -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useParams: () => ({ id: '1' }), diff --git a/client/src/pages/JourneyPage.test.tsx b/client/src/pages/JourneyPage.test.tsx index d00e88e55..35c2509ff 100644 --- a/client/src/pages/JourneyPage.test.tsx +++ b/client/src/pages/JourneyPage.test.tsx @@ -15,8 +15,8 @@ import JourneyPage from './JourneyPage'; // ── Mocks ──────────────────────────────────────────────────────────────────── const mockNavigate = vi.fn(); -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useNavigate: () => mockNavigate }; }); diff --git a/client/src/pages/JourneyPublicPage.test.tsx b/client/src/pages/JourneyPublicPage.test.tsx index 460e82c46..3c869f69f 100644 --- a/client/src/pages/JourneyPublicPage.test.tsx +++ b/client/src/pages/JourneyPublicPage.test.tsx @@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; import React from 'react'; import { render, screen, waitFor, fireEvent } from '../../tests/helpers/render'; -import { Routes, Route } from 'react-router-dom'; +import { Routes, Route } from 'react-router'; import { http, HttpResponse } from 'msw'; import { server } from '../../tests/helpers/msw/server'; import { resetAllStores, seedStore } from '../../tests/helpers/store'; @@ -11,8 +11,8 @@ import userEvent from '@testing-library/user-event'; // ── Mocks ──────────────────────────────────────────────────────────────────── -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useParams: () => ({ token: 'test-share-token' }) }; }); diff --git a/client/src/pages/LoginPage.oidc-redirect.test.tsx b/client/src/pages/LoginPage.oidc-redirect.test.tsx index 28ee96964..780a88c57 100644 --- a/client/src/pages/LoginPage.oidc-redirect.test.tsx +++ b/client/src/pages/LoginPage.oidc-redirect.test.tsx @@ -6,8 +6,8 @@ import { resetAllStores } from '../../tests/helpers/store'; import LoginPage from './LoginPage'; const mockNavigate = vi.fn(); -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useNavigate: () => mockNavigate }; }); diff --git a/client/src/pages/PluginPage.tsx b/client/src/pages/PluginPage.tsx index ae9f82bd7..3b2d5f69f 100644 --- a/client/src/pages/PluginPage.tsx +++ b/client/src/pages/PluginPage.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { useParams } from 'react-router-dom' +import { useParams } from 'react-router' import PageShell from '../components/Layout/PageShell' import PluginFrame from '../components/Plugins/PluginFrame' import { usePluginStore } from '../store/pluginStore' diff --git a/client/src/pages/SharedTripPage.test.tsx b/client/src/pages/SharedTripPage.test.tsx index 37ea5a9f8..5de871b4b 100644 --- a/client/src/pages/SharedTripPage.test.tsx +++ b/client/src/pages/SharedTripPage.test.tsx @@ -1,6 +1,6 @@ import { describe, it, expect, beforeEach, vi } from 'vitest'; import { render, screen, waitFor, fireEvent } from '../../tests/helpers/render'; -import { Routes, Route } from 'react-router-dom'; +import { Routes, Route } from 'react-router'; import { http, HttpResponse } from 'msw'; import { server } from '../../tests/helpers/msw/server'; import { resetAllStores, seedStore } from '../../tests/helpers/store'; diff --git a/client/src/pages/TripPlannerPage.test.tsx b/client/src/pages/TripPlannerPage.test.tsx index 6c06c784d..3263ea83f 100644 --- a/client/src/pages/TripPlannerPage.test.tsx +++ b/client/src/pages/TripPlannerPage.test.tsx @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import React from 'react'; import { render, screen, waitFor, act, fireEvent } from '../../tests/helpers/render'; -import { Routes, Route } from 'react-router-dom'; +import { Routes, Route } from 'react-router'; import { resetAllStores, seedStore } from '../../tests/helpers/store'; import { buildUser, buildTrip, buildDay, buildPlace, buildAssignment } from '../../tests/helpers/factories'; import { useAuthStore } from '../store/authStore'; diff --git a/client/src/pages/TripPlannerPage.tsx b/client/src/pages/TripPlannerPage.tsx index ddc462cce..bc4956678 100644 --- a/client/src/pages/TripPlannerPage.tsx +++ b/client/src/pages/TripPlannerPage.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react' import ReactDOM from 'react-dom' -import { useParams, useNavigate, useSearchParams } from 'react-router-dom' +import { useParams, useNavigate, useSearchParams } from 'react-router' import { useTripStore } from '../store/tripStore' import { useCanDo } from '../store/permissionsStore' import { useSettingsStore } from '../store/settingsStore' diff --git a/client/src/pages/admin/useAdmin.test.tsx b/client/src/pages/admin/useAdmin.test.tsx index d5825d763..dc0f31c4b 100644 --- a/client/src/pages/admin/useAdmin.test.tsx +++ b/client/src/pages/admin/useAdmin.test.tsx @@ -2,7 +2,7 @@ import { http, HttpResponse } from 'msw'; import React from 'react'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { MemoryRouter } from 'react-router-dom'; +import { MemoryRouter } from 'react-router'; import { buildAdmin, buildUser } from '../../../tests/helpers/factories'; import { server } from '../../../tests/helpers/msw/server'; import { act, renderHook, waitFor } from '../../../tests/helpers/render'; diff --git a/client/src/pages/admin/useAdmin.ts b/client/src/pages/admin/useAdmin.ts index 0b9c35f4a..c9642dfff 100644 --- a/client/src/pages/admin/useAdmin.ts +++ b/client/src/pages/admin/useAdmin.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import apiClient, { adminApi, authApi } from '../../api/client' import { useAuthStore } from '../../store/authStore' import { useSettingsStore } from '../../store/settingsStore' diff --git a/client/src/pages/atlas/useAtlas.ts b/client/src/pages/atlas/useAtlas.ts index 3ee6fd583..00340c860 100644 --- a/client/src/pages/atlas/useAtlas.ts +++ b/client/src/pages/atlas/useAtlas.ts @@ -1,5 +1,5 @@ import React, { useEffect, useMemo, useState, useRef } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { getIntlLanguage, getLocaleForLanguage, useTranslation } from '../../i18n' import { useSettingsStore } from '../../store/settingsStore' import apiClient, { mapsApi, pluginsApi, type PluginAtlasLayer } from '../../api/client' diff --git a/client/src/pages/collections/useCollections.test.tsx b/client/src/pages/collections/useCollections.test.tsx index 6e56de9d8..d6888cc23 100644 --- a/client/src/pages/collections/useCollections.test.tsx +++ b/client/src/pages/collections/useCollections.test.tsx @@ -16,7 +16,7 @@ import { useCollections } from './useCollections' const navigate = vi.fn() let routeParams: { id?: string } = {} -vi.mock('react-router-dom', () => ({ +vi.mock('react-router', () => ({ useNavigate: () => navigate, useParams: () => routeParams, })) diff --git a/client/src/pages/collections/useCollections.ts b/client/src/pages/collections/useCollections.ts index 4b7f800c5..86d53760c 100644 --- a/client/src/pages/collections/useCollections.ts +++ b/client/src/pages/collections/useCollections.ts @@ -1,5 +1,5 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { useNavigate, useParams } from 'react-router-dom' +import { useNavigate, useParams } from 'react-router' import { useTranslation } from '../../i18n' import { useElementSize } from '../../hooks/useElementSize' import { useElementRect } from '../../hooks/useElementRect' diff --git a/client/src/pages/dashboard/useDashboard.test.tsx b/client/src/pages/dashboard/useDashboard.test.tsx index 9d382cede..6031b7d35 100644 --- a/client/src/pages/dashboard/useDashboard.test.tsx +++ b/client/src/pages/dashboard/useDashboard.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { renderHook, act, waitFor } from '@testing-library/react'; -import { MemoryRouter } from 'react-router-dom'; +import { MemoryRouter } from 'react-router'; import { http, HttpResponse } from 'msw'; import { server } from '../../../tests/helpers/msw/server'; import { resetAllStores, seedStore } from '../../../tests/helpers/store'; diff --git a/client/src/pages/dashboard/useDashboard.ts b/client/src/pages/dashboard/useDashboard.ts index 7852a859e..53d991e25 100644 --- a/client/src/pages/dashboard/useDashboard.ts +++ b/client/src/pages/dashboard/useDashboard.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react' -import { useNavigate, useSearchParams } from 'react-router-dom' +import { useNavigate, useSearchParams } from 'react-router' import { tripsApi, authApi, reservationsApi } from '../../api/client' import { tripRepo } from '../../repo/tripRepo' import { useAuthStore } from '../../store/authStore' diff --git a/client/src/pages/files/useFiles.ts b/client/src/pages/files/useFiles.ts index 11b1abad7..f62bfe277 100644 --- a/client/src/pages/files/useFiles.ts +++ b/client/src/pages/files/useFiles.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react' -import { useParams, useNavigate } from 'react-router-dom' +import { useParams, useNavigate } from 'react-router' import { useTripStore } from '../../store/tripStore' import { tripRepo } from '../../repo/tripRepo' import { placeRepo } from '../../repo/placeRepo' diff --git a/client/src/pages/forgotPassword/useForgotPassword.test.ts b/client/src/pages/forgotPassword/useForgotPassword.test.ts index b5b12d052..d4a1045d4 100644 --- a/client/src/pages/forgotPassword/useForgotPassword.test.ts +++ b/client/src/pages/forgotPassword/useForgotPassword.test.ts @@ -5,7 +5,7 @@ import { authApi } from '../../api/client'; import { useForgotPassword } from './useForgotPassword'; const navigate = vi.fn(); -vi.mock('react-router-dom', () => ({ useNavigate: () => navigate })); +vi.mock('react-router', () => ({ useNavigate: () => navigate })); const submitEvent = () => ({ preventDefault: vi.fn() }) as unknown as FormEvent; diff --git a/client/src/pages/forgotPassword/useForgotPassword.ts b/client/src/pages/forgotPassword/useForgotPassword.ts index 848587960..9c9740541 100644 --- a/client/src/pages/forgotPassword/useForgotPassword.ts +++ b/client/src/pages/forgotPassword/useForgotPassword.ts @@ -1,5 +1,5 @@ import { useState, useEffect, type FormEvent } from 'react' -import { useNavigate } from 'react-router-dom' +import { useNavigate } from 'react-router' import { authApi } from '../../api/client' /** diff --git a/client/src/pages/help/useHelp.test.ts b/client/src/pages/help/useHelp.test.ts index c4b094099..bdd20b013 100644 --- a/client/src/pages/help/useHelp.test.ts +++ b/client/src/pages/help/useHelp.test.ts @@ -4,7 +4,7 @@ import { helpApi, type HelpNavSection, type HelpPageData } from '../../api/clien import { useHelp } from './useHelp'; let routeParams: { slug?: string } = {}; -vi.mock('react-router-dom', () => ({ useParams: () => routeParams })); +vi.mock('react-router', () => ({ useParams: () => routeParams })); const SECTIONS: HelpNavSection[] = [ { title: 'Getting started', pages: [{ slug: 'Home', title: 'Welcome' }, { slug: 'Install', title: 'Installation' }] }, diff --git a/client/src/pages/help/useHelp.ts b/client/src/pages/help/useHelp.ts index 0d3f6329f..b6d746ac8 100644 --- a/client/src/pages/help/useHelp.ts +++ b/client/src/pages/help/useHelp.ts @@ -1,5 +1,5 @@ import { useEffect, useMemo, useRef, useState } from 'react' -import { useParams } from 'react-router-dom' +import { useParams } from 'react-router' import { helpApi, type HelpNavSection, type HelpPageData } from '../../api/client' /** State + data loading for the in-app help wiki (see PATTERN.md). */ diff --git a/client/src/pages/join/useJoinTrip.test.ts b/client/src/pages/join/useJoinTrip.test.ts index beb96e645..788a325f3 100644 --- a/client/src/pages/join/useJoinTrip.test.ts +++ b/client/src/pages/join/useJoinTrip.test.ts @@ -6,7 +6,7 @@ import { useJoinTrip } from './useJoinTrip'; const navigate = vi.fn(); let params: { token?: string } = { token: 'inv-1' }; -vi.mock('react-router-dom', () => ({ +vi.mock('react-router', () => ({ useNavigate: () => navigate, useParams: () => params, })); diff --git a/client/src/pages/join/useJoinTrip.ts b/client/src/pages/join/useJoinTrip.ts index 5830261a8..0a7b8f14d 100644 --- a/client/src/pages/join/useJoinTrip.ts +++ b/client/src/pages/join/useJoinTrip.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react' -import { useNavigate, useParams } from 'react-router-dom' +import { useNavigate, useParams } from 'react-router' import { tripInviteApi } from '../../api/client' export type JoinTripState = 'loading' | 'ready' | 'joining' | 'invalid' diff --git a/client/src/pages/journey/useJourney.ts b/client/src/pages/journey/useJourney.ts index d5f2acee0..4c3d3b6ce 100644 --- a/client/src/pages/journey/useJourney.ts +++ b/client/src/pages/journey/useJourney.ts @@ -1,5 +1,5 @@ import { useEffect, useState, useMemo, useRef } from 'react' -import { useNavigate, useSearchParams } from 'react-router-dom' +import { useNavigate, useSearchParams } from 'react-router' import { useJourneyStore } from '../../store/journeyStore' import { journeyApi } from '../../api/client' import { useToast } from '../../components/shared/Toast' diff --git a/client/src/pages/journeyDetail/useJourneyDetail.test.tsx b/client/src/pages/journeyDetail/useJourneyDetail.test.tsx index 704c8be07..8ae8a5726 100644 --- a/client/src/pages/journeyDetail/useJourneyDetail.test.tsx +++ b/client/src/pages/journeyDetail/useJourneyDetail.test.tsx @@ -1,6 +1,6 @@ // FE-JRN-DETHOOK-001 to FE-JRN-DETHOOK-022 import { describe, it, expect, beforeEach, afterEach, vi, type Mock } from 'vitest'; -import { useLocation } from 'react-router-dom'; +import { useLocation } from 'react-router'; import { http, HttpResponse } from 'msw'; import { server } from '../../../tests/helpers/msw/server'; import { render, screen, fireEvent, waitFor } from '../../../tests/helpers/render'; @@ -13,8 +13,8 @@ let routeParams: { id?: string } = { id: '7' }; const mockNavigate = vi.fn(); let mockIsMobile = false; -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useParams: () => routeParams, useNavigate: () => mockNavigate }; }); diff --git a/client/src/pages/journeyDetail/useJourneyDetail.ts b/client/src/pages/journeyDetail/useJourneyDetail.ts index f6737b13d..68bf4e822 100644 --- a/client/src/pages/journeyDetail/useJourneyDetail.ts +++ b/client/src/pages/journeyDetail/useJourneyDetail.ts @@ -1,5 +1,5 @@ import { useEffect, useState, useRef, useCallback, useMemo } from 'react' -import { useParams, useNavigate, useSearchParams } from 'react-router-dom' +import { useParams, useNavigate, useSearchParams } from 'react-router' import { useJourneyStore } from '../../store/journeyStore' import { useTranslation } from '../../i18n' import { addListener, removeListener } from '../../api/websocket' diff --git a/client/src/pages/journeyPublic/useJourneyPublic.ts b/client/src/pages/journeyPublic/useJourneyPublic.ts index 656bc5a0d..71f71ee31 100644 --- a/client/src/pages/journeyPublic/useJourneyPublic.ts +++ b/client/src/pages/journeyPublic/useJourneyPublic.ts @@ -1,5 +1,5 @@ import { useEffect, useState, useMemo, useRef, useCallback } from 'react' -import { useParams } from 'react-router-dom' +import { useParams } from 'react-router' import { journeyApi } from '../../api/client' import { useSettingsStore } from '../../store/settingsStore' import type { JourneyMapHandle } from '../../components/Journey/JourneyMap' diff --git a/client/src/pages/login/useLogin.test.tsx b/client/src/pages/login/useLogin.test.tsx index 2d7695efd..80f33c838 100644 --- a/client/src/pages/login/useLogin.test.tsx +++ b/client/src/pages/login/useLogin.test.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { renderHook, act, waitFor } from '../../../tests/helpers/render'; -import { MemoryRouter, type MemoryRouterProps } from 'react-router-dom'; +import { MemoryRouter, type MemoryRouterProps } from 'react-router'; import { http, HttpResponse } from 'msw'; import { server } from '../../../tests/helpers/msw/server'; import { resetAllStores } from '../../../tests/helpers/store'; @@ -14,8 +14,8 @@ import { startAuthentication } from '@simplewebauthn/browser'; import { useLogin } from './useLogin'; const mockNavigate = vi.fn(); -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useNavigate: () => mockNavigate }; }); diff --git a/client/src/pages/login/useLogin.ts b/client/src/pages/login/useLogin.ts index 7accfa2ef..e8c642c03 100644 --- a/client/src/pages/login/useLogin.ts +++ b/client/src/pages/login/useLogin.ts @@ -1,5 +1,5 @@ import { useState, useEffect, useMemo, useRef } from 'react' -import { useNavigate, useLocation } from 'react-router-dom' +import { useNavigate, useLocation } from 'react-router' import { useAuthStore } from '../../store/authStore' import { useSettingsStore, hasStoredLanguage } from '../../store/settingsStore' import { useTranslation, detectBrowserLanguage } from '../../i18n' diff --git a/client/src/pages/resetPassword/useResetPassword.test.ts b/client/src/pages/resetPassword/useResetPassword.test.ts index e71d02c45..39482ad9a 100644 --- a/client/src/pages/resetPassword/useResetPassword.test.ts +++ b/client/src/pages/resetPassword/useResetPassword.test.ts @@ -7,7 +7,7 @@ import { useResetPassword } from './useResetPassword'; const navigate = vi.fn(); let search = new URLSearchParams('token=abc123'); -vi.mock('react-router-dom', () => ({ +vi.mock('react-router', () => ({ useNavigate: () => navigate, useSearchParams: () => [search], })); diff --git a/client/src/pages/resetPassword/useResetPassword.ts b/client/src/pages/resetPassword/useResetPassword.ts index 10202aa3c..22a9b0826 100644 --- a/client/src/pages/resetPassword/useResetPassword.ts +++ b/client/src/pages/resetPassword/useResetPassword.ts @@ -1,5 +1,5 @@ import { useState, useEffect, type FormEvent } from 'react' -import { useNavigate, useSearchParams } from 'react-router-dom' +import { useNavigate, useSearchParams } from 'react-router' import { authApi } from '../../api/client' import { getApiErrorMessage } from '../../types' import { useTranslation } from '../../i18n' diff --git a/client/src/pages/settings/useSettings.ts b/client/src/pages/settings/useSettings.ts index e5cb74ba4..441de700c 100644 --- a/client/src/pages/settings/useSettings.ts +++ b/client/src/pages/settings/useSettings.ts @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react' -import { useSearchParams } from 'react-router-dom' +import { useSearchParams } from 'react-router' import { authApi } from '../../api/client' import { useAddonStore } from '../../store/addonStore' diff --git a/client/src/pages/sharedTrip/useSharedTrip.ts b/client/src/pages/sharedTrip/useSharedTrip.ts index 2214dfc77..49470123d 100644 --- a/client/src/pages/sharedTrip/useSharedTrip.ts +++ b/client/src/pages/sharedTrip/useSharedTrip.ts @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react' -import { useParams } from 'react-router-dom' +import { useParams } from 'react-router' import { shareApi } from '../../api/client' import { useExchangeRates } from '../../hooks/useExchangeRates' diff --git a/client/src/pages/tripPlanner/useTripPlanner.test.tsx b/client/src/pages/tripPlanner/useTripPlanner.test.tsx index 71f142a2d..aa711020c 100644 --- a/client/src/pages/tripPlanner/useTripPlanner.test.tsx +++ b/client/src/pages/tripPlanner/useTripPlanner.test.tsx @@ -31,7 +31,7 @@ const setSearchParams = vi.fn((updater: (p: URLSearchParams) => URLSearchParams) searchParams = typeof updater === 'function' ? updater(next) : next }) -vi.mock('react-router-dom', () => ({ +vi.mock('react-router', () => ({ useParams: () => routeParams, useNavigate: () => navigate, useSearchParams: () => [searchParams, setSearchParams], diff --git a/client/src/pages/tripPlanner/useTripPlanner.ts b/client/src/pages/tripPlanner/useTripPlanner.ts index 0fbb06e6f..f0e35b4d2 100644 --- a/client/src/pages/tripPlanner/useTripPlanner.ts +++ b/client/src/pages/tripPlanner/useTripPlanner.ts @@ -1,5 +1,5 @@ import { useState, useEffect, useCallback, useMemo, useRef } from 'react' -import { useParams, useNavigate, useSearchParams } from 'react-router-dom' +import { useParams, useNavigate, useSearchParams } from 'react-router' import { useTripStore } from '../../store/tripStore' import { useCanDo } from '../../store/permissionsStore' import { useSettingsStore } from '../../store/settingsStore' diff --git a/client/tests/helpers/render.tsx b/client/tests/helpers/render.tsx index b62cdefb5..b669eaa2b 100644 --- a/client/tests/helpers/render.tsx +++ b/client/tests/helpers/render.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { render, type RenderOptions } from '@testing-library/react'; -import { MemoryRouter, type MemoryRouterProps } from 'react-router-dom'; +import { MemoryRouter, type MemoryRouterProps } from 'react-router'; import { TranslationProvider } from '../../src/i18n/TranslationContext'; interface RenderWithProvidersOptions extends Omit { diff --git a/client/tests/unit/mobile/MBottomNav.test.tsx b/client/tests/unit/mobile/MBottomNav.test.tsx index f9a458f43..88f709fdd 100644 --- a/client/tests/unit/mobile/MBottomNav.test.tsx +++ b/client/tests/unit/mobile/MBottomNav.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { describe, it, expect, beforeEach } from 'vitest'; -import { useLocation } from 'react-router-dom'; +import { useLocation } from 'react-router'; import { render, screen, fireEvent } from '../../helpers/render'; import MBottomNav from '../../../src/mobile/components/MBottomNav'; import { useAddonStore } from '../../../src/store/addonStore'; diff --git a/client/tests/unit/mobile/admin/MAdmin.test.tsx b/client/tests/unit/mobile/admin/MAdmin.test.tsx index 96b7285c8..33dbd8dd5 100644 --- a/client/tests/unit/mobile/admin/MAdmin.test.tsx +++ b/client/tests/unit/mobile/admin/MAdmin.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; -import { Route, Routes } from 'react-router-dom'; +import { Route, Routes } from 'react-router'; import { http, HttpResponse } from 'msw'; import { fireEvent, render, screen, waitFor } from '../../../helpers/render'; import { server } from '../../../helpers/msw/server'; diff --git a/client/tests/unit/mobile/dashboard/MDashWidgets.test.tsx b/client/tests/unit/mobile/dashboard/MDashWidgets.test.tsx index 8514c1557..49bca79e5 100644 --- a/client/tests/unit/mobile/dashboard/MDashWidgets.test.tsx +++ b/client/tests/unit/mobile/dashboard/MDashWidgets.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { renderHook, act } from '@testing-library/react'; -import { useLocation } from 'react-router-dom'; +import { useLocation } from 'react-router'; import { http, HttpResponse } from 'msw'; import { render, screen, fireEvent, waitFor } from '../../../helpers/render'; import { server } from '../../../helpers/msw/server'; diff --git a/client/tests/unit/mobile/journey/MJourneySettingsSheet.test.tsx b/client/tests/unit/mobile/journey/MJourneySettingsSheet.test.tsx index 03bdefb5d..cd45158f6 100644 --- a/client/tests/unit/mobile/journey/MJourneySettingsSheet.test.tsx +++ b/client/tests/unit/mobile/journey/MJourneySettingsSheet.test.tsx @@ -7,8 +7,8 @@ import { useJourneyStore } from '../../../../src/store/journeyStore'; import type { JourneyDetail } from '../../../../src/store/journeyStore'; const mockNavigate = vi.fn(); -vi.mock('react-router-dom', async () => { - const actual = await vi.importActual('react-router-dom'); +vi.mock('react-router', async () => { + const actual = await vi.importActual('react-router'); return { ...actual, useNavigate: () => mockNavigate }; }); diff --git a/client/tests/unit/mobile/settings/MSettingsAccount.test.tsx b/client/tests/unit/mobile/settings/MSettingsAccount.test.tsx index de1186299..62eb83561 100644 --- a/client/tests/unit/mobile/settings/MSettingsAccount.test.tsx +++ b/client/tests/unit/mobile/settings/MSettingsAccount.test.tsx @@ -15,8 +15,8 @@ import MSettingsAccount from '../../../../src/mobile/screens/settings/MSettingsA const navigateMock = vi.fn(); -vi.mock('react-router-dom', async (importOriginal) => { - const actual = await importOriginal(); +vi.mock('react-router', async (importOriginal) => { + const actual = await importOriginal(); return { ...actual, useNavigate: () => navigateMock }; }); diff --git a/client/tests/unit/mobile/settings/MSettingsNotifications.test.tsx b/client/tests/unit/mobile/settings/MSettingsNotifications.test.tsx index 2808470c4..3f424f390 100644 --- a/client/tests/unit/mobile/settings/MSettingsNotifications.test.tsx +++ b/client/tests/unit/mobile/settings/MSettingsNotifications.test.tsx @@ -1,6 +1,6 @@ // FE-MOB-SETNOTIF-001 onwards import { describe, it, expect, beforeEach } from 'vitest'; -import { useLocation } from 'react-router-dom'; +import { useLocation } from 'react-router'; import userEvent from '@testing-library/user-event'; import { http, HttpResponse } from 'msw'; import { render, screen, waitFor, within } from '../../../helpers/render'; diff --git a/client/tests/unit/mobile/vacay/useMVacay.test.tsx b/client/tests/unit/mobile/vacay/useMVacay.test.tsx index 077a9e196..e63744105 100644 --- a/client/tests/unit/mobile/vacay/useMVacay.test.tsx +++ b/client/tests/unit/mobile/vacay/useMVacay.test.tsx @@ -11,8 +11,8 @@ import type { VacayEntry, VacayPlan, VacayStat, VacayUser } from '../../../../sr const navigateMock = vi.fn(); -vi.mock('react-router-dom', async (importOriginal) => { - const actual = await importOriginal(); +vi.mock('react-router', async (importOriginal) => { + const actual = await importOriginal(); return { ...actual, useNavigate: () => navigateMock }; }); diff --git a/package-lock.json b/package-lock.json index 2fbeefe8e..5c162dc42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,7 +50,7 @@ "react-leaflet": "^5.0.0", "react-leaflet-cluster": "^4.1.3", "react-markdown": "^10.1.0", - "react-router-dom": "^6.22.2", + "react-router": "^7.18.2", "rehype-sanitize": "^6.0.0", "remark-breaks": "^4.0.0", "remark-gfm": "^4.0.1", @@ -95,6 +95,19 @@ "vitest": "^4.1.9" } }, + "client/node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "client/node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", @@ -108,6 +121,34 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "client/node_modules/react-router": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.2.tgz", + "integrity": "sha512-aUVMjFm3GAPTTZL7oYr5E7ETiqfQCHRLH+B+5afnICvf0r7kkK4eR6SMuwbSTJw/7t+12khT/Kahij49fqOCIg==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "client/node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, "client/node_modules/vite": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.0.tgz", @@ -5812,15 +5853,6 @@ "react-dom": "^19.0.0" } }, - "node_modules/@remix-run/router": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.3.tgz", - "integrity": "sha512-4An71tdz9X8+3sI4Qqqd2LWd9vS39J7sqd9EU4Scw7TJE/qB10Flv/UuqbPVgfQV9XoK8Np6jNquZitnZq5i+Q==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.2.tgz", @@ -16849,38 +16881,6 @@ "react": ">=18" } }, - "node_modules/react-router": { - "version": "6.30.4", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.4.tgz", - "integrity": "sha512-SVUsDe+DybHM/WmYKIVYhZh1o5Dcuf16yM6WjG02Q9XVFMZIJyHYhwrr6bFBXZkVP6z69kNkMyBCujt8FaFLJA==", - "license": "MIT", - "dependencies": { - "@remix-run/router": "1.23.3" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/react-router-dom": { - "version": "6.30.4", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.4.tgz", - "integrity": "sha512-q4HvNl+mmDdkS0g+MqiBZNteQJCuimWoOyHMy4T/RQLAn9Z29+E91QXRaxOujeMl2HTzRSS0KFPd7lxX3PjV0Q==", - "license": "MIT", - "dependencies": { - "@remix-run/router": "1.23.3", - "react-router": "6.30.4" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",