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

View File

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

View File

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

View File

@ -1,4 +1,3 @@
import { CSSProperties } from 'react';
import logout from './Authentication/logout';
import Carpool from './Carpool';
import Events from './Events';
@ -7,21 +6,11 @@ import { useMe } from './hooks';
import UIPressable from './UIPressable';
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() {
const user = useMe()!;
return (
<div style={style}>
<>
<UIPrimaryTitle>WheelShare</UIPrimaryTitle>
<Carpool
@ -40,6 +29,6 @@ export default function WheelShare() {
<Groups />
<Events />
</div>
</>
);
}

View File

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