mirror of
https://github.com/myfatemi04/wheelshare-frontend.git
synced 2025-04-16 00:50:18 -04:00
successfully use useImmutable for EventCarpoolCreateButton
This commit is contained in:
parent
a48ad180e0
commit
ac6717d527
|
@ -33,7 +33,24 @@ export default function Event({
|
||||||
id: number;
|
id: number;
|
||||||
initial?: IEvent;
|
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 [myPlaceId, setPlaceId] = useState<string | null>(null);
|
||||||
const [interested, setInterested] = useState(false);
|
const [interested, setInterested] = useState(false);
|
||||||
const [updating, setUpdating] = useState(false);
|
const [updating, setUpdating] = useState(false);
|
||||||
|
@ -53,7 +70,7 @@ export default function Event({
|
||||||
|
|
||||||
const refresh = useCallback(() => {
|
const refresh = useCallback(() => {
|
||||||
getEvent(id).then(setEvent);
|
getEvent(id).then(setEvent);
|
||||||
}, [id]);
|
}, [id, setEvent]);
|
||||||
|
|
||||||
useEffect(refresh, [refresh]);
|
useEffect(refresh, [refresh]);
|
||||||
|
|
||||||
|
|
121
src/components/Event/EventCarpoolCreateButton.tsx
Normal file
121
src/components/Event/EventCarpoolCreateButton.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,19 +1,15 @@
|
||||||
import CancelIcon from '@material-ui/icons/Cancel';
|
import CancelIcon from '@material-ui/icons/Cancel';
|
||||||
import CheckIcon from '@material-ui/icons/Check';
|
import CheckIcon from '@material-ui/icons/Check';
|
||||||
import EmojiPeopleIcon from '@material-ui/icons/EmojiPeople';
|
import EmojiPeopleIcon from '@material-ui/icons/EmojiPeople';
|
||||||
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useContext, useMemo } from 'react';
|
||||||
import { lightgrey } from '../../lib/colors';
|
|
||||||
import { Location } from '../../lib/estimateoptimalpath';
|
import { Location } from '../../lib/estimateoptimalpath';
|
||||||
import {
|
import {
|
||||||
useCancelCarpoolRequest,
|
useCancelCarpoolRequest,
|
||||||
useInvitationState,
|
useInvitationState,
|
||||||
useSendCarpoolRequest,
|
useSendCarpoolRequest,
|
||||||
} from '../../state/Notifications/NotificationsHooks';
|
} from '../../state/Notifications/NotificationsHooks';
|
||||||
import { createCarpool } from '../api';
|
|
||||||
import { useMe } from '../hooks';
|
import { useMe } from '../hooks';
|
||||||
import { IEvent } from '../types';
|
import { IEvent } from '../types';
|
||||||
import UIButton from '../UI/UIButton';
|
|
||||||
import UILink from '../UI/UILink';
|
|
||||||
import useOptimalPath from '../useOptimalPath';
|
import useOptimalPath from '../useOptimalPath';
|
||||||
import usePlace from '../usePlace';
|
import usePlace from '../usePlace';
|
||||||
import EventContext from './EventContext';
|
import EventContext from './EventContext';
|
||||||
|
@ -138,110 +134,22 @@ function CarpoolRow({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreationStatus = null | 'pending' | 'completed' | 'errored';
|
|
||||||
|
|
||||||
export default function Carpools() {
|
export default function Carpools() {
|
||||||
const { event, tentativeInvites, signups, setHasCarpool } =
|
const { event } = useContext(EventContext);
|
||||||
useContext(EventContext);
|
|
||||||
const [creationStatus, setCreationStatus] = useState<CreationStatus>(null);
|
|
||||||
const [createdCarpoolId, setCreatedCarpoolId] = useState<null | number>(null);
|
|
||||||
|
|
||||||
const me = useMe()!;
|
const myId = useMe()?.id;
|
||||||
const myCarpool = useMemo(
|
|
||||||
|
const alreadyInCarpool = useMemo(
|
||||||
() =>
|
() =>
|
||||||
event.carpools.find((carpool) =>
|
event.carpools.some((carpool) =>
|
||||||
carpool.members.some((member) => member.id === me.id)
|
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 (
|
return (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
<h3 style={{ marginBottom: '0' }}>Carpools</h3>
|
<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) => (
|
{event.carpools.map((carpool) => (
|
||||||
<CarpoolRow
|
<CarpoolRow
|
||||||
carpool={carpool}
|
carpool={carpool}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import latlongdist, { R_miles } from '../../lib/latlongdist';
|
||||||
import { useMe } from '../hooks';
|
import { useMe } from '../hooks';
|
||||||
import { IEventSignup } from '../types';
|
import { IEventSignup } from '../types';
|
||||||
import usePlace from '../usePlace';
|
import usePlace from '../usePlace';
|
||||||
|
import EventCarpoolCreateButton from './EventCarpoolCreateButton';
|
||||||
import EventContext from './EventContext';
|
import EventContext from './EventContext';
|
||||||
|
|
||||||
function EventSignup({
|
function EventSignup({
|
||||||
|
@ -125,6 +126,7 @@ export default function EventSignups({
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
<h3 style={{ marginBlockEnd: '0' }}>People without a carpool</h3>
|
<h3 style={{ marginBlockEnd: '0' }}>People without a carpool</h3>
|
||||||
|
<EventCarpoolCreateButton />
|
||||||
{signupsWithoutCarpool.map((signup) => (
|
{signupsWithoutCarpool.map((signup) => (
|
||||||
<EventSignup
|
<EventSignup
|
||||||
key={signup.user.id}
|
key={signup.user.id}
|
||||||
|
|
|
@ -59,7 +59,6 @@ export type IGroup = {
|
||||||
export type IEvent = {
|
export type IEvent = {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
groupId: number;
|
|
||||||
group: {
|
group: {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
|
|
@ -90,7 +90,6 @@ function createEdgeForArray<T extends PlainJS>(
|
||||||
};
|
};
|
||||||
} else if (typeof target[property] === 'function') {
|
} else if (typeof target[property] === 'function') {
|
||||||
return function () {
|
return function () {
|
||||||
console.log(target[property]);
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return target[property].apply(target, arguments);
|
return target[property].apply(target, arguments);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user