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",