mirror of
https://github.com/myfatemi04/wheelshare-frontend.git
synced 2025-04-21 11:20:17 -04:00
add requesting/cancelling request (notifications provider)
This commit is contained in:
parent
9ecf21dab3
commit
41a8a57854
|
@ -1,5 +1,6 @@
|
||||||
import { CSSProperties, lazy, Suspense } from 'react';
|
import { CSSProperties, lazy, Suspense } from 'react';
|
||||||
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
import { BrowserRouter, Route, Switch } from 'react-router-dom';
|
||||||
|
import NotificationsProvider from '../state/Notifications/NotificationsProvider';
|
||||||
import { useMe } from './hooks';
|
import { useMe } from './hooks';
|
||||||
import WheelShare from './WheelShare';
|
import WheelShare from './WheelShare';
|
||||||
import WheelShareLoggedOut from './WheelShareLoggedOut';
|
import WheelShareLoggedOut from './WheelShareLoggedOut';
|
||||||
|
@ -22,27 +23,29 @@ const style: CSSProperties = {
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const user = useMe();
|
const user = useMe();
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: '1rem', maxWidth: '100vw' }}>
|
<NotificationsProvider>
|
||||||
<div style={style}>
|
<div style={{ padding: '1rem', maxWidth: '100vw' }}>
|
||||||
<BrowserRouter>
|
<div style={style}>
|
||||||
<Switch>
|
<BrowserRouter>
|
||||||
<Route
|
<Switch>
|
||||||
path="/"
|
|
||||||
exact
|
|
||||||
component={user ? WheelShare : WheelShareLoggedOut}
|
|
||||||
/>
|
|
||||||
<Suspense fallback={null}>
|
|
||||||
<Route path="/groups/:id" component={Group} />
|
|
||||||
<Route
|
<Route
|
||||||
component={Authenticator}
|
path="/"
|
||||||
path="/auth/:provider/callback"
|
exact
|
||||||
|
component={user ? WheelShare : WheelShareLoggedOut}
|
||||||
/>
|
/>
|
||||||
<Route path="/carpools/:id" component={CarpoolPage} />
|
<Suspense fallback={null}>
|
||||||
<Route path="/events/:id" component={EventPage} />
|
<Route path="/groups/:id" component={Group} />
|
||||||
</Suspense>
|
<Route
|
||||||
</Switch>
|
component={Authenticator}
|
||||||
</BrowserRouter>
|
path="/auth/:provider/callback"
|
||||||
|
/>
|
||||||
|
<Route path="/carpools/:id" component={CarpoolPage} />
|
||||||
|
<Route path="/events/:id" component={EventPage} />
|
||||||
|
</Suspense>
|
||||||
|
</Switch>
|
||||||
|
</BrowserRouter>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</NotificationsProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import AccountCircleIcon from '@material-ui/icons/AccountCircle';
|
import AccountCircleIcon from '@material-ui/icons/AccountCircle';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useMemo } from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
|
import { useInvitationState } from '../../state/Notifications/NotificationsHooks';
|
||||||
|
import { NotificationsContext } from '../../state/Notifications/NotificationsProvider';
|
||||||
import { lightgrey } from '../colors';
|
import { lightgrey } from '../colors';
|
||||||
|
import { useMe } from '../hooks';
|
||||||
import UIButton from '../UI/UIButton';
|
import UIButton from '../UI/UIButton';
|
||||||
import { CarpoolContext } from './Carpool';
|
import { CarpoolContext } from './Carpool';
|
||||||
|
|
||||||
|
@ -21,9 +26,26 @@ export default function MemberList({
|
||||||
name: string;
|
name: string;
|
||||||
}[];
|
}[];
|
||||||
}) {
|
}) {
|
||||||
const { leave } = useContext(CarpoolContext);
|
const { leave, carpool } = useContext(CarpoolContext);
|
||||||
const membersToShow = members.slice(0, 2);
|
const membersToShow = members.slice(0, 2);
|
||||||
const hiddenMemberCount = members.length - membersToShow.length;
|
const hiddenMemberCount = members.length - membersToShow.length;
|
||||||
|
const me = useMe()!;
|
||||||
|
|
||||||
|
const isMember = useMemo(() => {
|
||||||
|
return members.some(({ id }) => id === me.id);
|
||||||
|
}, [me.id, members]);
|
||||||
|
|
||||||
|
const { sendCarpoolRequest, cancelCarpoolRequest } =
|
||||||
|
useContext(NotificationsContext);
|
||||||
|
const invitationState = useInvitationState(carpool.id);
|
||||||
|
|
||||||
|
const sendRequest = useCallback(() => {
|
||||||
|
sendCarpoolRequest(carpool.id);
|
||||||
|
}, [carpool.id, sendCarpoolRequest]);
|
||||||
|
|
||||||
|
const cancelRequest = useCallback(() => {
|
||||||
|
cancelCarpoolRequest(carpool.id);
|
||||||
|
}, [carpool.id, cancelCarpoolRequest]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -48,9 +70,20 @@ export default function MemberList({
|
||||||
) : (
|
) : (
|
||||||
'This carpool has no members.'
|
'This carpool has no members.'
|
||||||
)}
|
)}
|
||||||
<UIButton onClick={leave} style={{ backgroundColor: lightgrey }}>
|
|
||||||
Leave
|
{isMember ? (
|
||||||
</UIButton>
|
<UIButton onClick={leave} style={{ backgroundColor: lightgrey }}>
|
||||||
|
Leave
|
||||||
|
</UIButton>
|
||||||
|
) : invitationState === 'requested' ? (
|
||||||
|
<UIButton onClick={cancelRequest}>Cancel request to join</UIButton>
|
||||||
|
) : invitationState === 'none' ? (
|
||||||
|
<UIButton onClick={sendRequest}>Request to join</UIButton>
|
||||||
|
) : (
|
||||||
|
<span>
|
||||||
|
You've been invited, we need to make it so you can accept the invite
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,3 +193,11 @@ export async function cancelCarpoolInvite(carpoolId: number, userId: number) {
|
||||||
export async function leaveCarpool(carpoolId: number) {
|
export async function leaveCarpool(carpoolId: number) {
|
||||||
return await post(`/carpools/${carpoolId}/leave`, {});
|
return await post(`/carpools/${carpoolId}/leave`, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function sendCarpoolRequest(carpoolId: number) {
|
||||||
|
return await post('/carpools/' + carpoolId + '/request', {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function cancelCarpoolRequest(carpoolId: number) {
|
||||||
|
return await delete$('/carpools/' + carpoolId + '/request');
|
||||||
|
}
|
||||||
|
|
21
src/state/Notifications/NotificationsHooks.tsx
Normal file
21
src/state/Notifications/NotificationsHooks.tsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
import { NotificationsContext } from './NotificationsProvider';
|
||||||
|
|
||||||
|
export function useInvitationState(
|
||||||
|
carpoolId: number
|
||||||
|
): 'invited' | 'requested' | 'none' {
|
||||||
|
const notifications = useContext(NotificationsContext);
|
||||||
|
|
||||||
|
const invited = useMemo(
|
||||||
|
() => notifications.invitedCarpoolIds.has(carpoolId),
|
||||||
|
[carpoolId, notifications.invitedCarpoolIds]
|
||||||
|
);
|
||||||
|
|
||||||
|
const requested = useMemo(
|
||||||
|
() => notifications.requestedCarpoolIds.has(carpoolId),
|
||||||
|
[carpoolId, notifications.requestedCarpoolIds]
|
||||||
|
);
|
||||||
|
|
||||||
|
return invited ? 'invited' : requested ? 'requested' : 'none';
|
||||||
|
}
|
54
src/state/Notifications/NotificationsProvider.tsx
Normal file
54
src/state/Notifications/NotificationsProvider.tsx
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import { createContext, ReactNode, useCallback, useState } from 'react';
|
||||||
|
import * as immutable from 'immutable';
|
||||||
|
import * as api from '../../components/api';
|
||||||
|
|
||||||
|
export const NotificationsContext = createContext({
|
||||||
|
invitedCarpoolIds: immutable.Set<number>(),
|
||||||
|
requestedCarpoolIds: immutable.Set<number>(),
|
||||||
|
|
||||||
|
sendCarpoolRequest: (carpoolId: number) =>
|
||||||
|
console.error('not implemented: sendCarpoolRequest'),
|
||||||
|
|
||||||
|
cancelCarpoolRequest: (carpoolId: number) =>
|
||||||
|
console.error('not implemented: cancelCarpoolRequest'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function NotificationsProvider({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
}) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
const [invitedCarpoolIds, _setInvitedCarpoolIds] = useState(
|
||||||
|
immutable.Set<number>()
|
||||||
|
);
|
||||||
|
|
||||||
|
const [requestedCarpoolIds, setRequestedCarpoolIds] = useState(
|
||||||
|
immutable.Set<number>()
|
||||||
|
);
|
||||||
|
|
||||||
|
const sendCarpoolRequest = useCallback((carpoolId: number) => {
|
||||||
|
api
|
||||||
|
.sendCarpoolRequest(carpoolId)
|
||||||
|
.then(() => setRequestedCarpoolIds((ids) => ids.add(carpoolId)));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const cancelCarpoolRequest = useCallback((carpoolId: number) => {
|
||||||
|
api
|
||||||
|
.cancelCarpoolRequest(carpoolId)
|
||||||
|
.then(() => setRequestedCarpoolIds((ids) => ids.delete(carpoolId)));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NotificationsContext.Provider
|
||||||
|
value={{
|
||||||
|
invitedCarpoolIds,
|
||||||
|
requestedCarpoolIds,
|
||||||
|
sendCarpoolRequest,
|
||||||
|
cancelCarpoolRequest,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</NotificationsContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user