successfully use useImmutable for EventCarpoolCreateButton

This commit is contained in:
Michael Fatemi 2021-07-15 09:56:00 -04:00
parent a48ad180e0
commit ac6717d527
6 changed files with 150 additions and 104 deletions

View File

@ -33,7 +33,24 @@ export default function Event({
id: number;
initial?: IEvent;
}) {
const [event, setEvent] = useState<IEvent | null>(initial || null);
const [event, setEvent] = useImmutable<IEvent | null>({
id,
name: '',
group: {
id: 0,
name: '',
},
carpools: [],
startTime: '',
endTime: '',
daysOfWeek: 0,
placeId: '',
formattedAddress: '',
latitude: 0,
longitude: 0,
duration: 0,
...(initial || {}),
});
const [myPlaceId, setPlaceId] = useState<string | null>(null);
const [interested, setInterested] = useState(false);
const [updating, setUpdating] = useState(false);
@ -53,7 +70,7 @@ export default function Event({
const refresh = useCallback(() => {
getEvent(id).then(setEvent);
}, [id]);
}, [id, setEvent]);
useEffect(refresh, [refresh]);

View File

@ -0,0 +1,121 @@
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { lightgrey } from '../../lib/colors';
import { createCarpool } from '../api';
import { useMe } from '../hooks';
import UIButton from '../UI/UIButton';
import UILink from '../UI/UILink';
import EventContext from './EventContext';
type CreationStatus = null | 'pending' | 'completed' | 'errored';
export default function EventCarpoolCreateButton() {
const { event, setHasCarpool, tentativeInvites, signups } =
useContext(EventContext);
const [creationStatus, setCreationStatus] = useState<CreationStatus>(null);
const [createdCarpoolId, setCreatedCarpoolId] = useState<null | number>(null);
const me = useMe()!;
const myCarpool = useMemo(
() =>
event.carpools.find((carpool) =>
carpool.members.some((member) => member.id === me.id)
),
[event.carpools, me.id]
);
const alreadyInCarpool =
myCarpool !== undefined || creationStatus === 'completed';
useEffect(() => {
setHasCarpool(alreadyInCarpool);
}, [alreadyInCarpool, setHasCarpool]);
const createCarpoolCallback = useCallback(() => {
setCreationStatus('pending');
createCarpool({
name: me.name + "'s Carpool",
eventId: event.id,
invitedUserIds: Object.keys(tentativeInvites).map(Number),
})
.then(({ id }) => {
setCreatedCarpoolId(id);
event.carpools.push({
id,
name: me.name + "'s Carpool",
members: [{ id: me.id, name: me.name }],
});
setCreationStatus('completed');
})
.catch(() => {
setCreationStatus('errored');
});
}, [event.carpools, event.id, me.id, me.name, tentativeInvites]);
const tentativeInviteNames = useMemo(() => {
if (!signups) return [];
const names = Object.keys(tentativeInvites).map((id) => {
const signup = signups[id];
return signup?.user.name;
});
return names.filter((n) => n != null);
}, [tentativeInvites, signups]);
let createCarpoolSection;
if (tentativeInviteNames.length > 0) {
const inviteeCount = tentativeInviteNames.length;
const peoplePlural = inviteeCount > 1 ? 'People' : 'Person';
createCarpoolSection = (
<>
<br />
<b>List:</b>
<br />
{tentativeInviteNames.join(',')}
<UIButton
onClick={createCarpoolCallback}
style={{ backgroundColor: lightgrey }}
>
{creationStatus === null
? `Create Carpool With ${inviteeCount} ${peoplePlural}`
: creationStatus === 'pending'
? 'Creating...'
: 'Errored'}
</UIButton>
</>
);
} else
createCarpoolSection = (
<>
<span>Available to drive?</span>
<UIButton
onClick={createCarpoolCallback}
style={{ backgroundColor: lightgrey }}
>
{creationStatus === null
? 'Create Empty Carpool'
: creationStatus === 'pending'
? 'Creating...'
: 'Errored'}
</UIButton>
</>
);
return (
<div>
{creationStatus === 'completed' ? (
<span>
Created{' '}
<UILink href={`/carpools/${createdCarpoolId}`}>your carpool</UILink>!
</span>
) : myCarpool ? (
<span>
You are already in a carpool for this event:{' '}
<UILink href={`/carpools/${myCarpool.id}`}>{myCarpool.name}</UILink>
</span>
) : (
createCarpoolSection
)}
</div>
);
}

View File

@ -1,19 +1,15 @@
import CancelIcon from '@material-ui/icons/Cancel';
import CheckIcon from '@material-ui/icons/Check';
import EmojiPeopleIcon from '@material-ui/icons/EmojiPeople';
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { lightgrey } from '../../lib/colors';
import { useCallback, useContext, useMemo } from 'react';
import { Location } from '../../lib/estimateoptimalpath';
import {
useCancelCarpoolRequest,
useInvitationState,
useSendCarpoolRequest,
} from '../../state/Notifications/NotificationsHooks';
import { createCarpool } from '../api';
import { useMe } from '../hooks';
import { IEvent } from '../types';
import UIButton from '../UI/UIButton';
import UILink from '../UI/UILink';
import useOptimalPath from '../useOptimalPath';
import usePlace from '../usePlace';
import EventContext from './EventContext';
@ -138,110 +134,22 @@ function CarpoolRow({
);
}
type CreationStatus = null | 'pending' | 'completed' | 'errored';
export default function Carpools() {
const { event, tentativeInvites, signups, setHasCarpool } =
useContext(EventContext);
const [creationStatus, setCreationStatus] = useState<CreationStatus>(null);
const [createdCarpoolId, setCreatedCarpoolId] = useState<null | number>(null);
const { event } = useContext(EventContext);
const me = useMe()!;
const myCarpool = useMemo(
const myId = useMe()?.id;
const alreadyInCarpool = useMemo(
() =>
event.carpools.find((carpool) =>
carpool.members.some((member) => member.id === me.id)
event.carpools.some((carpool) =>
carpool.members.some((member) => member.id === myId)
),
[event.carpools, me.id]
[event.carpools, myId]
);
const alreadyInCarpool =
myCarpool !== undefined || creationStatus === 'completed';
useEffect(() => {
setHasCarpool(alreadyInCarpool);
}, [alreadyInCarpool, setHasCarpool]);
const createCarpoolCallback = useCallback(() => {
setCreationStatus('pending');
createCarpool({
name: me.name + "'s Carpool",
eventId: event.id,
invitedUserIds: Object.keys(tentativeInvites).map(Number),
})
.then(({ id }) => {
setCreatedCarpoolId(id);
setCreationStatus('completed');
})
.catch(() => {
setCreationStatus('errored');
});
}, [event.id, me.name, tentativeInvites]);
const tentativeInviteNames = useMemo(() => {
if (!signups) return [];
const names = Object.keys(tentativeInvites).map((id) => {
const signup = signups[id];
return signup?.user.name;
});
return names.filter((n) => n != null);
}, [tentativeInvites, signups]);
let createCarpoolSection;
if (tentativeInviteNames.length > 0) {
const inviteeCount = tentativeInviteNames.length;
const peoplePlural = inviteeCount > 1 ? 'People' : 'Person';
createCarpoolSection = (
<>
<br />
<b>You have invited these people to carpool with you:</b>
{tentativeInviteNames.join(',')}
<UIButton
onClick={createCarpoolCallback}
style={{ backgroundColor: lightgrey }}
>
{creationStatus === null
? `Create Carpool With ${inviteeCount} ${peoplePlural}`
: creationStatus === 'pending'
? 'Creating...'
: 'Errored'}
</UIButton>
</>
);
} else
createCarpoolSection = (
<>
<span>Available to drive?</span>
<UIButton
onClick={createCarpoolCallback}
style={{ backgroundColor: lightgrey }}
>
{creationStatus === null
? 'Create Empty Carpool'
: creationStatus === 'pending'
? 'Creating...'
: 'Errored'}
</UIButton>
</>
);
return (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<h3 style={{ marginBottom: '0' }}>Carpools</h3>
{creationStatus === 'completed' ? (
<span>
Created{' '}
<UILink href={`/carpools/${createdCarpoolId}`}>your carpool</UILink>!
</span>
) : myCarpool ? (
<span>
You are already in a carpool for this event:{' '}
<UILink href={`/carpools/${myCarpool.id}`}>{myCarpool.name}</UILink>
</span>
) : (
createCarpoolSection
)}
{event.carpools.map((carpool) => (
<CarpoolRow
carpool={carpool}

View File

@ -6,6 +6,7 @@ import latlongdist, { R_miles } from '../../lib/latlongdist';
import { useMe } from '../hooks';
import { IEventSignup } from '../types';
import usePlace from '../usePlace';
import EventCarpoolCreateButton from './EventCarpoolCreateButton';
import EventContext from './EventContext';
function EventSignup({
@ -125,6 +126,7 @@ export default function EventSignups({
return (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<h3 style={{ marginBlockEnd: '0' }}>People without a carpool</h3>
<EventCarpoolCreateButton />
{signupsWithoutCarpool.map((signup) => (
<EventSignup
key={signup.user.id}

View File

@ -59,7 +59,6 @@ export type IGroup = {
export type IEvent = {
id: number;
name: string;
groupId: number;
group: {
id: number;
name: string;

View File

@ -90,7 +90,6 @@ function createEdgeForArray<T extends PlainJS>(
};
} else if (typeof target[property] === 'function') {
return function () {
console.log(target[property]);
// @ts-ignore
return target[property].apply(target, arguments);
};