clean up some of the code

This commit is contained in:
Michael Fatemi 2021-07-07 23:52:03 -04:00
parent 5a2088118f
commit 362447689b
5 changed files with 106 additions and 86 deletions

View File

@ -1,11 +1,11 @@
import { lazy, Suspense, useContext, useState, useEffect } from 'react'; import { CSSProperties, lazy, Suspense, useEffect, useState } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom'; import { BrowserRouter, Route, Switch } from 'react-router-dom';
import AuthenticationContext from './Authentication/AuthenticationContext'; import { getReceivedInvitationsAndRequests } from './api';
import { useMe } from './hooks';
import Notifications from './Notifications';
import { IInvitation } from './types';
import WheelShare from './WheelShare'; import WheelShare from './WheelShare';
import WheelShareLoggedOut from './WheelShareLoggedOut'; import WheelShareLoggedOut from './WheelShareLoggedOut';
import Notifications from './Notifications';
import { getReceivedInvitationsAndRequests } from './api';
import { IInvitation } from './types';
const Authenticator = lazy(() => import('./Authentication/Authenticator')); const Authenticator = lazy(() => import('./Authentication/Authenticator'));
const Group = lazy(() => import('./Group')); const Group = lazy(() => import('./Group'));
@ -37,33 +37,54 @@ const dummyNotificationData: IInvitation[] = [
}, },
]; ];
export default function App() { const style: CSSProperties = {
const { user } = useContext(AuthenticationContext); display: 'flex',
// eslint-disable-next-line flexDirection: 'column',
alignItems: 'center',
width: '30rem',
maxWidth: '30rem',
marginLeft: 'auto',
marginRight: 'auto',
};
function useNotifications() {
const [notifications, setNotifications] = useState(dummyNotificationData); const [notifications, setNotifications] = useState(dummyNotificationData);
useEffect(() => { useEffect(() => {
getReceivedInvitationsAndRequests().then(setNotifications); getReceivedInvitationsAndRequests().then(setNotifications);
}, []); }, []);
return notifications;
}
export default function App() {
const user = useMe();
const notifications = useNotifications();
return ( return (
<div style={{ padding: '1rem' }}> <div style={{ padding: '1rem' }}>
{notifications.length > 0 ? ( <div style={style}>
<Notifications notifications={notifications} /> {notifications.length > 0 ? (
) : ( <Notifications notifications={notifications} />
<span>No notifications</span> ) : (
)} <span>No notifications</span>
<BrowserRouter> )}
<Switch> <BrowserRouter>
<Route <Switch>
path="/" <Route
exact path="/"
component={user ? WheelShare : WheelShareLoggedOut} exact
/> component={user ? WheelShare : WheelShareLoggedOut}
<Suspense fallback={null}> />
<Route path="/groups/:id" component={Group} /> <Suspense fallback={null}>
<Route component={Authenticator} path="/auth/:provider/callback" /> <Route path="/groups/:id" component={Group} />
</Suspense> <Route
</Switch> component={Authenticator}
</BrowserRouter> path="/auth/:provider/callback"
/>
</Suspense>
</Switch>
</BrowserRouter>
</div>
</div> </div>
); );
} }

View File

@ -19,22 +19,13 @@ function inferRedirectUrl() {
return redirectUrl; return redirectUrl;
} }
export default function Authenticator() { function useToken(
const { provider } = useParams<{ provider: string }>(); code: string | null,
const [code, error] = useCodeAndError(); provider: string
const { refresh } = useContext(AuthenticationContext); ): [string | null, boolean] {
const [pending, setPending] = useState(false);
const [pending, setPending] = useState(true);
const [token, setToken] = useState<string | null>(null); const [token, setToken] = useState<string | null>(null);
useEffect(() => {
if (token) {
localStorage.setItem('session_token', token);
} else {
localStorage.removeItem('session_token');
}
}, [token]);
useEffect(() => { useEffect(() => {
if (code) { if (code) {
setPending(true); setPending(true);
@ -46,10 +37,34 @@ export default function Authenticator() {
} }
}, [code, provider]); }, [code, provider]);
return [token, pending];
}
function useLocalStorageSync(key: string, value: string | null) {
useEffect(() => {
if (value) {
localStorage.setItem(key, value);
} else {
localStorage.removeItem(key);
}
}, [key, value]);
}
function useRefresh(refresh: Function, watch: string | null) {
useEffect(() => { useEffect(() => {
// Refresh when the token changes
refresh(); refresh();
}, [token, refresh]); }, [watch, refresh]);
}
export default function Authenticator() {
const { provider } = useParams<{ provider: string }>();
const [code, error] = useCodeAndError();
const { refresh } = useContext(AuthenticationContext);
const [token, pending] = useToken(code, provider);
useLocalStorageSync('session_token', token);
useRefresh(refresh, token);
let children: JSX.Element; let children: JSX.Element;
@ -86,15 +101,5 @@ export default function Authenticator() {
); );
} }
return ( return children;
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
{children}
</div>
);
} }

