Migrated to react router v7
This commit is contained in:
@@ -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: <RootLayout />,
|
||||
children: [
|
||||
// Public routes
|
||||
{ path: '/', element: <Home /> },
|
||||
{ path: '/auth/google/callback', element: <GoogleCallback /> },
|
||||
{ path: '/verify-email', element: <VerifyEmail /> },
|
||||
{ path: '/reset-password', element: <ResetPassword /> },
|
||||
{ path: '/items', element: <ItemList /> },
|
||||
{ path: '/items/:id', element: <ItemDetail /> },
|
||||
{ path: '/users/:id', element: <PublicProfile /> },
|
||||
{ path: '/forum', element: <ForumPosts /> },
|
||||
{ path: '/forum/:id', element: <ForumPostDetail /> },
|
||||
{ path: '/faq', element: <FAQ /> },
|
||||
|
||||
// Protected routes group
|
||||
{
|
||||
element: <ProtectedLayout />,
|
||||
children: [
|
||||
{ path: '/items/:id/edit', element: <EditItem /> },
|
||||
{ path: '/items/:id/rent', element: <RentItem /> },
|
||||
{ path: '/create-item', element: <CreateItem /> },
|
||||
{ path: '/renting', element: <Renting /> },
|
||||
{ path: '/complete-payment/:rentalId', element: <CompletePayment /> },
|
||||
{ path: '/owning', element: <Owning /> },
|
||||
{ path: '/profile', element: <Profile /> },
|
||||
{ path: '/messages', element: <Messages /> },
|
||||
{ path: '/forum/create', element: <CreateForumPost /> },
|
||||
{ path: '/forum/:id/edit', element: <CreateForumPost /> },
|
||||
{ path: '/my-posts', element: <MyPosts /> },
|
||||
{ path: '/earnings', element: <EarningsDashboard /> },
|
||||
],
|
||||
},
|
||||
|
||||
// Catch-all route
|
||||
{ path: '*', element: <NotFound /> },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const AppContent: React.FC = () => {
|
||||
const { showAuthModal, authModalMode, closeAuthModal, user } = useAuth();
|
||||
const [hasAlphaAccess, setHasAlphaAccess] = useState<boolean | null>(null);
|
||||
const [checkingAccess, setCheckingAccess] = useState(true);
|
||||
|
||||
// Step-up authentication state
|
||||
const [showStepUpModal, setShowStepUpModal] = useState(false);
|
||||
const [stepUpAction, setStepUpAction] = useState<string | undefined>();
|
||||
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 <AlphaGate />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Router>
|
||||
<div className="d-flex flex-column min-vh-100">
|
||||
<Navbar />
|
||||
<main className="flex-grow-1">
|
||||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/auth/google/callback" element={<GoogleCallback />} />
|
||||
<Route path="/verify-email" element={<VerifyEmail />} />
|
||||
<Route path="/reset-password" element={<ResetPassword />} />
|
||||
<Route path="/items" element={<ItemList />} />
|
||||
<Route path="/items/:id" element={<ItemDetail />} />
|
||||
<Route path="/users/:id" element={<PublicProfile />} />
|
||||
<Route
|
||||
path="/items/:id/edit"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<EditItem />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/items/:id/rent"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<RentItem />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/create-item"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<CreateItem />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/renting"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<Renting />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/complete-payment/:rentalId"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<CompletePayment />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/owning"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<Owning />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/profile"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<Profile />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/messages"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<Messages />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route path="/forum" element={<ForumPosts />} />
|
||||
<Route path="/forum/:id" element={<ForumPostDetail />} />
|
||||
<Route
|
||||
path="/forum/create"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<CreateForumPost />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/forum/:id/edit"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<CreateForumPost />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/my-posts"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<MyPosts />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/earnings"
|
||||
element={
|
||||
<PrivateRoute>
|
||||
<EarningsDashboard />
|
||||
</PrivateRoute>
|
||||
}
|
||||
/>
|
||||
<Route path="/faq" element={<FAQ />} />
|
||||
<Route path="*" element={<NotFound />} />
|
||||
</Routes>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
</Router>
|
||||
|
||||
<AuthModal
|
||||
show={showAuthModal}
|
||||
onHide={closeAuthModal}
|
||||
initialMode={authModalMode}
|
||||
/>
|
||||
|
||||
{/* Show feedback button for authenticated users */}
|
||||
{user && <FeedbackButton />}
|
||||
|
||||
{/* Global Step-Up Authentication Modal */}
|
||||
<TwoFactorVerifyModal
|
||||
show={showStepUpModal}
|
||||
onHide={handleStepUpClose}
|
||||
onSuccess={handleStepUpSuccess}
|
||||
action={stepUpAction}
|
||||
methods={stepUpMethods}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
return <RouterProvider router={router} />;
|
||||
};
|
||||
|
||||
const AppWithSocket: React.FC = () => {
|
||||
@@ -274,4 +139,4 @@ function App() {
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
export default App;
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
const Footer: React.FC = () => {
|
||||
return (
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Link } from "react-router";
|
||||
|
||||
interface PricingFormProps {
|
||||
pricePerHour: number | string;
|
||||
|
||||
@@ -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<PrivateRouteProps> = ({ children }) => {
|
||||
const ProtectedLayout: React.FC = () => {
|
||||
const { user, loading, openAuthModal } = useAuth();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -41,7 +38,7 @@ const PrivateRoute: React.FC<PrivateRouteProps> = ({ children }) => {
|
||||
);
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
return <Outlet />;
|
||||
};
|
||||
|
||||
export default PrivateRoute;
|
||||
export default ProtectedLayout;
|
||||
77
frontend/src/components/RootLayout.tsx
Normal file
77
frontend/src/components/RootLayout.tsx
Normal file
@@ -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<string | undefined>();
|
||||
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 (
|
||||
<>
|
||||
<div className="d-flex flex-column min-vh-100">
|
||||
<Navbar />
|
||||
<main className="flex-grow-1">
|
||||
<Outlet />
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
|
||||
<AuthModal
|
||||
show={showAuthModal}
|
||||
onHide={closeAuthModal}
|
||||
initialMode={authModalMode}
|
||||
/>
|
||||
|
||||
{/* Show feedback button for authenticated users */}
|
||||
{user && <FeedbackButton />}
|
||||
|
||||
{/* Global Step-Up Authentication Modal */}
|
||||
<TwoFactorVerifyModal
|
||||
show={showStepUpModal}
|
||||
onHide={handleStepUpClose}
|
||||
onSuccess={handleStepUpSuccess}
|
||||
action={stepUpAction}
|
||||
methods={stepUpMethods}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default RootLayout;
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Link } from "react-router";
|
||||
|
||||
interface FAQItem {
|
||||
question: string;
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Link } from "react-router";
|
||||
|
||||
const NotFound: React.FC = () => {
|
||||
return (
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user