From 3a761ffc8b22f970c1e951a973580cd3e140ec41 Mon Sep 17 00:00:00 2001 From: Michael Fatemi Date: Thu, 15 Jul 2021 07:32:40 -0400 Subject: [PATCH] use immutable for Carpools --- src/components/Carpool/Carpool.tsx | 74 +++++++++++++++++------ src/components/Carpool/CarpoolDetails.tsx | 6 +- src/components/Carpool/InvitationList.tsx | 9 ++- src/components/Carpool/MemberList.tsx | 29 ++++----- 4 files changed, 75 insertions(+), 43 deletions(-) diff --git a/src/components/Carpool/Carpool.tsx b/src/components/Carpool/Carpool.tsx index ede0650..44d1c41 100644 --- a/src/components/Carpool/Carpool.tsx +++ b/src/components/Carpool/Carpool.tsx @@ -1,5 +1,11 @@ -import { useMemo } from 'react'; -import { createContext, useCallback, useEffect, useState } from 'react'; +import * as immutable from 'immutable'; +import { + createContext, + useCallback, + useEffect, + useMemo, + useState, +} from 'react'; import { cancelCarpoolInvite, getCarpool, @@ -7,14 +13,33 @@ import { sendCarpoolInvite, } from '../api'; import { useMe } from '../hooks'; -import { ICarpool } from '../types'; import UISecondaryBox from '../UI/UISecondaryBox'; import CarpoolDetails from './CarpoolDetails'; import InvitationsAndRequests from './InvitationsAndRequests'; import MemberList from './MemberList'; +class CarpoolState extends immutable.Record({ + id: 0, + name: '', + eventId: -1, + event: { + id: -1, + name: '', + formattedAddress: '', + latitude: 0, + longitude: 0, + placeId: '', + }, + members: immutable.List<{ id: number; name: string }>(), + invitations: + immutable.Map< + number, + { isRequest: boolean; user: { id: number; name: string } } + >(), +}) {} + export const CarpoolContext = createContext({ - carpool: null! as ICarpool, + carpool: new CarpoolState(), sendInvite: (user: { id: number; name: string }) => { console.error('not implemented: sendInvite'); }, @@ -27,10 +52,23 @@ export const CarpoolContext = createContext({ }); export default function Carpool({ id }: { id: number }) { - const [carpool, setCarpool] = useState(null); + const [carpool, setCarpool] = useState(new CarpoolState()); useEffect(() => { - getCarpool(id).then(setCarpool); + getCarpool(id).then((carpool) => { + setCarpool( + new CarpoolState({ + id: carpool.id, + name: carpool.name, + eventId: carpool.eventId || carpool.event.id, + event: carpool.event, + members: immutable.List(carpool.members), + invitations: immutable.Map( + carpool.invitations.map((invite) => [invite.user.id, invite]) + ), + }) + ); + }); }, [id]); const sendInvite = useCallback( @@ -38,15 +76,11 @@ export default function Carpool({ id }: { id: number }) { if (carpool) { sendCarpoolInvite(id, user.id) .then(() => { - setCarpool( - (carpool) => - carpool && { - ...carpool, - invitations: [ - ...carpool.invitations, - { isRequest: false, user }, - ], - } + setCarpool((carpool) => + carpool.set( + 'invitations', + carpool.invitations.set(user.id, { isRequest: false, user }) + ) ); }) .catch(console.error); @@ -78,7 +112,7 @@ export default function Carpool({ id }: { id: number }) { [id] ); - const eventId = carpool?.eventId; + const eventId = carpool.eventId; const leave = useCallback(() => { if (eventId) { @@ -93,8 +127,8 @@ export default function Carpool({ id }: { id: number }) { const me = useMe(); const isMember = useMemo( - () => carpool?.members.some((m) => m.id === me?.id), - [carpool?.members, me?.id] + () => carpool.members.some((m) => m.id === me?.id), + [carpool.members, me?.id] ); if (!carpool) { @@ -116,8 +150,8 @@ export default function Carpool({ id }: { id: number }) {

{carpool.name}

{carpool.event.name}

{isMember && } - - + + ) : (

Loading

diff --git a/src/components/Carpool/CarpoolDetails.tsx b/src/components/Carpool/CarpoolDetails.tsx index f1fe129..c2f5ed0 100644 --- a/src/components/Carpool/CarpoolDetails.tsx +++ b/src/components/Carpool/CarpoolDetails.tsx @@ -1,9 +1,11 @@ import EventIcon from '@material-ui/icons/Event'; import LocationOnIcon from '@material-ui/icons/LocationOn'; +import { useContext } from 'react'; -import { ICarpool } from '../types'; +import { CarpoolContext } from './Carpool'; -export default function CarpoolDetails({ carpool }: { carpool: ICarpool }) { +export default function CarpoolDetails() { + const { carpool } = useContext(CarpoolContext); return (
!invitation.isRequest) + .valueSeq() .map((invitation) => invitation.user.id) ), [carpool.invitations] @@ -68,11 +69,9 @@ export default function InvitationList() { const availableSignupsAlreadyInvited = useMemo( () => - availableSignups - ? availableSignups.filter((signup) => - invitedUserIDs.has(signup.user.id) - ) - : null, + availableSignups?.filter((signup) => + invitedUserIDs.has(signup.user.id) + ) ?? null, [availableSignups, invitedUserIDs] ); diff --git a/src/components/Carpool/MemberList.tsx b/src/components/Carpool/MemberList.tsx index a768e4e..6e6a5e0 100644 --- a/src/components/Carpool/MemberList.tsx +++ b/src/components/Carpool/MemberList.tsx @@ -18,22 +18,13 @@ function MemberRow({ member }: { member: { id: number; name: string } }) { ); } -export default function MemberList({ - members, -}: { - members: { - id: number; - name: string; - }[]; -}) { - const { leave, carpool } = useContext(CarpoolContext); - const membersToShow = members.slice(0, 2); - const hiddenMemberCount = members.length - membersToShow.length; - const me = useMe()!; +const shownMembersCount = 2; - const isMember = useMemo(() => { - return members.some(({ id }) => id === me.id); - }, [me.id, members]); +export default function MemberList() { + const { leave, carpool } = useContext(CarpoolContext); + const members = carpool.members; + const membersToShow = members.slice(0, shownMembersCount); + const hiddenMemberCount = members.size - membersToShow.size; const { sendCarpoolRequest, cancelCarpoolRequest } = useContext(NotificationsContext); @@ -47,6 +38,12 @@ export default function MemberList({ cancelCarpoolRequest(carpool.id); }, [carpool.id, cancelCarpoolRequest]); + const me = useMe()!; + + const isMember = useMemo(() => { + return members.some(({ id }) => id === me?.id); + }, [me?.id, members]); + return (

Members

- {members.length > 0 ? ( + {members.size > 0 ? (
{membersToShow.map((member) => (