View File

@ -10,9 +10,12 @@ export default function Notifications({
<div className="notifications"> <div className="notifications">
<div style={{ display: 'flex', flexDirection: 'column' }}> <div style={{ display: 'flex', flexDirection: 'column' }}>
<h3 style={{ marginBlockEnd: '0' }}>Notifications</h3> <h3 style={{ marginBlockEnd: '0' }}>Notifications</h3>
{notifications.map((notification) => { {notifications.map((notification) => (
return <Notification notification={notification} />; <Notification
})} notification={notification}
key={`${notification.user.id}:${notification.carpool.id}`}
/>
))}
</div> </div>
</div> </div>
); );

View File

@ -1,4 +1,3 @@
import { CSSProperties } from 'react';
import logout from './Authentication/logout'; import logout from './Authentication/logout';
import Carpool from './Carpool'; import Carpool from './Carpool';
import Events from './Events'; import Events from './Events';
@ -7,21 +6,11 @@ import { useMe } from './hooks';
import UIPressable from './UIPressable'; import UIPressable from './UIPressable';
import UIPrimaryTitle from './UIPrimaryTitle'; import UIPrimaryTitle from './UIPrimaryTitle';
const style: CSSProperties = {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
width: '30rem',
maxWidth: '30rem',
marginLeft: 'auto',
marginRight: 'auto',
};
export default function WheelShare() { export default function WheelShare() {
const user = useMe()!; const user = useMe()!;
return ( return (
<div style={style}> <>
<UIPrimaryTitle>WheelShare</UIPrimaryTitle> <UIPrimaryTitle>WheelShare</UIPrimaryTitle>
<Carpool <Carpool
@ -40,6 +29,6 @@ export default function WheelShare() {
<Groups /> <Groups />
<Events /> <Events />
</div> </>
); );
} }

View File

@ -1,28 +1,30 @@
import { CSSProperties } from 'react';
import UILink from './UILink'; import UILink from './UILink';
import UIPrimaryTitle from './UIPrimaryTitle'; import UIPrimaryTitle from './UIPrimaryTitle';
const dev = true; function createAuthorizationEndpoint(redirectUrl: string) {
const ION_AUTHORIZATION_ENDPOINT = dev const url = new URL('https://ion.tjhsst.edu/oauth/authorize');
? 'https://ion.tjhsst.edu/oauth/authorize?response_type=code&client_id=rNa6n9YSg8ftINdyVPpUsaMuxNbHLo9dh1OsOktR&scope=read&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fion%2Fcallback'
: 'https://ion.tjhsst.edu/oauth/authorize?response_type=code&client_id=rNa6n9YSg8ftINdyVPpUsaMuxNbHLo9dh1OsOktR&scope=read&redirect_uri=https%3A%2F%2Fwheelshare.space%2Fauth%2Fion%2Fcallback';
const style: CSSProperties = { url.searchParams.set('response_type', 'code');
display: 'flex', url.searchParams.set('client_id', 'rNa6n9YSg8ftINdyVPpUsaMuxNbHLo9dh1OsOktR');
flexDirection: 'column', url.searchParams.set('redirect_uri', redirectUrl);
alignItems: 'center', url.searchParams.set('scope', 'read');
width: '30rem',
maxWidth: '30rem', return url.toString();
marginLeft: 'auto', }
marginRight: 'auto',
}; const dev = true;
const endpoint = createAuthorizationEndpoint(
dev
? 'http://localhost:3000/auth/ion/callback'
: 'https://wheelshare.space/auth/ion/callback'
);
export default function WheelShareLoggedOut() { export default function WheelShareLoggedOut() {
return ( return (
<div style={style}> <>
<UIPrimaryTitle>WheelShare</UIPrimaryTitle> <UIPrimaryTitle>WheelShare</UIPrimaryTitle>
<p>To get started, log in with your Ion account.</p> <p>To get started, log in with your Ion account.</p>
<UILink href={ION_AUTHORIZATION_ENDPOINT}>Log in</UILink> <UILink href={endpoint}>Log in</UILink>
</div> </>
); );
} }