Skip to content

Commit

Permalink
Merge pull request #1021 from MTES-MCT/chore-upgrade-react-router
Browse files Browse the repository at this point in the history
Upgrade react router v5 to v6
  • Loading branch information
Falinor authored Nov 27, 2024
2 parents baa97bf + d08c00b commit 022e38d
Show file tree
Hide file tree
Showing 48 changed files with 809 additions and 763 deletions.
4 changes: 1 addition & 3 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
"classnames": "^2.5.1",
"date-fns": "^2.30.0",
"fetch-intercept": "^2.4.0",
"history": "^5.3.0",
"immutable": "^5.0.0",
"jose": "^4.15.9",
"lexical": "^0.18.0",
Expand All @@ -59,7 +58,7 @@
"react-map-gl": "^7.1.7",
"react-redux": "^8.1.3",
"react-redux-loading-bar": "^5.0.8",
"react-router-dom": "^5.3.4",
"react-router-dom": "^6.28.0",
"react-scripts": "^5.0.1",
"react-toastify": "^10.0.5",
"react-use": "^17.5.1",
Expand Down Expand Up @@ -89,7 +88,6 @@
"@types/randomstring": "^1.3.0",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.0",
"@types/react-router-dom": "^5.3.3",
"@types/uuid": "^9.0.8",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
Expand Down
167 changes: 69 additions & 98 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,97 +1,95 @@
import { useMatomo } from '@jonkoops/matomo-tracker-react';
import React, { useEffect } from 'react';
import { useEffect } from 'react';
import { hideLoading, showLoading } from 'react-redux-loading-bar';
import {
BrowserRouter,
Redirect,
createBrowserRouter,
createRoutesFromElements,
Navigate,
Route,
RouteProps,
Switch
RouterProvider
} from 'react-router-dom';

import './App.scss';
import Footer from './components/Footer/Footer';
import LoginView from './views/Login/LoginView';
import { useAppDispatch, useAppSelector } from './hooks/useStore';
import AuthenticatedLayout from './layouts/AuthenticatedLayout';
import HousingListView from './views/HousingList/HousingListView';
import FetchInterceptor from './components/FetchInterceptor/FetchInterceptor';
import OwnerView from './views/Owner/OwnerView';
import CampaignsListView from './views/Campaign/CampaignListView';
import CampaignView from './views/Campaign/CampaignView';
import ScrollToTop from './components/ScrollToTop/ScrollToTop';
import AccountPasswordView from './views/Account/AccountPasswordView';
import GroupView from './views/Group/GroupView';
import CampaignsListView from './views/Campaign/CampaignListView';
import HousingView from './views/Housing/HousingView';
import ResourcesView from './views/Resources/ResourcesView';
import AccountCreationView from './views/Account/AccountCreationView';
import ForgottenPasswordView from './views/Account/ForgottenPasswordView';
import ResetPasswordView from './views/Account/ResetPasswordView';
import { useUser } from './hooks/useUser';
import { useAppDispatch, useAppSelector } from './hooks/useStore';
import OwnerView from './views/Owner/OwnerView';
import StatusView from './views/Resources/StatusView';
import ResourcesView from './views/Resources/ResourcesView';
import AccountView from './views/Account/AccountView';
import GroupView from './views/Group/GroupView';
import AccountPasswordView from './views/Account/AccountPasswordView';
import UsersView from './views/Users/UsersView';
import TerritoryEstablishmentsView from './views/TerritoryEstablishments/TerritoryEstablishmentsView';
import SmallHeader from './components/Header/SmallHeader';
import Header from './components/Header/Header';
import GuestLayout from './layouts/GuestLayout';
import AccountCreationView from './views/Account/AccountCreationView';
import LoginView from './views/Login/LoginView';
import ForgottenPasswordView from './views/Account/ForgottenPasswordView';
import ResetPasswordView from './views/Account/ResetPasswordView';
import NotFoundView from './views/NotFoundView';

