diff --git a/src/applications/accredited-representative-portal/auth.js b/src/applications/accredited-representative-portal/auth.js new file mode 100644 index 000000000000..7390ad8fe493 --- /dev/null +++ b/src/applications/accredited-representative-portal/auth.js @@ -0,0 +1,21 @@ +import { apiRequest } from '@department-of-veterans-affairs/platform-utilities/api'; + +let user = null; + +export async function fetchUser() { + try { + user = await apiRequest('/accredited_representative_portal/v0/user'); + return user; + } catch (error) { + user = null; + throw error; + } +} + +export function getUser() { + return user; +} + +export function isAuthenticated() { + return user !== null; +} diff --git a/src/applications/accredited-representative-portal/components/common/Header/common/UserNav.jsx b/src/applications/accredited-representative-portal/components/common/Header/common/UserNav.jsx index 2c26fd354adc..4d84fd551a37 100644 --- a/src/applications/accredited-representative-portal/components/common/Header/common/UserNav.jsx +++ b/src/applications/accredited-representative-portal/components/common/Header/common/UserNav.jsx @@ -1,12 +1,7 @@ -import React, { useState, useRef, useEffect } from 'react'; -import { useSelector } from 'react-redux'; +import React, { useState, useRef, useEffect, useContext } from 'react'; import PropTypes from 'prop-types'; - +import UserContext from '../../../../userContext'; import { SIGN_IN_URL, SIGN_OUT_URL } from '../../../../constants'; -import { - selectUserProfile, - selectIsUserLoading, -} from '../../../../selectors/user'; const generateUniqueId = () => `account-menu-${Math.random() @@ -14,8 +9,9 @@ const generateUniqueId = () => .substring(2, 11)}`; const UserNav = ({ isMobile }) => { - const profile = useSelector(selectUserProfile); - const isLoading = useSelector(selectIsUserLoading); + const user = useContext(UserContext); + const profile = user?.profile; + const isLoading = !profile; const uniqueId = useRef(generateUniqueId()); const [isDropdownOpen, setDropdownOpen] = useState(false); @@ -130,12 +126,7 @@ const UserNav = ({ isMobile }) => { }; UserNav.propTypes = { - isLoading: PropTypes.bool, isMobile: PropTypes.bool, - profile: PropTypes.shape({ - firstName: PropTypes.string, - lastName: PropTypes.string, - }), }; export default UserNav; diff --git a/src/applications/accredited-representative-portal/routes.jsx b/src/applications/accredited-representative-portal/routes.jsx index a013175aea1e..b903708d0187 100644 --- a/src/applications/accredited-representative-portal/routes.jsx +++ b/src/applications/accredited-representative-portal/routes.jsx @@ -1,5 +1,11 @@ import React from 'react'; -import { createBrowserRouter, useNavigation, Outlet } from 'react-router-dom'; +import { + createBrowserRouter, + useNavigation, + useLoaderData, + Navigate, + Outlet, +} from 'react-router-dom'; import { VaLoadingIndicator } from '@department-of-veterans-affairs/component-library/dist/react-bindings'; import App from './containers/App'; @@ -12,6 +18,9 @@ import POARequestDetailsPage, { poaRequestLoader, } from './containers/POARequestDetailsPage'; import ErrorMessage from './components/common/ErrorMessage'; +import UserContext from './userContext'; +import { userLoader } from './userLoader'; +import { SIGN_IN_URL } from './constants'; const LoadingWrapper = () => { const navigation = useNavigation(); @@ -23,6 +32,20 @@ const LoadingWrapper = () => { return ; }; +const AuthenticatedRoutes = () => { + const user = useLoaderData(); + + if (!user || !user.profile) { + return ; + } + + return ( + + + + ); +}; + const router = createBrowserRouter( [ { @@ -33,10 +56,12 @@ const router = createBrowserRouter( element: , }, { - element: , + path: '/', + element: , children: [ { - element: , + loader: userLoader, + element: , children: [ { path: 'poa-requests', diff --git a/src/applications/accredited-representative-portal/userContext.js b/src/applications/accredited-representative-portal/userContext.js new file mode 100644 index 000000000000..ae66c8cdf5a0 --- /dev/null +++ b/src/applications/accredited-representative-portal/userContext.js @@ -0,0 +1,5 @@ +import { createContext } from 'react'; + +const UserContext = createContext(null); + +export default UserContext; diff --git a/src/applications/accredited-representative-portal/userLoader.js b/src/applications/accredited-representative-portal/userLoader.js new file mode 100644 index 000000000000..3e9f341397ab --- /dev/null +++ b/src/applications/accredited-representative-portal/userLoader.js @@ -0,0 +1,16 @@ +import { redirect } from 'react-router'; +import { fetchUser, isAuthenticated } from './auth'; +import { SIGN_IN_URL } from './constants'; + +export async function userLoader() { + try { + const user = await fetchUser(); + if (!isAuthenticated()) { + redirect(SIGN_IN_URL); + } + return user; + } catch (error) { + redirect(SIGN_IN_URL); + return null; + } +}