Refactoring

This commit is contained in:
2025-01-19 23:08:39 -06:00
parent e7b4bbb82b
commit da07e9a632
2 changed files with 99 additions and 188 deletions

View File

@@ -1,179 +1,51 @@
import { useEffect, useState } from 'react';
import { ISiteNavProps } from './ISiteNavProps';
import { useNavigate } from 'react-router-dom';
import { useAppContext } from '../../hooks/appContext/UseAppContext';
import {
Avatar,
Button,
IconButton,
Menu,
MenuItem,
Navbar,
PlaneIcon,
SignOutIcon,
Spinner,
Typography
} from '@noahspan/noahspan-components';
import { useIsAuthenticated, useMsal } from '@azure/msal-react';
import { InteractionStatus } from '@azure/msal-browser';
import { useAccessToken } from '../../hooks/accessToken/UseAcessToken';
import { useHttpClient } from '../../hooks/httpClient/UseHttpClient';
import { useEffect } from 'react';
import { Route, Routes } from 'react-router-dom';
import Pilots from './components/pilots/Pilots';
import Logbook from './components/logbook/Logbook';
import { useAppContext } from './hooks/appContext/UseAppContext';
import { AxiosInstance, AxiosResponse } from 'axios';
import { User } from '@microsoft/microsoft-graph-types';
import { EventMessage, EventPayload, EventType } from '@azure/msal-browser';
import { useHttpClient } from './hooks/httpClient/UseHttpClient';
import { useFeatureFlag } from './hooks/featureFlag/UseFeatureFlag';
import SiteNav from './components/siteNav/SiteNav';
type EventPayloadExtended = EventPayload & { accessToken: string };
const SiteNav: React.FC<unknown> = () => {
const [loading, setLoading] = useState<boolean>(false);
const [userPhoto, setUserPhoto] = useState<string>();
const App: React.FC<unknown> = () => {
const httpClient: AxiosInstance = useHttpClient();
const appContext = useAppContext();
const isAuthenticated = useIsAuthenticated();
const { getAccessToken } = useAccessToken();
const { inProgress, instance } = useMsal();
const navigate = useNavigate();
const pages = [
{
name: 'Logbook',
url: '/'
},
{
name: 'Pilots',
url: '/pilots'
}
];
const handleSignIn = async () => {
await instance.loginRedirect({
scopes: [`api://${import.meta.env.VITE_CLIENT_ID}/user_impersonation`]
});
};
const handleSignOut = () => {
instance.logoutRedirect();
};
const getUserProfile = async (accessToken: string): Promise<User> => {
try {
const response: AxiosResponse = await httpClient.get(`api/userProfile`, {
headers: {
Authorization: accessToken
}
});
const userProfile: User = response.data;
return userProfile;
} catch (error) {
throw new Error();
}
};
const getUserPhoto = async (accessToken: string): Promise<string> => {
try {
const response: AxiosResponse = await httpClient.get(`api/userPhoto`, {
headers: {
Authorization: accessToken
},
responseType: 'arraybuffer'
});
const arrayBufferView = new Uint8Array(response.data);
const blob = new Blob([arrayBufferView], { type: 'image/png' });
const imageUrl = window.URL.createObjectURL(blob);
// useEffect(() => {
// const getFeatureFlags = async () => {
// try {
// const featureFlagKeys: string = 'flying-pilots';
// const response: AxiosResponse = await httpClient.get(
// `api/featureFlags?keys=${featureFlagKeys}&label=${import.meta.env.MODE}`
// );
// const featureFlags: { key: string; enabled: boolean }[] = response.data;
return imageUrl;
} catch (error) {
console.log(error);
throw new Error();
}
};
const handlePageClick = (url: string) => {
navigate(url);
};
// if (featureFlags.length > 0) {
// appContext.dispatch({
// type: 'SET_FEATURE_FLAGS',
// payload: featureFlags
// });
// }
// } catch (error) {
// console.log(error);
// }
// };
const Settings = () => {
return (
<MenuItem onClick={handleSignOut}>
<SignOutIcon />
<Typography sx={{ marginLeft: '10px', textAlign: 'center' }}>
Sign Out
</Typography>
</MenuItem>
);
};
useEffect(() => {
const callback = instance.addEventCallback(
async (message: EventMessage) => {
if (message.eventType === EventType.LOGIN_SUCCESS) {
try {
setLoading(true);
const eventPayload: EventPayloadExtended =
message.payload as EventPayloadExtended;
const userProfile: User = await getUserProfile(
eventPayload.accessToken
);
const userPhoto = await getUserPhoto(eventPayload.accessToken);
appContext.dispatch({
type: 'SET_USER_PROFILE',
payload: userProfile
});
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
}
}
);
return () => {
if (callback) {
instance.removeEventCallback(callback);
appContext.dispatch({ type: 'SET_USER_PROFILE', payload: {} });
}
};
}, []);
useEffect(() => {
const setUserProfile = async () => {
try {
setLoading(true);
const accessToken: string = await getAccessToken();
const userProfile = await getUserProfile(accessToken);
const userPhoto = await getUserPhoto(accessToken);
setUserPhoto(userPhoto);
appContext.dispatch({
type: 'SET_USER_PROFILE',
payload: userProfile
});
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
};
if (
isAuthenticated &&
Object.keys(appContext.state.userProfile).length === 0
) {
setUserProfile();
}
}, [isAuthenticated]);
// getFeatureFlags();
// }, []);
return (
<Navbar
handlePageClick={handlePageClick}
handleSignIn={handleSignIn}
isAuthenticated={isAuthenticated}
logo={<PlaneIcon size="2x" />}
pages={pages}
settings={<Settings />}
userPhoto={userPhoto}
/>
<div>
<SiteNav />
<Routes>
{/* {useFeatureFlag('flying-pilots')?.enabled && ( */}
<Route path="/pilots" element={<Pilots />} />
{/* )} */}
<Route path="/" element={<Logbook />} />
</Routes>
</div>
);
};
export default SiteNav;
export default App;

View File

@@ -1,27 +1,37 @@
import { useEffect, useState } from 'react';
import { ISiteNavProps } from './ISiteNavProps';
import { useNavigate } from 'react-router-dom';
import { useAppContext } from '../../hooks/appContext/UseAppContext';
import {
Avatar,
Button,
IconButton,
Menu,
MenuItem,
Navbar,
PlaneIcon,
SignOutIcon,
Spinner,
Typography
} from '@noahspan/noahspan-components';
import { useIsAuthenticated, useMsal } from '@azure/msal-react';
import { InteractionStatus } from '@azure/msal-browser';
import { useAccessToken } from '../../hooks/accessToken/UseAcessToken';
import { useHttpClient } from '../../hooks/httpClient/UseHttpClient';
import { AxiosInstance, AxiosResponse } from 'axios';
import { User } from '@microsoft/microsoft-graph-types';
import { EventMessage, EventPayload, EventType } from '@azure/msal-browser';
type EventPayloadExtended = EventPayload & { accessToken: string };
const SiteNav: React.FC<unknown> = () => {
const [loading, setLoading] = useState<boolean>(false);
const [userPhoto, setUserPhoto] = useState<string>();
const httpClient: AxiosInstance = useHttpClient();
const appContext = useAppContext();
const isAuthenticated = useIsAuthenticated();
const { getAccessToken } = useAccessToken();
const { instance } = useMsal();
const { inProgress, instance } = useMsal();
const navigate = useNavigate();
const pages = [
{
@@ -33,22 +43,14 @@ const SiteNav: React.FC<unknown> = () => {
url: '/pilots'
}
];
const handleSignInRedirect = () => {
instance
.loginRedirect({
scopes: [`api://${import.meta.env.VITE_CLIENT_ID}/user_impersonation`]
})
.catch((error) => console.log(error));
const handleSignIn = async () => {
await instance.loginRedirect({
scopes: [`api://${import.meta.env.VITE_CLIENT_ID}/user_impersonation`]
});
};
const handleSignOut = () => {
instance.logoutRedirect();
};
const handleSignOutRedirect = () => {
instance.logoutRedirect({
postLogoutRedirectUri: '/'
})
window.location.reload();
}
const getUserProfile = async (accessToken: string): Promise<User> => {
try {
const response: AxiosResponse = await httpClient.get(`api/userProfile`, {
@@ -63,7 +65,6 @@ const SiteNav: React.FC<unknown> = () => {
throw new Error();
}
};
const getUserPhoto = async (accessToken: string): Promise<string> => {
try {
const response: AxiosResponse = await httpClient.get(`api/userPhoto`, {
@@ -82,14 +83,13 @@ const SiteNav: React.FC<unknown> = () => {
throw new Error();
}
};
const handlePageClick = (url: string) => {
navigate(url);
};
const Settings = () => {
return (
<MenuItem onClick={handleSignOutRedirect}>
<MenuItem onClick={handleSignOut}>
<SignOutIcon />
<Typography sx={{ marginLeft: '10px', textAlign: 'center' }}>
Sign Out
@@ -98,9 +98,46 @@ const SiteNav: React.FC<unknown> = () => {
);
};
useEffect(() => {
const callback = instance.addEventCallback(
async (message: EventMessage) => {
if (message.eventType === EventType.LOGIN_SUCCESS) {
try {
setLoading(true);
const eventPayload: EventPayloadExtended =
message.payload as EventPayloadExtended;
const userProfile: User = await getUserProfile(
eventPayload.accessToken
);
const userPhoto = await getUserPhoto(eventPayload.accessToken);
appContext.dispatch({
type: 'SET_USER_PROFILE',
payload: userProfile
});
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
}
}
);
return () => {
if (callback) {
instance.removeEventCallback(callback);
appContext.dispatch({ type: 'SET_USER_PROFILE', payload: {} });
}
};
}, []);
useEffect(() => {
const setUserProfile = async () => {
try {
setLoading(true);
const accessToken: string = await getAccessToken();
const userProfile = await getUserProfile(accessToken);
const userPhoto = await getUserPhoto(accessToken);
@@ -113,6 +150,8 @@ const SiteNav: React.FC<unknown> = () => {
});
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
};
@@ -127,7 +166,7 @@ const SiteNav: React.FC<unknown> = () => {
return (
<Navbar
handlePageClick={handlePageClick}
handleSignIn={handleSignInRedirect}
handleSignIn={handleSignIn}
isAuthenticated={isAuthenticated}
logo={<PlaneIcon size="2x" />}
pages={pages}
@@ -137,4 +176,4 @@ const SiteNav: React.FC<unknown> = () => {
);
};
export default SiteNav;
export default SiteNav;