Accepting carpools on the frontend works!

This commit is contained in:
Michael Fatemi 2021-07-15 14:15:01 -04:00
parent 9f7c40c7df
commit 2eea5f0dc5
6 changed files with 107 additions and 29 deletions

View File

@ -20,16 +20,24 @@ function MemberRow({ member }: { member: { id: number; name: string } }) {
const shownMembersCount = 2; const shownMembersCount = 2;
const defaultMe = { id: 0, name: '' };
export default function MemberList() { export default function MemberList() {
const { leave, carpool } = useContext(CarpoolContext); const { leave, carpool } = useContext(CarpoolContext);
const members = carpool.members; const members = carpool.members;
const membersToShow = members.slice(0, shownMembersCount); const membersToShow = members.slice(0, shownMembersCount);
const hiddenMemberCount = members.length - membersToShow.length; const hiddenMemberCount = members.length - membersToShow.length;
const { sendCarpoolRequest, cancelCarpoolRequest } = const {
useContext(NotificationsContext); sendCarpoolRequest,
cancelCarpoolRequest,
acceptCarpoolInvite,
denyCarpoolInvite,
} = useContext(NotificationsContext);
const invitationState = useInvitationState(carpool.id); const invitationState = useInvitationState(carpool.id);
const me = useMe() || defaultMe;
const sendRequest = useCallback(() => { const sendRequest = useCallback(() => {
sendCarpoolRequest(carpool.id); sendCarpoolRequest(carpool.id);
}, [carpool.id, sendCarpoolRequest]); }, [carpool.id, sendCarpoolRequest]);
@ -38,7 +46,17 @@ export default function MemberList() {
cancelCarpoolRequest(carpool.id); cancelCarpoolRequest(carpool.id);
}, [carpool.id, cancelCarpoolRequest]); }, [carpool.id, cancelCarpoolRequest]);
const me = useMe() || { id: 0, name: '' }; const acceptInvitation = useCallback(() => {
acceptCarpoolInvite(carpool.id).then(() => {
members.push(me);
});
}, [acceptCarpoolInvite, carpool.id, members, me]);
const denyInvitation = useCallback(() => {
denyCarpoolInvite(carpool.id).then(() => {
members.push(me);
});
}, [carpool.id, denyCarpoolInvite, me, members]);
const isMember = useMemo(() => { const isMember = useMemo(() => {
return members.some(({ id }) => id === me?.id); return members.some(({ id }) => id === me?.id);
@ -78,7 +96,21 @@ export default function MemberList() {
<UIButton onClick={sendRequest}>Request to join</UIButton> <UIButton onClick={sendRequest}>Request to join</UIButton>
) : ( ) : (
<span> <span>
You've been invited, we need to make it so you can accept the invite You've been invited to this carpool!
<div style={{ display: 'flex', width: '100%', textAlign: 'center' }}>
<UIButton
onClick={acceptInvitation}
style={{ backgroundColor: lightgrey, flex: 1, margin: '0.5rem' }}
>
Accept
</UIButton>
<UIButton
onClick={denyInvitation}
style={{ backgroundColor: lightgrey, flex: 1, margin: '0.5rem' }}
>
Deny
</UIButton>
</div>
</span> </span>
)} )}
</div> </div>

View File

@ -1,4 +1,4 @@
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { green, lightgrey } from '../../lib/colors'; import { green, lightgrey } from '../../lib/colors';
import getPlaceDetails from '../../lib/getPlaceDetails'; import getPlaceDetails from '../../lib/getPlaceDetails';
import { addOrUpdateEventSignup, getEvent, removeEventSignup } from '../api'; import { addOrUpdateEventSignup, getEvent, removeEventSignup } from '../api';
@ -46,12 +46,21 @@ export default function Event({
...(initial || {}), ...(initial || {}),
}); });
const [found, setFound] = useState(false);
const me = useMe() || { id: 0, name: '' }; const me = useMe() || { id: 0, name: '' };
const [tentativeInvites] = useImmutable<Record<number, boolean>>({}); const [tentativeInvites] = useImmutable<Record<number, boolean>>({});
const refresh = useCallback(() => { const refresh = useCallback(() => {
getEvent(id).then(setEvent); getEvent(id).then((e) => {
if (e) {
setFound(true);
setEvent(e);
} else {
setFound(false);
}
});
}, [id, setEvent]); }, [id, setEvent]);
useEffect(refresh, [refresh]); useEffect(refresh, [refresh]);
@ -91,8 +100,12 @@ export default function Event({
const interested = !!event.signups[me.id]; const interested = !!event.signups[me.id];
if (!event) { if (!found) {
return <UISecondaryBox>Loading...</UISecondaryBox>; return (
<>
<h1>Event Not Found</h1>
</>
);
} }
const { name, group, formattedAddress, startTime, endTime } = event; const { name, group, formattedAddress, startTime, endTime } = event;

View File

@ -1,4 +1,4 @@
import { createContext, useEffect } from 'react'; import { createContext, useEffect, useState } from 'react';
import { getGroup } from '../api'; import { getGroup } from '../api';
import EventCreatorLink from '../EventCreator/EventCreatorLink'; import EventCreatorLink from '../EventCreator/EventCreatorLink';
import EventStream from '../EventStream'; import EventStream from '../EventStream';
@ -20,12 +20,15 @@ export const GroupContext = createContext({ group: DEFAULT_GROUP() });
export default function Group({ id }: { id: number }) { export default function Group({ id }: { id: number }) {
const [group, setGroup] = useImmutable<IGroup>(DEFAULT_GROUP()); const [group, setGroup] = useImmutable<IGroup>(DEFAULT_GROUP());
const [found, setFound] = useState(false);
useEffect(() => { useEffect(() => {
getGroup(id).then(setGroup); getGroup(id)
.then(setGroup)
.catch(() => setFound(false));
}, [id, setGroup]); }, [id, setGroup]);
return ( return found ? (
<GroupContext.Provider value={{ group }}> <GroupContext.Provider value={{ group }}>
<div <div
style={{ style={{
@ -55,5 +58,9 @@ export default function Group({ id }: { id: number }) {
)} )}
</div> </div>
</GroupContext.Provider> </GroupContext.Provider>
) : (
<>
<h1>Group not found</h1>
</>
); );
} }

View File

@ -19,12 +19,12 @@ export default function Notification({
}, [carpoolId, notification.user.id]); }, [carpoolId, notification.user.id]);
const acceptInv = useCallback(() => { const acceptInv = useCallback(() => {
acceptInvite(carpoolId, notification.user.id); acceptInvite(carpoolId);
}, [carpoolId, notification.user.id]); }, [carpoolId]);
const rejectInv = useCallback(() => { const rejectInv = useCallback(() => {
denyInvite(carpoolId, notification.user.id); denyInvite(carpoolId);
}, [carpoolId, notification.user.id]); }, [carpoolId]);
const sentTime = new Date(notification.sentTime); const sentTime = new Date(notification.sentTime);

View File

@ -138,16 +138,16 @@ export async function acceptRequest(carpoolId: number, userId: number) {
return await post(`/carpools/${carpoolId}/accept_request`, { userId }); return await post(`/carpools/${carpoolId}/accept_request`, { userId });
} }
export async function acceptInvite(carpoolId: number, userId: number) { export async function acceptInvite(carpoolId: number) {
return await post(`/carpools/${carpoolId}/accept_invite`, { userId }); return await post(`/carpools/${carpoolId}/accept_invite`, {});
} }
export async function denyRequest(carpoolId: number, userId: number) { export async function denyRequest(carpoolId: number, userId: number) {
return await post(`/carpools/${carpoolId}/deny_request`, { userId }); return await post(`/carpools/${carpoolId}/deny_request`, { userId });
} }
export async function denyInvite(carpoolId: number, userId: number) { export async function denyInvite(carpoolId: number) {
return await post(`/carpools/${carpoolId}/deny_invite`, { userId }); return await post(`/carpools/${carpoolId}/deny_invite`, {});
} }
export async function getMe() { export async function getMe() {

View File

@ -7,11 +7,17 @@ export const NotificationsContext = createContext({
invitedCarpoolIds: {} as Record<number, boolean>, invitedCarpoolIds: {} as Record<number, boolean>,
requestedCarpoolIds: {} as Record<number, boolean>, requestedCarpoolIds: {} as Record<number, boolean>,
sendCarpoolRequest: (carpoolId: number) => sendCarpoolRequest: async (carpoolId: number) =>
console.error('not implemented: sendCarpoolRequest'), console.error('not implemented: sendCarpoolRequest'),
cancelCarpoolRequest: (carpoolId: number) => cancelCarpoolRequest: async (carpoolId: number) =>
console.error('not implemented: cancelCarpoolRequest'), console.error('not implemented: cancelCarpoolRequest'),
acceptCarpoolInvite: async (carpoolId: number) =>
console.error('not implemented: acceptCarpoolInvite'),
denyCarpoolInvite: async (carpoolId: number) =>
console.error('not implemented: denyCarpoolInvite'),
}); });
export default function NotificationsProvider({ export default function NotificationsProvider({
@ -44,23 +50,41 @@ export default function NotificationsProvider({
}, [setInvitedCarpoolIds, setRequestedCarpoolIds]); }, [setInvitedCarpoolIds, setRequestedCarpoolIds]);
const sendCarpoolRequest = useCallback( const sendCarpoolRequest = useCallback(
(carpoolId: number) => { async (carpoolId: number) => {
api.sendCarpoolRequest(carpoolId).then(() => { await api.sendCarpoolRequest(carpoolId);
requestedCarpoolIds[carpoolId] = true;
}); requestedCarpoolIds[carpoolId] = true;
}, },
[requestedCarpoolIds] [requestedCarpoolIds]
); );
const cancelCarpoolRequest = useCallback( const cancelCarpoolRequest = useCallback(
(carpoolId: number) => { async (carpoolId: number) => {
api.cancelCarpoolRequest(carpoolId).then(() => { await api.cancelCarpoolRequest(carpoolId);
delete requestedCarpoolIds[carpoolId];
}); delete requestedCarpoolIds[carpoolId];
}, },
[requestedCarpoolIds] [requestedCarpoolIds]
); );
const acceptCarpoolInvite = useCallback(
async (carpoolId: number) => {
await api.acceptInvite(carpoolId);
delete invitedCarpoolIds[carpoolId];
},
[invitedCarpoolIds]
);
const denyCarpoolInvite = useCallback(
async (carpoolId: number) => {
await api.denyInvite(carpoolId);
delete invitedCarpoolIds[carpoolId];
},
[invitedCarpoolIds]
);
return ( return (
<NotificationsContext.Provider <NotificationsContext.Provider
value={{ value={{
@ -68,6 +92,8 @@ export default function NotificationsProvider({
requestedCarpoolIds, requestedCarpoolIds,
sendCarpoolRequest, sendCarpoolRequest,
cancelCarpoolRequest, cancelCarpoolRequest,
acceptCarpoolInvite,
denyCarpoolInvite,
}} }}
> >
{children} {children}