const router = createBrowserRouter(
createRoutesFromElements(
<Route>
<Route element={<AuthenticatedLayout />}>
<Route path="/" element={<Navigate to="/parc-de-logements" />} />
<Route path="/parc-de-logements" element={<HousingListView />} />
<Route
path="/parc-de-logements/campagnes/:id"
element={<CampaignView />}
/>
<Route path="/groupes/:id" element={<GroupView />} />
<Route path="/campagnes" element={<CampaignsListView />} />
<Route path="/campagnes/:id" element={<CampaignView />} />
<Route
path="/proprietaires/:ownerId/logements/:housingId"
element={<HousingView />}
/>
<Route path="/proprietaires/:ownerId" element={<OwnerView />} />
<Route
path="/logements/:housingId/proprietaires/:ownerId"
element={<OwnerView />}
/>
<Route path="/logements/:housingId" element={<HousingView />} />
<Route path="/ressources/statuts" element={<StatusView />} />
<Route path="/ressources" element={<ResourcesView />} />

<Route path="/compte" element={<AccountView />} />
<Route path="/compte/mot-de-passe" element={<AccountPasswordView />} />

<Route path="/utilisateurs" element={<UsersView />} />
<Route
path="/autres-etablissements"
element={<TerritoryEstablishmentsView />}
/>
</Route>

const authenticatedRoutes: RouteProps[] = [
{
path: '/parc-de-logements',
component: HousingListView
},
// TODO: remove this
{ path: '/parc-de-logements/campagnes/:id', component: CampaignView },
{ path: '/groupes/:id', component: GroupView },
{ path: '/campagnes', component: CampaignsListView },
{ path: '/campagnes/:id', component: CampaignView },
{
path: '/proprietaires/:ownerId/logements/:housingId',
component: HousingView
},
{ path: '/proprietaires/:ownerId', component: OwnerView },
{
path: '/logements/:housingId/proprietaires/:ownerId',
component: OwnerView
},
{ path: '/logements/:housingId', component: HousingView },
{ path: '/ressources/statuts', component: StatusView },
{ path: '/ressources', component: ResourcesView },
<Route element={<GuestLayout />}>
<Route path="/inscription/*" element={<AccountCreationView />} />
<Route path="/connexion" element={<LoginView />} />
<Route
path="/mot-de-passe/oublie"
element={<ForgottenPasswordView />}
/>
<Route path="/mot-de-passe/nouveau" element={<ResetPasswordView />} />
<Route path="/admin" element={<LoginView />} />
</Route>

{ path: '/compte', component: AccountView },
{ path: '/compte/mot-de-passe', component: AccountPasswordView },
{ path: '/utilisateurs', component: UsersView },
{ path: '/autres-etablissements', component: TerritoryEstablishmentsView }
];
const guestRoutes: RouteProps[] = [
{ path: '/inscription*', component: AccountCreationView },
{ path: '/connexion', component: LoginView },
{
path: '/mot-de-passe/oublie',
component: ForgottenPasswordView
},
{
path: '/mot-de-passe/nouveau',
component: ResetPasswordView
},
{ path: '/admin', component: LoginView }
];
<Route path="*" element={<NotFoundView />} />
</Route>
)
);

