wheelshare-frontend/src/components/Event/Event.tsx
2021-07-15 14:15:01 -04:00

161 lines
3.7 KiB
TypeScript

import { useCallback, useEffect, useState } from 'react';
import { green, lightgrey } from '../../lib/colors';
import getPlaceDetails from '../../lib/getPlaceDetails';
import { addOrUpdateEventSignup, getEvent, removeEventSignup } from '../api';
import { useMe } from '../hooks';
import { IEvent } from '../types';
import UIButton from '../UI/UIButton';
import UILink from '../UI/UILink';
import UIPlacesAutocomplete from '../UI/UIPlacesAutocomplete';
import UISecondaryBox from '../UI/UISecondaryBox';
import UISecondaryHeader from '../UI/UISecondaryHeader';
import useImmutable from '../useImmutable';
import EventCarpools from './EventCarpools';
import EventContext from './EventContext';
import EventDetails from './EventDetails';
import EventSignups from './EventSignups';
function GroupName({ group }: { group: IEvent['group'] }) {
return <UILink href={`/groups/${group.id}`}>{group.name}</UILink>;
}
export default function Event({
id,
initial,
}: {
id: number;
initial?: IEvent;
}) {
const [event, setEvent] = useImmutable<IEvent>({
id,
name: '',
group: {
id: 0,
name: '',
},
signups: {},
carpools: [],
startTime: '',
endTime: '',
daysOfWeek: 0,
placeId: '',
formattedAddress: '',
latitude: 0,
longitude: 0,
duration: 0,
...(initial || {}),
});
const [found, setFound] = useState(false);
const me = useMe() || { id: 0, name: '' };
const [tentativeInvites] = useImmutable<Record<number, boolean>>({});
const refresh = useCallback(() => {
getEvent(id).then((e) => {
if (e) {
setFound(true);
setEvent(e);
} else {
setFound(false);
}
});
}, [id, setEvent]);
useEffect(refresh, [refresh]);
const updateSignup = useCallback(
async (placeId: string | null) => {
await addOrUpdateEventSignup(id, placeId);
if (placeId) {
const details = await getPlaceDetails(placeId);
event.signups[me.id] = {
user: { id: me.id, name: me.name },
placeId,
...details,
};
} else {
event.signups[me.id] = {
user: { id: me.id, name: me.name },
placeId: null,
latitude: null,
longitude: null,
formattedAddress: null,
};
}
},
[event.signups, id, me.id, me.name]
);
const removeSignup = useCallback(async () => {
await removeEventSignup(id);
if (event.signups[me.id]) {
delete event.signups[me.id];
}
}, [id, me.id, event.signups]);
const interested = !!event.signups[me.id];
if (!found) {
return (
<>
<h1>Event Not Found</h1>
</>
);
}
const { name, group, formattedAddress, startTime, endTime } = event;
return (
<EventContext.Provider
value={{
event,
refresh,
default: false,
tentativeInvites,
}}
>
<UISecondaryBox>
<div style={{ textAlign: 'center' }}>
<UISecondaryHeader>{name}</UISecondaryHeader>
{group && <GroupName group={group} />}
</div>
<EventDetails {...{ startTime, endTime, formattedAddress }} />
<UIButton
onClick={interested ? () => removeSignup() : () => updateSignup(null)}
style={{
backgroundColor: interested ? green : lightgrey,
color: interested ? 'white' : 'black',
transition: 'color 0.2s, background-color 0.2s',
}}
>
{interested ? 'Interested' : 'Not interested'}
</UIButton>
{interested && (
<>
<UIPlacesAutocomplete
placeholder="Pickup and dropoff location"
onSelected={(_address, placeId) => {
updateSignup(placeId);
}}
style={
event.signups[me.id]?.placeId != null
? { border: '2px solid ' + green }
: {}
}
placeId={event.signups[me.id]?.placeId}
/>
<br />
<EventCarpools />
{event.signups !== null && <EventSignups />}
</>
)}
</UISecondaryBox>
</EventContext.Provider>
);
}