diff --git a/app/src/App.tsx b/app/src/App.tsx index 50eb147..c78d675 100644 --- a/app/src/App.tsx +++ b/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 = () => { - const [loading, setLoading] = useState(false); - const [userPhoto, setUserPhoto] = useState(); +const App: React.FC = () => { 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 => { - 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 => { - 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 ( - - - - Sign Out - - - ); - }; - - 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 ( - } - pages={pages} - settings={} - userPhoto={userPhoto} - /> +
+ + + {/* {useFeatureFlag('flying-pilots')?.enabled && ( */} + } /> + {/* )} */} + } /> + +
); }; -export default SiteNav; \ No newline at end of file +export default App; \ No newline at end of file diff --git a/app/src/components/siteNav/SiteNav.tsx b/app/src/components/siteNav/SiteNav.tsx index 0dba599..50eb147 100644 --- a/app/src/components/siteNav/SiteNav.tsx +++ b/app/src/components/siteNav/SiteNav.tsx @@ -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 = () => { + const [loading, setLoading] = useState(false); const [userPhoto, setUserPhoto] = useState(); 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 = () => { 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 => { try { const response: AxiosResponse = await httpClient.get(`api/userProfile`, { @@ -63,7 +65,6 @@ const SiteNav: React.FC = () => { throw new Error(); } }; - const getUserPhoto = async (accessToken: string): Promise => { try { const response: AxiosResponse = await httpClient.get(`api/userPhoto`, { @@ -82,14 +83,13 @@ const SiteNav: React.FC = () => { throw new Error(); } }; - const handlePageClick = (url: string) => { navigate(url); }; const Settings = () => { return ( - + Sign Out @@ -98,9 +98,46 @@ const SiteNav: React.FC = () => { ); }; + 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 = () => { }); } catch (error) { console.log(error); + } finally { + setLoading(false); } }; @@ -127,7 +166,7 @@ const SiteNav: React.FC = () => { return ( } pages={pages} @@ -137,4 +176,4 @@ const SiteNav: React.FC = () => { ); }; -export default SiteNav; +export default SiteNav; \ No newline at end of file