mirror of
https://github.com/myfatemi04/wheelshare-frontend.git
synced 2025-04-21 11:20:17 -04:00
update api to use new session stfuf
This commit is contained in:
parent
86f327bf9e
commit
557d554db3
|
@ -1,6 +1,9 @@
|
||||||
import WheelShare from './WheelShare';
|
import { lazy, Suspense, useContext } from 'react';
|
||||||
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
||||||
import { lazy, Suspense } from 'react';
|
import AuthenticationContext from './Authentication/AuthenticationContext';
|
||||||
|
import logout from './Authentication/logout';
|
||||||
|
import UIButton from './UIButton';
|
||||||
|
import WheelShare from './WheelShare';
|
||||||
|
|
||||||
const Authenticator = lazy(() => import('./Authentication/Authenticator'));
|
const Authenticator = lazy(() => import('./Authentication/Authenticator'));
|
||||||
const Group = lazy(() => import('./Group'));
|
const Group = lazy(() => import('./Group'));
|
||||||
|
@ -11,23 +14,37 @@ const ION_AUTHORIZATION_ENDPOINT = dev
|
||||||
: 'https://ion.tjhsst.edu/oauth/authorize?response_type=code&client_id=rNa6n9YSg8ftINdyVPpUsaMuxNbHLo9dh1OsOktR&scope=read&redirect_uri=https%3A%2F%2Fwheelshare.space%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';
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
const { isLoggedIn, user } = useContext(AuthenticationContext);
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<a href={ION_AUTHORIZATION_ENDPOINT}>Login Link for Testing Oauth</a>
|
|
||||||
<div style={{ padding: '1rem' }}>
|
<div style={{ padding: '1rem' }}>
|
||||||
|
{isLoggedIn ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
backgroundColor: '#f6f6f6',
|
||||||
|
borderRadius: '0.5rem',
|
||||||
|
padding: '1rem',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{user!.name}{' '}
|
||||||
|
<UIButton style={{ marginTop: 0 }} onClick={logout}>
|
||||||
|
Log out
|
||||||
|
</UIButton>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<a href={ION_AUTHORIZATION_ENDPOINT}>Log in</a>
|
||||||
|
)}
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/" exact component={WheelShare} />
|
<Route path="/" exact component={WheelShare} />
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<Route path="/groups/:id" component={Group} />
|
<Route path="/groups/:id" component={Group} />
|
||||||
<Route
|
<Route component={Authenticator} path="/auth/:provider/callback" />
|
||||||
component={Authenticator}
|
|
||||||
path="/auth/:provider/callback"
|
|
||||||
/>
|
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Switch>
|
</Switch>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
export type User = {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
email?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type AuthState = {
|
export type AuthState = {
|
||||||
isLoggedIn: boolean | null;
|
isLoggedIn: boolean | null;
|
||||||
user: Carpool.User | null;
|
user: User | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that can be used to trigger an auth state refresh.
|
* Function that can be used to trigger an auth state refresh.
|
||||||
|
|
|
@ -16,16 +16,21 @@ export default function AuthenticationWrapper({
|
||||||
});
|
});
|
||||||
|
|
||||||
const refreshAuthState = useCallback(() => {
|
const refreshAuthState = useCallback(() => {
|
||||||
|
const loggedOut = () =>
|
||||||
|
setAuthState({ isLoggedIn: false, user: null, refreshAuthState });
|
||||||
|
|
||||||
if (sessionToken) {
|
if (sessionToken) {
|
||||||
getMe().then((user) => {
|
getMe()
|
||||||
|
.then((user) => {
|
||||||
if (user) {
|
if (user) {
|
||||||
setAuthState({ isLoggedIn: true, user, refreshAuthState });
|
setAuthState({ isLoggedIn: true, user, refreshAuthState });
|
||||||
} else {
|
} else {
|
||||||
setAuthState({ isLoggedIn: false, user: null, refreshAuthState });
|
loggedOut();
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.catch(loggedOut);
|
||||||
} else {
|
} else {
|
||||||
setAuthState({ isLoggedIn: false, user: null, refreshAuthState });
|
loggedOut();
|
||||||
}
|
}
|
||||||
}, [sessionToken]);
|
}, [sessionToken]);
|
||||||
|
|
||||||
|
|
|
@ -10,22 +10,31 @@ export default function Authenticator() {
|
||||||
const { refreshAuthState } = useContext(AuthenticationContext);
|
const { refreshAuthState } = useContext(AuthenticationContext);
|
||||||
const [status, setStatus] =
|
const [status, setStatus] =
|
||||||
useState<'pending' | 'errored' | 'authenticated'>('pending');
|
useState<'pending' | 'errored' | 'authenticated'>('pending');
|
||||||
|
const [token, setToken] = useState<string | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
createSession(code!)
|
createSession(code!)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.status === 'success') {
|
if (data.status === 'success') {
|
||||||
|
console.log('Success! Token:', data.token);
|
||||||
|
setToken(data.token);
|
||||||
localStorage.setItem('session_token', data.token);
|
localStorage.setItem('session_token', data.token);
|
||||||
refreshAuthState && refreshAuthState();
|
|
||||||
setStatus('authenticated');
|
setStatus('authenticated');
|
||||||
} else {
|
} else {
|
||||||
|
console.log('Authentication failure.');
|
||||||
|
setToken(null);
|
||||||
|
localStorage.removeItem('session_token');
|
||||||
setStatus('errored');
|
setStatus('errored');
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setStatus('errored');
|
setStatus('errored');
|
||||||
});
|
});
|
||||||
}, [code, provider, refreshAuthState]);
|
}, [code, provider]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
refreshAuthState && refreshAuthState();
|
||||||
|
}, [token, refreshAuthState]);
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'authenticated':
|
case 'authenticated':
|
||||||
|
|
4
src/components/Authentication/logout.ts
Normal file
4
src/components/Authentication/logout.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export default function logout() {
|
||||||
|
localStorage.removeItem('session_token');
|
||||||
|
window.location.href = '/';
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { post, removeEventSignup } from './api';
|
import { addEventSignup, removeEventSignup } from './api';
|
||||||
import { green, lightgrey } from './colors';
|
import { green, lightgrey } from './colors';
|
||||||
import latlongdist, { R_miles } from './latlongdist';
|
import latlongdist, { R_miles } from './latlongdist';
|
||||||
import UIButton from './UIButton';
|
import UIButton from './UIButton';
|
||||||
|
@ -313,15 +313,14 @@ export default function Event({ event }: { event: IEvent }) {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
interested === true &&
|
interested === true &&
|
||||||
(prev.placeId !== placeId || prev.eventId !== event.id)
|
(prev.placeId !== placeId || prev.eventId !== event.id) &&
|
||||||
|
placeId !== null
|
||||||
) {
|
) {
|
||||||
prev.placeId = placeId;
|
prev.placeId = placeId;
|
||||||
prev.eventId = event.id;
|
prev.eventId = event.id;
|
||||||
prev.interested = true;
|
prev.interested = true;
|
||||||
|
|
||||||
post(`/events/${event.id}/signup`, {
|
addEventSignup(event.id, placeId!).finally(() => setUpdating(false));
|
||||||
placeId,
|
|
||||||
}).finally(() => setUpdating(false));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}, [event.id, interested, placeId, updating]);
|
}, [event.id, interested, placeId, updating]);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Dispatch, SetStateAction, useCallback, useState } from 'react';
|
import { Dispatch, SetStateAction, useCallback, useState } from 'react';
|
||||||
import { post } from './api';
|
import { createEvent } from './api';
|
||||||
import { toggleBit } from './bits';
|
import { toggleBit } from './bits';
|
||||||
import { green, lightgrey } from './colors';
|
import { green, lightgrey } from './colors';
|
||||||
import { IGroup } from './Group';
|
import { IGroup } from './Group';
|
||||||
|
@ -120,7 +120,7 @@ export default function EventCreator({ group }: { group: IGroup }) {
|
||||||
!durationIsNegative &&
|
!durationIsNegative &&
|
||||||
!creating;
|
!creating;
|
||||||
|
|
||||||
const createEvent = useCallback(() => {
|
const onClickedCreateEvent = useCallback(() => {
|
||||||
if (!creating) {
|
if (!creating) {
|
||||||
if (startTime === null) {
|
if (startTime === null) {
|
||||||
console.warn(
|
console.warn(
|
||||||
|
@ -129,12 +129,19 @@ export default function EventCreator({ group }: { group: IGroup }) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (placeId === null) {
|
||||||
|
console.warn(
|
||||||
|
'Tried tro create an event where the placeId was unspecified.'
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const duration =
|
const duration =
|
||||||
endTime !== null ? (endTime.getTime() - startTime.getTime()) / 60 : 0;
|
endTime !== null ? (endTime.getTime() - startTime.getTime()) / 60 : 0;
|
||||||
|
|
||||||
setCreating(true);
|
setCreating(true);
|
||||||
|
|
||||||
post('/events', {
|
createEvent({
|
||||||
name,
|
name,
|
||||||
startTime,
|
startTime,
|
||||||
duration,
|
duration,
|
||||||
|
@ -143,7 +150,6 @@ export default function EventCreator({ group }: { group: IGroup }) {
|
||||||
placeId,
|
placeId,
|
||||||
daysOfWeek,
|
daysOfWeek,
|
||||||
})
|
})
|
||||||
.then((response) => response.json())
|
|
||||||
.then(({ id }) => {
|
.then(({ id }) => {
|
||||||
setCreatedEventId(id);
|
setCreatedEventId(id);
|
||||||
})
|
})
|
||||||
|
@ -211,7 +217,7 @@ export default function EventCreator({ group }: { group: IGroup }) {
|
||||||
)}
|
)}
|
||||||
{createdEventId === -1 ? (
|
{createdEventId === -1 ? (
|
||||||
<UIButton
|
<UIButton
|
||||||
onClick={buttonEnabled ? createEvent : noop}
|
onClick={buttonEnabled ? onClickedCreateEvent : noop}
|
||||||
style={!buttonEnabled ? { color: 'grey' } : {}}
|
style={!buttonEnabled ? { color: 'grey' } : {}}
|
||||||
>
|
>
|
||||||
{creating ? 'Creating event' : 'Create event'}
|
{creating ? 'Creating event' : 'Create event'}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import { post } from './api';
|
import { createGroup } from './api';
|
||||||
import UIButton from './UIButton';
|
import UIButton from './UIButton';
|
||||||
import UILink from './UILink';
|
import UILink from './UILink';
|
||||||
import UISecondaryBox from './UISecondaryBox';
|
import UISecondaryBox from './UISecondaryBox';
|
||||||
|
@ -11,13 +11,10 @@ export default function GroupCreator() {
|
||||||
useState<boolean | null>(null);
|
useState<boolean | null>(null);
|
||||||
const [createdGroupId, setCreatedGroupId] = useState(0);
|
const [createdGroupId, setCreatedGroupId] = useState(0);
|
||||||
const [creating, setCreating] = useState(false);
|
const [creating, setCreating] = useState(false);
|
||||||
const createGroup = useCallback(() => {
|
const onClickedCreateGroup = useCallback(() => {
|
||||||
if (!creating) {
|
if (!creating) {
|
||||||
setCreating(true);
|
setCreating(true);
|
||||||
post('/groups', {
|
createGroup(name)
|
||||||
name,
|
|
||||||
})
|
|
||||||
.then((res) => res.json())
|
|
||||||
.then(({ id }) => {
|
.then(({ id }) => {
|
||||||
setCreationSuccessful(true);
|
setCreationSuccessful(true);
|
||||||
setCreatedGroupId(id);
|
setCreatedGroupId(id);
|
||||||
|
@ -36,7 +33,7 @@ export default function GroupCreator() {
|
||||||
Name
|
Name
|
||||||
<UITextInput onChangeText={setName} value={name} />
|
<UITextInput onChangeText={setName} value={name} />
|
||||||
<UIButton
|
<UIButton
|
||||||
onClick={createGroup}
|
onClick={onClickedCreateGroup}
|
||||||
style={!buttonEnabled ? { color: 'grey' } : {}}
|
style={!buttonEnabled ? { color: 'grey' } : {}}
|
||||||
>
|
>
|
||||||
{creating ? 'Creating group' : 'Create group'}
|
{creating ? 'Creating group' : 'Create group'}
|
||||||
|
|
|
@ -1,26 +1,32 @@
|
||||||
export async function post(path: string, data: any) {
|
async function post(path: string, data: any) {
|
||||||
const res = await fetch('http://localhost:5000/api' + path, {
|
const res = await fetch('http://localhost:5000/api' + path, {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
body: JSON.stringify(data),
|
body: JSON.stringify(data),
|
||||||
headers: {
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('session_token'),
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return await res.json();
|
return await res.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function delete$(path: string) {
|
async function delete$(path: string) {
|
||||||
const res = await fetch('http://localhost:5000/api' + path, {
|
const res = await fetch('http://localhost:5000/api' + path, {
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
headers: {
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('session_token'),
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return await res.json();
|
return await res.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get(path: string) {
|
async function get(path: string) {
|
||||||
const res = await fetch('http://localhost:5000/api' + path);
|
const res = await fetch('http://localhost:5000/api' + path, {
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer ' + localStorage.getItem('session_token'),
|
||||||
|
},
|
||||||
|
});
|
||||||
return await res.json();
|
return await res.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,10 +47,47 @@ export async function getPlaceDetails(
|
||||||
return await get('/place/' + placeId);
|
return await get('/place/' + placeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function addEventSignup(eventId: number, placeId: string) {
|
||||||
|
post(`/events/${eventId}/signup`, {
|
||||||
|
placeId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export async function removeEventSignup(eventId: number) {
|
export async function removeEventSignup(eventId: number) {
|
||||||
return await delete$(`/events/${eventId}/signup`);
|
return await delete$(`/events/${eventId}/signup`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function createEvent({
|
||||||
|
name,
|
||||||
|
startTime,
|
||||||
|
duration,
|
||||||
|
endDate,
|
||||||
|
groupId,
|
||||||
|
placeId,
|
||||||
|
daysOfWeek,
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
startTime: Date;
|
||||||
|
duration: number;
|
||||||
|
endDate: Date | null;
|
||||||
|
groupId: number;
|
||||||
|
placeId: string;
|
||||||
|
daysOfWeek: number;
|
||||||
|
}) {
|
||||||
|
const { id } = await post('/events', {
|
||||||
|
name,
|
||||||
|
startTime,
|
||||||
|
duration,
|
||||||
|
endDate,
|
||||||
|
groupId,
|
||||||
|
placeId,
|
||||||
|
daysOfWeek,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export async function getEvents() {
|
export async function getEvents() {
|
||||||
return await get('/events');
|
return await get('/events');
|
||||||
}
|
}
|
||||||
|
@ -65,6 +108,15 @@ export async function deleteGroup(id: number) {
|
||||||
return await delete$('/groups/' + id);
|
return await delete$('/groups/' + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function createGroup(name: string) {
|
||||||
|
const result = await post('/groups', {
|
||||||
|
name,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
id: result.id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export async function getMe() {
|
export async function getMe() {
|
||||||
return await get('/users/@me');
|
return await get('/users/@me');
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,13 @@ import ReactDOM from 'react-dom';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './components/App';
|
import App from './components/App';
|
||||||
import reportWebVitals from './reportWebVitals';
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
import AuthenticationWrapper from './components/Authentication/AuthenticationWrapper';
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
<AuthenticationWrapper>
|
||||||
<App />
|
<App />
|
||||||
|
</AuthenticationWrapper>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user