function App() {
const { pushInstruction } = useMatomo();
const { isAuthenticated, user } = useUser();
const dispatch = useAppDispatch();
const isSomeQueryPending = useAppSelector((state) =>
Object.values(state.api.queries).some(
(query) => query?.status === 'pending'
)
);

FetchInterceptor();

useEffect(() => {
pushInstruction('setUserId', user?.id);
}, [pushInstruction, user]);

useEffect(() => {
if (isSomeQueryPending) {
dispatch(showLoading());
Expand All @@ -100,34 +98,7 @@ function App() {
}
}, [dispatch, isSomeQueryPending]);

const routes = (isAuthenticated ? authenticatedRoutes : guestRoutes)
.map((route) => (
<Route
exact
path={route.path}
component={route.component}
key={`route_${route.path}`}
/>
));

const redirection = isAuthenticated ? '/parc-de-logements' : '/connexion';

return (
<React.Suspense fallback={<></>}>
<BrowserRouter>
{isAuthenticated ? <SmallHeader /> : <Header />}
<ScrollToTop />

<Switch>
{routes}
<Route path="*">
<Redirect to={redirection} />
</Route>
</Switch>
<Footer />
</BrowserRouter>
</React.Suspense>
);
return <RouterProvider router={router} />;
}

export default App;
24 changes: 24 additions & 0 deletions frontend/src/components/Auth/RequireAuth.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { PropsWithChildren } from 'react';
import { Navigate, useLocation } from 'react-router-dom';

import { useUser } from '../../hooks/useUser';
import { useFetchInterceptor } from '../../hooks/useFetchInterceptor';

interface RequireAuthProps {}

function RequireAuth(props: PropsWithChildren<RequireAuthProps>) {
const { isAuthenticated } = useUser();
const location = useLocation();

useFetchInterceptor();

if (isAuthenticated) {
return props.children;
}

return (
<Navigate to="/connexion" replace state={{ path: location.pathname }} />
);
}

export default RequireAuth;
18 changes: 18 additions & 0 deletions frontend/src/components/Auth/RequireGuest.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { PropsWithChildren } from 'react';

import { useUser } from '../../hooks/useUser';
import NotFoundView from '../../views/NotFoundView';

interface RequireGuestProps {}

function RequireGuest(props: PropsWithChildren<RequireGuestProps>) {
const { isGuest } = useUser();

if (isGuest) {
return props.children;
}

return <NotFoundView />;
}

export default RequireGuest;
29 changes: 0 additions & 29 deletions frontend/src/components/FetchInterceptor/FetchInterceptor.tsx

This file was deleted.

24 changes: 12 additions & 12 deletions frontend/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ function Header() {
linkProps: {
to: getUserNavItem(navItem).url,
'data-testid': `fr-header-nav-item-${getUserNavItem(
navItem,
).url.substring(1)}`,
navItem
).url.substring(1)}`
},
text: getUserNavItem(navItem).label,
isActive: location.pathname.startsWith(getUserNavItem(navItem).url),
isActive: location.pathname.startsWith(getUserNavItem(navItem).url)
});

return (
Expand All @@ -55,23 +55,23 @@ function Header() {
Ministère <br />
du Logement <br />
et de la Rénovation <br />
urbaine
urbaine
</>
}
homeLinkProps={{
to: '/',
title: 'Accueil - Zéro Logement Vacant',
title: 'Accueil - Zéro Logement Vacant'
}}
serviceTitle="Zéro Logement Vacant"
serviceTagline={
isAuthenticated ? (
(isAdmin || isVisitor) ? (
isAdmin || isVisitor ? (
<EstablishmentSearchableSelect
initialEstablishmentOption={
authUser
? {
value: authUser.establishment.id,
label: authUser.establishment.name,
label: authUser.establishment.name
}
: undefined
}
Expand Down Expand Up @@ -104,24 +104,24 @@ function Header() {
<AccountSideMenu />
</Container>
}
/>,
/>
]
: [
{
iconId: 'fr-icon-user-fill',
linkProps: {
to: '/connexion',
to: '/connexion'
},
text: 'Connexion',
},
text: 'Connexion'
}
]
}
navigation={
isAuthenticated
? [
getMainNavigationItem(UserNavItems.HousingList),
getMainNavigationItem(UserNavItems.Campaign),
getMainNavigationItem(UserNavItems.Resources),
getMainNavigationItem(UserNavItems.Resources)
]
: withNavItems && []
}
Expand Down
Loading

0 comments on commit 022e38d

Please sign in to comment.