From 28554acc2d752c222636219ee1506f8397893065 Mon Sep 17 00:00:00 2001
From: jackiettran <41605212+jackiettran@users.noreply.github.com>
Date: Mon, 19 Jan 2026 22:50:53 -0500
Subject: [PATCH] Migrated to react router v7
---
frontend/package-lock.json | 80 ++----
frontend/package.json | 3 +-
frontend/src/App.tsx | 229 ++++--------------
.../__tests__/components/ItemCard.test.tsx | 2 +-
.../src/__tests__/components/Navbar.test.tsx | 6 +-
frontend/src/components/Footer.tsx | 2 +-
frontend/src/components/ForumPostListItem.tsx | 2 +-
frontend/src/components/ItemCard.tsx | 2 +-
frontend/src/components/ItemReviews.tsx | 2 +-
frontend/src/components/Navbar.tsx | 2 +-
frontend/src/components/PricingForm.tsx | 2 +-
.../{PrivateRoute.tsx => ProtectedLayout.tsx} | 11 +-
frontend/src/components/RootLayout.tsx | 77 ++++++
frontend/src/pages/CompletePayment.tsx | 2 +-
frontend/src/pages/CreateForumPost.tsx | 2 +-
frontend/src/pages/CreateItem.tsx | 2 +-
frontend/src/pages/EarningsDashboard.tsx | 2 +-
frontend/src/pages/EditItem.tsx | 2 +-
frontend/src/pages/FAQ.tsx | 2 +-
frontend/src/pages/ForumPostDetail.tsx | 2 +-
frontend/src/pages/ForumPosts.tsx | 2 +-
frontend/src/pages/GoogleCallback.tsx | 2 +-
frontend/src/pages/Home.tsx | 2 +-
frontend/src/pages/ItemDetail.tsx | 2 +-
frontend/src/pages/ItemList.tsx | 2 +-
frontend/src/pages/MyPosts.tsx | 2 +-
frontend/src/pages/NotFound.tsx | 2 +-
frontend/src/pages/Owning.tsx | 2 +-
frontend/src/pages/Profile.tsx | 2 +-
frontend/src/pages/PublicProfile.tsx | 2 +-
frontend/src/pages/RentItem.tsx | 2 +-
frontend/src/pages/Renting.tsx | 2 +-
frontend/src/pages/ResetPassword.tsx | 2 +-
frontend/src/pages/VerifyEmail.tsx | 2 +-
frontend/src/services/api.ts | 2 +-
35 files changed, 180 insertions(+), 284 deletions(-)
rename frontend/src/components/{PrivateRoute.tsx => ProtectedLayout.tsx} (83%)
create mode 100644 frontend/src/components/RootLayout.tsx
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 6ec308a..e3d554a 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -20,14 +20,13 @@
"@types/node": "^20.0.0",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
- "@types/react-router-dom": "^5.3.3",
"axios": "^1.10.0",
"bootstrap": "^5.3.7",
"browser-image-compression": "^2.0.2",
"react": "^19.1.0",
"react-datepicker": "^9.1.0",
"react-dom": "^19.1.0",
- "react-router-dom": "^6.30.1",
+ "react-router": "^7.12.0",
"socket.io-client": "^4.8.1",
"stripe": "^18.4.0",
"typescript": "^4.9.5"
@@ -1271,15 +1270,6 @@
"url": "https://opencollective.com/popperjs"
}
},
- "node_modules/@remix-run/router": {
- "version": "1.23.2",
- "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz",
- "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==",
- "license": "MIT",
- "engines": {
- "node": ">=14.0.0"
- }
- },
"node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.27",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
@@ -1860,12 +1850,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@types/history": {
- "version": "4.7.11",
- "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
- "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
- "license": "MIT"
- },
"node_modules/@types/node": {
"version": "20.19.30",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz",
@@ -1893,27 +1877,6 @@
"@types/react": "^19.2.0"
}
},
- "node_modules/@types/react-router": {
- "version": "5.1.20",
- "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz",
- "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==",
- "license": "MIT",
- "dependencies": {
- "@types/history": "^4.7.11",
- "@types/react": "*"
- }
- },
- "node_modules/@types/react-router-dom": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz",
- "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==",
- "license": "MIT",
- "dependencies": {
- "@types/history": "^4.7.11",
- "@types/react": "*",
- "@types/react-router": "*"
- }
- },
"node_modules/@types/statuses": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz",
@@ -2384,7 +2347,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
"integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
@@ -3692,35 +3654,25 @@
}
},
"node_modules/react-router": {
- "version": "6.30.3",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz",
- "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==",
+ "version": "7.12.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.12.0.tgz",
+ "integrity": "sha512-kTPDYPFzDVGIIGNLS5VJykK0HfHLY5MF3b+xj0/tTyNYL1gF1qs7u67Z9jEhQk2sQ98SUaHxlG31g1JtF7IfVw==",
"license": "MIT",
"dependencies": {
- "@remix-run/router": "1.23.2"
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
},
"engines": {
- "node": ">=14.0.0"
+ "node": ">=20.0.0"
},
"peerDependencies": {
- "react": ">=16.8"
- }
- },
- "node_modules/react-router-dom": {
- "version": "6.30.3",
- "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz",
- "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==",
- "license": "MIT",
- "dependencies": {
- "@remix-run/router": "1.23.2",
- "react-router": "6.30.3"
+ "react": ">=18",
+ "react-dom": ">=18"
},
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "react": ">=16.8",
- "react-dom": ">=16.8"
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
}
},
"node_modules/redent": {
@@ -3837,6 +3789,12 @@
"semver": "bin/semver.js"
}
},
+ "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"
+ },
"node_modules/side-channel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 4cb7012..519e3c2 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -16,14 +16,13 @@
"@types/node": "^20.0.0",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
- "@types/react-router-dom": "^5.3.3",
"axios": "^1.10.0",
"bootstrap": "^5.3.7",
"browser-image-compression": "^2.0.2",
"react": "^19.1.0",
"react-datepicker": "^9.1.0",
"react-dom": "^19.1.0",
- "react-router-dom": "^6.30.1",
+ "react-router": "^7.12.0",
"socket.io-client": "^4.8.1",
"stripe": "^18.4.0",
"typescript": "^4.9.5"
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 3e310d6..48ff69d 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,13 +1,10 @@
-import React, { useState, useEffect, useCallback } from 'react';
-import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
+import React, { useState, useEffect } from 'react';
+import { createBrowserRouter, RouterProvider } from 'react-router';
import { AuthProvider, useAuth } from './contexts/AuthContext';
import { SocketProvider } from './contexts/SocketContext';
-import Navbar from './components/Navbar';
-import Footer from './components/Footer';
-import AuthModal from './components/AuthModal';
+import RootLayout from './components/RootLayout';
+import ProtectedLayout from './components/ProtectedLayout';
import AlphaGate from './components/AlphaGate';
-import FeedbackButton from './components/FeedbackButton';
-import { TwoFactorVerifyModal } from './components/TwoFactor';
import Home from './pages/Home';
import GoogleCallback from './pages/GoogleCallback';
import VerifyEmail from './pages/VerifyEmail';
@@ -30,50 +27,56 @@ import EarningsDashboard from './pages/EarningsDashboard';
import CompletePayment from './pages/CompletePayment';
import FAQ from './pages/FAQ';
import NotFound from './pages/NotFound';
-import PrivateRoute from './components/PrivateRoute';
import axios from 'axios';
import './App.css';
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:5001';
+const router = createBrowserRouter([
+ {
+ element: ,
+ children: [
+ // Public routes
+ { path: '/', element: },
+ { path: '/auth/google/callback', element: },
+ { path: '/verify-email', element: },
+ { path: '/reset-password', element: },
+ { path: '/items', element: },
+ { path: '/items/:id', element: },
+ { path: '/users/:id', element: },
+ { path: '/forum', element: },
+ { path: '/forum/:id', element: },
+ { path: '/faq', element: },
+
+ // Protected routes group
+ {
+ element: ,
+ children: [
+ { path: '/items/:id/edit', element: },
+ { path: '/items/:id/rent', element: },
+ { path: '/create-item', element: },
+ { path: '/renting', element: },
+ { path: '/complete-payment/:rentalId', element: },
+ { path: '/owning', element: },
+ { path: '/profile', element: },
+ { path: '/messages', element: },
+ { path: '/forum/create', element: },
+ { path: '/forum/:id/edit', element: },
+ { path: '/my-posts', element: },
+ { path: '/earnings', element: },
+ ],
+ },
+
+ // Catch-all route
+ { path: '*', element: },
+ ],
+ },
+]);
+
const AppContent: React.FC = () => {
- const { showAuthModal, authModalMode, closeAuthModal, user } = useAuth();
const [hasAlphaAccess, setHasAlphaAccess] = useState(null);
const [checkingAccess, setCheckingAccess] = useState(true);
- // Step-up authentication state
- const [showStepUpModal, setShowStepUpModal] = useState(false);
- const [stepUpAction, setStepUpAction] = useState();
- const [stepUpMethods, setStepUpMethods] = useState<("totp" | "email" | "recovery")[]>([]);
-
- // Listen for step-up authentication required events
- useEffect(() => {
- const handleStepUpRequired = (event: CustomEvent) => {
- const { action, methods } = event.detail;
- setStepUpAction(action);
- setStepUpMethods(methods || ["totp", "email", "recovery"]);
- setShowStepUpModal(true);
- };
-
- window.addEventListener("stepUpRequired", handleStepUpRequired as EventListener);
-
- return () => {
- window.removeEventListener("stepUpRequired", handleStepUpRequired as EventListener);
- };
- }, []);
-
- const handleStepUpSuccess = useCallback(() => {
- setShowStepUpModal(false);
- setStepUpAction(undefined);
- // Dispatch event so pending actions can auto-retry
- window.dispatchEvent(new CustomEvent("stepUpSuccess"));
- }, []);
-
- const handleStepUpClose = useCallback(() => {
- setShowStepUpModal(false);
- setStepUpAction(undefined);
- }, []);
-
useEffect(() => {
const checkAlphaAccess = async () => {
// Bypass alpha access check if feature is disabled
@@ -115,145 +118,7 @@ const AppContent: React.FC = () => {
return ;
}
- return (
- <>
-
-
-
-
-
- } />
- } />
- } />
- } />
- } />
- } />
- } />
-
-
-
- }
- />
-
-
-
- }
- />
-
-
-
- }
- />
-
-
-
- }
- />
-
-
-
- }
- />
-
-
-
- }
- />
-
-
-
- }
- />
-
-
-
- }
- />
- } />
- } />
-
-
-
- }
- />
-
-
-
- }
- />
-
-
-
- }
- />
-
-
-
- }
- />
- } />
- } />
-
-
-
-
-
-
-
-
- {/* Show feedback button for authenticated users */}
- {user && }
-
- {/* Global Step-Up Authentication Modal */}
-
- >
- );
+ return ;
};
const AppWithSocket: React.FC = () => {
@@ -274,4 +139,4 @@ function App() {
);
}
-export default App;
\ No newline at end of file
+export default App;
diff --git a/frontend/src/__tests__/components/ItemCard.test.tsx b/frontend/src/__tests__/components/ItemCard.test.tsx
index d02a42c..e91f4c8 100644
--- a/frontend/src/__tests__/components/ItemCard.test.tsx
+++ b/frontend/src/__tests__/components/ItemCard.test.tsx
@@ -7,7 +7,7 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
-import { BrowserRouter } from 'react-router-dom';
+import { BrowserRouter } from 'react-router';
import { vi, type MockedFunction } from 'vitest';
import ItemCard from '../../components/ItemCard';
import { Item } from '../../types';
diff --git a/frontend/src/__tests__/components/Navbar.test.tsx b/frontend/src/__tests__/components/Navbar.test.tsx
index 76b813b..22a1641 100644
--- a/frontend/src/__tests__/components/Navbar.test.tsx
+++ b/frontend/src/__tests__/components/Navbar.test.tsx
@@ -7,7 +7,7 @@
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
-import { BrowserRouter } from 'react-router-dom';
+import { BrowserRouter } from 'react-router';
import { vi, type Mock } from 'vitest';
import Navbar from '../../components/Navbar';
import { rentalAPI, messageAPI } from '../../services/api';
@@ -45,8 +45,8 @@ vi.mock('../../contexts/AuthContext', () => ({
// Mock useNavigate
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/frontend/src/components/Footer.tsx b/frontend/src/components/Footer.tsx
index 80d6cae..8f78120 100644
--- a/frontend/src/components/Footer.tsx
+++ b/frontend/src/components/Footer.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { Link } from 'react-router-dom';
+import { Link } from 'react-router';
const Footer: React.FC = () => {
return (
diff --git a/frontend/src/components/ForumPostListItem.tsx b/frontend/src/components/ForumPostListItem.tsx
index 9bb2380..7fb78ed 100644
--- a/frontend/src/components/ForumPostListItem.tsx
+++ b/frontend/src/components/ForumPostListItem.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { Link } from "react-router-dom";
+import { Link } from "react-router";
import { ForumPost } from "../types";
import CategoryBadge from "./CategoryBadge";
import PostStatusBadge from "./PostStatusBadge";
diff --git a/frontend/src/components/ItemCard.tsx b/frontend/src/components/ItemCard.tsx
index 283ba20..8753c0d 100644
--- a/frontend/src/components/ItemCard.tsx
+++ b/frontend/src/components/ItemCard.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { Link } from 'react-router-dom';
+import { Link } from 'react-router';
import { Item } from '../types';
import { getImageUrl } from '../services/uploadService';
diff --git a/frontend/src/components/ItemReviews.tsx b/frontend/src/components/ItemReviews.tsx
index 162e92c..61a6956 100644
--- a/frontend/src/components/ItemReviews.tsx
+++ b/frontend/src/components/ItemReviews.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import { useNavigate } from "react-router-dom";
+import { useNavigate } from "react-router";
import { Rental } from "../types";
import { itemAPI } from "../services/api";
import Avatar from "./Avatar";
diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx
index 1d080dc..c1aca8f 100644
--- a/frontend/src/components/Navbar.tsx
+++ b/frontend/src/components/Navbar.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect, useRef, useCallback } from "react";
-import { Link, useNavigate, useLocation } from "react-router-dom";
+import { Link, useNavigate, useLocation } from "react-router";
import { useAuth } from "../contexts/AuthContext";
import { useSocket } from "../contexts/SocketContext";
import { rentalAPI, messageAPI } from "../services/api";
diff --git a/frontend/src/components/PricingForm.tsx b/frontend/src/components/PricingForm.tsx
index 30c639f..45b1409 100644
--- a/frontend/src/components/PricingForm.tsx
+++ b/frontend/src/components/PricingForm.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { Link } from "react-router-dom";
+import { Link } from "react-router";
interface PricingFormProps {
pricePerHour: number | string;
diff --git a/frontend/src/components/PrivateRoute.tsx b/frontend/src/components/ProtectedLayout.tsx
similarity index 83%
rename from frontend/src/components/PrivateRoute.tsx
rename to frontend/src/components/ProtectedLayout.tsx
index 8e7170a..b6921a0 100644
--- a/frontend/src/components/PrivateRoute.tsx
+++ b/frontend/src/components/ProtectedLayout.tsx
@@ -1,11 +1,8 @@
import React, { useEffect } from "react";
+import { Outlet } from "react-router";
import { useAuth } from "../contexts/AuthContext";
-interface PrivateRouteProps {
- children: React.ReactNode;
-}
-
-const PrivateRoute: React.FC = ({ children }) => {
+const ProtectedLayout: React.FC = () => {
const { user, loading, openAuthModal } = useAuth();
useEffect(() => {
@@ -41,7 +38,7 @@ const PrivateRoute: React.FC = ({ children }) => {
);
}
- return <>{children}>;
+ return ;
};
-export default PrivateRoute;
+export default ProtectedLayout;
diff --git a/frontend/src/components/RootLayout.tsx b/frontend/src/components/RootLayout.tsx
new file mode 100644
index 0000000..67e5fcd
--- /dev/null
+++ b/frontend/src/components/RootLayout.tsx
@@ -0,0 +1,77 @@
+import React, { useState, useEffect, useCallback } from "react";
+import { Outlet } from "react-router";
+import { useAuth } from "../contexts/AuthContext";
+import Navbar from "./Navbar";
+import Footer from "./Footer";
+import AuthModal from "./AuthModal";
+import FeedbackButton from "./FeedbackButton";
+import { TwoFactorVerifyModal } from "./TwoFactor";
+
+const RootLayout: React.FC = () => {
+ const { showAuthModal, authModalMode, closeAuthModal, user } = useAuth();
+
+ // Step-up authentication state
+ const [showStepUpModal, setShowStepUpModal] = useState(false);
+ const [stepUpAction, setStepUpAction] = useState();
+ const [stepUpMethods, setStepUpMethods] = useState<("totp" | "email" | "recovery")[]>([]);
+
+ // Listen for step-up authentication required events
+ useEffect(() => {
+ const handleStepUpRequired = (event: CustomEvent) => {
+ const { action, methods } = event.detail;
+ setStepUpAction(action);
+ setStepUpMethods(methods || ["totp", "email", "recovery"]);
+ setShowStepUpModal(true);
+ };
+
+ window.addEventListener("stepUpRequired", handleStepUpRequired as EventListener);
+
+ return () => {
+ window.removeEventListener("stepUpRequired", handleStepUpRequired as EventListener);
+ };
+ }, []);
+
+ const handleStepUpSuccess = useCallback(() => {
+ setShowStepUpModal(false);
+ setStepUpAction(undefined);
+ // Dispatch event so pending actions can auto-retry
+ window.dispatchEvent(new CustomEvent("stepUpSuccess"));
+ }, []);
+
+ const handleStepUpClose = useCallback(() => {
+ setShowStepUpModal(false);
+ setStepUpAction(undefined);
+ }, []);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ {/* Show feedback button for authenticated users */}
+ {user && }
+
+ {/* Global Step-Up Authentication Modal */}
+
+ >
+ );
+};
+
+export default RootLayout;
diff --git a/frontend/src/pages/CompletePayment.tsx b/frontend/src/pages/CompletePayment.tsx
index 4328c85..c725548 100644
--- a/frontend/src/pages/CompletePayment.tsx
+++ b/frontend/src/pages/CompletePayment.tsx
@@ -1,5 +1,5 @@
import React, { useEffect, useState, useCallback, useRef } from "react";
-import { useParams, useNavigate, Link } from "react-router-dom";
+import { useParams, useNavigate, Link } from "react-router";
import { loadStripe } from "@stripe/stripe-js";
import { rentalAPI } from "../services/api";
import { useAuth } from "../contexts/AuthContext";
diff --git a/frontend/src/pages/CreateForumPost.tsx b/frontend/src/pages/CreateForumPost.tsx
index 2a740ce..8b1ba83 100644
--- a/frontend/src/pages/CreateForumPost.tsx
+++ b/frontend/src/pages/CreateForumPost.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import { useNavigate, Link, useParams } from "react-router-dom";
+import { useNavigate, Link, useParams } from "react-router";
import { useAuth } from "../contexts/AuthContext";
import { forumAPI, addressAPI } from "../services/api";
import { uploadImagesWithVariants, getImageUrl } from "../services/uploadService";
diff --git a/frontend/src/pages/CreateItem.tsx b/frontend/src/pages/CreateItem.tsx
index 4b0193d..9b37fba 100644
--- a/frontend/src/pages/CreateItem.tsx
+++ b/frontend/src/pages/CreateItem.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect, useRef } from "react";
-import { useNavigate } from "react-router-dom";
+import { useNavigate } from "react-router";
import { useAuth } from "../contexts/AuthContext";
import api, { addressAPI, userAPI, itemAPI } from "../services/api";
import { uploadImagesWithVariants } from "../services/uploadService";
diff --git a/frontend/src/pages/EarningsDashboard.tsx b/frontend/src/pages/EarningsDashboard.tsx
index e25e78f..986942c 100644
--- a/frontend/src/pages/EarningsDashboard.tsx
+++ b/frontend/src/pages/EarningsDashboard.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import { Link } from "react-router-dom";
+import { Link } from "react-router";
import { rentalAPI, userAPI, stripeAPI } from "../services/api";
import { Rental, User } from "../types";
import StripeConnectOnboarding from "../components/StripeConnectOnboarding";
diff --git a/frontend/src/pages/EditItem.tsx b/frontend/src/pages/EditItem.tsx
index fee9257..1e7b04e 100644
--- a/frontend/src/pages/EditItem.tsx
+++ b/frontend/src/pages/EditItem.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect, useRef } from "react";
-import { useParams, useNavigate } from "react-router-dom";
+import { useParams, useNavigate } from "react-router";
import { Item, Rental, Address } from "../types";
import { useAuth } from "../contexts/AuthContext";
import { itemAPI, rentalAPI, addressAPI, userAPI } from "../services/api";
diff --git a/frontend/src/pages/FAQ.tsx b/frontend/src/pages/FAQ.tsx
index e3634d2..8fd9b10 100644
--- a/frontend/src/pages/FAQ.tsx
+++ b/frontend/src/pages/FAQ.tsx
@@ -1,5 +1,5 @@
import React, { useState } from "react";
-import { Link } from "react-router-dom";
+import { Link } from "react-router";
interface FAQItem {
question: string;
diff --git a/frontend/src/pages/ForumPostDetail.tsx b/frontend/src/pages/ForumPostDetail.tsx
index 4113604..e209a7f 100644
--- a/frontend/src/pages/ForumPostDetail.tsx
+++ b/frontend/src/pages/ForumPostDetail.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
-import { useParams, useNavigate, Link, useSearchParams } from 'react-router-dom';
+import { useParams, useNavigate, Link, useSearchParams } from 'react-router';
import { useAuth } from '../contexts/AuthContext';
import { forumAPI } from '../services/api';
import { uploadImagesWithVariants, getImageUrl } from '../services/uploadService';
diff --git a/frontend/src/pages/ForumPosts.tsx b/frontend/src/pages/ForumPosts.tsx
index a6beff8..3dc1ec2 100644
--- a/frontend/src/pages/ForumPosts.tsx
+++ b/frontend/src/pages/ForumPosts.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
-import { Link, useSearchParams } from 'react-router-dom';
+import { Link, useSearchParams } from 'react-router';
import { useAuth } from '../contexts/AuthContext';
import { forumAPI } from '../services/api';
import { ForumPost } from '../types';
diff --git a/frontend/src/pages/GoogleCallback.tsx b/frontend/src/pages/GoogleCallback.tsx
index 9150abf..44bc730 100644
--- a/frontend/src/pages/GoogleCallback.tsx
+++ b/frontend/src/pages/GoogleCallback.tsx
@@ -1,5 +1,5 @@
import React, { useEffect, useState, useRef } from 'react';
-import { useNavigate, useSearchParams } from 'react-router-dom';
+import { useNavigate, useSearchParams } from 'react-router';
import { useAuth } from '../contexts/AuthContext';
import { fetchCSRFToken } from '../services/api';
diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx
index 8c74f8d..5d4cf5a 100644
--- a/frontend/src/pages/Home.tsx
+++ b/frontend/src/pages/Home.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import { Link } from "react-router-dom";
+import { Link } from "react-router";
import { useAuth } from "../contexts/AuthContext";
import { itemAPI } from "../services/api";
import { Item } from "../types";
diff --git a/frontend/src/pages/ItemDetail.tsx b/frontend/src/pages/ItemDetail.tsx
index 6a96124..40beeb8 100644
--- a/frontend/src/pages/ItemDetail.tsx
+++ b/frontend/src/pages/ItemDetail.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import { useParams, useNavigate } from "react-router-dom";
+import { useParams, useNavigate } from "react-router";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import { Item, Rental } from "../types";
diff --git a/frontend/src/pages/ItemList.tsx b/frontend/src/pages/ItemList.tsx
index 6dd1b47..b5e31b9 100644
--- a/frontend/src/pages/ItemList.tsx
+++ b/frontend/src/pages/ItemList.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect, useRef } from "react";
-import { useSearchParams, useNavigate } from "react-router-dom";
+import { useSearchParams, useNavigate } from "react-router";
import { Item } from "../types";
import { itemAPI } from "../services/api";
import ItemCard from "../components/ItemCard";
diff --git a/frontend/src/pages/MyPosts.tsx b/frontend/src/pages/MyPosts.tsx
index 4a3ca44..53ee7f8 100644
--- a/frontend/src/pages/MyPosts.tsx
+++ b/frontend/src/pages/MyPosts.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
-import { Link } from 'react-router-dom';
+import { Link } from 'react-router';
import { useAuth } from '../contexts/AuthContext';
import { forumAPI } from '../services/api';
import { ForumPost } from '../types';
diff --git a/frontend/src/pages/NotFound.tsx b/frontend/src/pages/NotFound.tsx
index 05c6cf4..fb93f0d 100644
--- a/frontend/src/pages/NotFound.tsx
+++ b/frontend/src/pages/NotFound.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { Link } from "react-router-dom";
+import { Link } from "react-router";
const NotFound: React.FC = () => {
return (
diff --git a/frontend/src/pages/Owning.tsx b/frontend/src/pages/Owning.tsx
index b2a8a39..c902889 100644
--- a/frontend/src/pages/Owning.tsx
+++ b/frontend/src/pages/Owning.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import { Link, useNavigate } from "react-router-dom";
+import { Link, useNavigate } from "react-router";
import { useAuth } from "../contexts/AuthContext";
import api from "../services/api";
import { Item, Rental, ConditionCheck } from "../types";
diff --git a/frontend/src/pages/Profile.tsx b/frontend/src/pages/Profile.tsx
index 71fd061..e73891a 100644
--- a/frontend/src/pages/Profile.tsx
+++ b/frontend/src/pages/Profile.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect, useCallback, useMemo } from "react";
-import { useNavigate } from "react-router-dom";
+import { useNavigate } from "react-router";
import { useAuth } from "../contexts/AuthContext";
import { userAPI, itemAPI, rentalAPI, addressAPI, conditionCheckAPI } from "../services/api";
import { User, Item, Rental, Address, ConditionCheck } from "../types";
diff --git a/frontend/src/pages/PublicProfile.tsx b/frontend/src/pages/PublicProfile.tsx
index 0d2b336..2156899 100644
--- a/frontend/src/pages/PublicProfile.tsx
+++ b/frontend/src/pages/PublicProfile.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
-import { useParams, useNavigate } from 'react-router-dom';
+import { useParams, useNavigate } from 'react-router';
import { User, Item } from '../types';
import { userAPI, itemAPI } from '../services/api';
import { getImageUrl } from '../services/uploadService';
diff --git a/frontend/src/pages/RentItem.tsx b/frontend/src/pages/RentItem.tsx
index 49517f2..8119682 100644
--- a/frontend/src/pages/RentItem.tsx
+++ b/frontend/src/pages/RentItem.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import { useParams, useNavigate, useSearchParams } from "react-router-dom";
+import { useParams, useNavigate, useSearchParams } from "react-router";
import { Item } from "../types";
import { useAuth } from "../contexts/AuthContext";
import { itemAPI, rentalAPI } from "../services/api";
diff --git a/frontend/src/pages/Renting.tsx b/frontend/src/pages/Renting.tsx
index c1d5370..12925a3 100644
--- a/frontend/src/pages/Renting.tsx
+++ b/frontend/src/pages/Renting.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import { Link, useNavigate } from "react-router-dom";
+import { Link, useNavigate } from "react-router";
import { useAuth } from "../contexts/AuthContext";
import { rentalAPI, conditionCheckAPI } from "../services/api";
import { getImageUrl } from "../services/uploadService";
diff --git a/frontend/src/pages/ResetPassword.tsx b/frontend/src/pages/ResetPassword.tsx
index ab04a1f..38ae02d 100644
--- a/frontend/src/pages/ResetPassword.tsx
+++ b/frontend/src/pages/ResetPassword.tsx
@@ -1,5 +1,5 @@
import React, { useEffect, useState, useRef } from 'react';
-import { useNavigate, useSearchParams, Link } from 'react-router-dom';
+import { useNavigate, useSearchParams, Link } from 'react-router';
import { useAuth } from '../contexts/AuthContext';
import { authAPI } from '../services/api';
import PasswordInput from '../components/PasswordInput';
diff --git a/frontend/src/pages/VerifyEmail.tsx b/frontend/src/pages/VerifyEmail.tsx
index 9858c33..70002a7 100644
--- a/frontend/src/pages/VerifyEmail.tsx
+++ b/frontend/src/pages/VerifyEmail.tsx
@@ -1,5 +1,5 @@
import React, { useEffect, useState, useRef } from "react";
-import { useNavigate, useSearchParams, Link } from "react-router-dom";
+import { useNavigate, useSearchParams, Link } from "react-router";
import { useAuth } from "../contexts/AuthContext";
import { authAPI } from "../services/api";
diff --git a/frontend/src/services/api.ts b/frontend/src/services/api.ts
index c672f51..cc5450d 100644
--- a/frontend/src/services/api.ts
+++ b/frontend/src/services/api.ts
@@ -160,7 +160,7 @@ api.interceptors.response.use(
isRefreshing = false;
processQueue(refreshError as AxiosError);
- // Refresh failed - let React Router handle redirects via PrivateRoute
+ // Refresh failed - let React Router handle redirects via ProtectedLayout
return Promise.reject(refreshError);
}
}