Refactoring
This commit is contained in:
206
app/src/App.tsx
206
app/src/App.tsx
@@ -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;
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user