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;
+ }
+}