all repos — caroster @ 9bb16d12337eb1922826febc04fd006384241999

[Octree] Group carpool to your event https://caroster.io

🐛 Fix blinking UI on event page
Simon Mulquin simon@octree.ch
Thu, 16 Jun 2022 07:23:43 +0000
commit

9bb16d12337eb1922826febc04fd006384241999

parent

a78d74bdc205a880e61fa477de33a5d876c6ea51

M backend/.strapi-updater.jsonbackend/.strapi-updater.json

@@ -1,5 +1,5 @@

{ "latest": "3.6.10", - "lastUpdateCheck": 1653460540026, - "lastNotification": 1637085344214 + "lastUpdateCheck": 1655278117505, + "lastNotification": 1655278102398 }
M frontend/containers/DrawerMenu/index.tsxfrontend/containers/DrawerMenu/index.tsx

@@ -23,7 +23,7 @@ <Drawer variant="permanent" className={classes.drawer}>

<DrawerMenuItem title={t('drawer.travels')} onClick={() => { - router.push(`/e/${uuid}`, undefined, {shallow: true}); + router.push(`/e/${uuid}`, null, {shallow: true}); setAreDetailsOpened(false); }} Icon={<Icon>directions_car</Icon>}
A frontend/layouts/Event.tsx

@@ -0,0 +1,90 @@

+import {PropsWithChildren, useEffect, useState} from 'react'; +import {makeStyles} from '@material-ui/core/styles'; +import {useTranslation} from 'react-i18next'; +import ErrorPage from '../pages/_error'; +import useEventStore from '../stores/useEventStore'; +import Layout from '../layouts/Default'; +import EventBar from '../containers/EventBar'; +import { + Event as EventType, + useEventByUuidQuery, + useUpdateEventMutation, + EditEventInput, +} from '../generated/graphql'; +import useBannerStore from '../stores/useBannerStore'; +import DrawerMenu from '../containers/DrawerMenu'; +import AddToMyEventDialog from '../containers/AddToMyEventDialog'; +import useToastStore from '../stores/useToastStore'; + +const POLL_INTERVAL = 10000; + +export type TabComponent = (props: {event: EventType}) => JSX.Element; + +interface Props { + eventUUID: string; + Tab: TabComponent; +} + +const EventLayout = (props: PropsWithChildren<Props>) => { + const {eventUUID, Tab} = props; + const bannerOffset = useBannerStore(s => s.offset); + const classes = useStyles({bannerOffset}); + const {t} = useTranslation(); + const addToast = useToastStore(s => s.addToast); + const setEvent = useEventStore(s => s.setEvent); + const eventUpdate = useEventStore(s => s.event); + const setIsEditing = useEventStore(s => s.setIsEditing); + const [updateEvent] = useUpdateEventMutation(); + const [isAddToMyEvent, setIsAddToMyEvent] = useState(false); + const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({ + pollInterval: POLL_INTERVAL, + variables: {uuid: eventUUID}, + }); + + useEffect(() => { + if (event) setEvent(event as EventType); + }, [event]); + + if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />; + + const onSave = async e => { + try { + const {uuid, ...data} = eventUpdate; + const {id, __typename, travels, users, waitingList, ...input} = data; + await updateEvent({ + variables: {uuid, eventUpdate: input as EditEventInput}, + refetchQueries: ['eventByUUID'], + }); + setIsEditing(false); + } catch (error) { + console.error(error); + addToast(t('event.errors.cant_update')); + } + }; + + return ( + <Layout + className={classes.layout} + pageTitle={t('event.title', {title: event.name})} + menuTitle={t('event.title', {title: event.name})} + displayMenu={false} + > + <EventBar event={event} onAdd={setIsAddToMyEvent} onSave={onSave} /> + <DrawerMenu /> + <Tab event={event} /> + <AddToMyEventDialog + event={event} + open={isAddToMyEvent} + onClose={() => setIsAddToMyEvent(false)} + /> + </Layout> + ); +}; + +const useStyles = makeStyles(theme => ({ + layout: ({bannerOffset}) => ({ + paddingTop: theme.mixins.toolbar.minHeight + bannerOffset, + }), +})); + +export default EventLayout;
M frontend/pages/e/[uuid]/index.tsxfrontend/pages/e/[uuid]/index.tsx

@@ -1,103 +1,44 @@

-import {useState, useReducer, useEffect} from 'react'; +import {useState, useReducer, PropsWithChildren} from 'react'; import {makeStyles} from '@material-ui/core/styles'; import {useTranslation} from 'react-i18next'; -import {initializeApollo} from '../../../lib/apolloClient'; -import useToastStore from '../../../stores/useToastStore'; -import useEventStore from '../../../stores/useEventStore'; -import Layout from '../../../layouts/Default'; -import AddToMyEventDialog from '../../../containers/AddToMyEventDialog'; +import EventLayout, { TabComponent } from '../../../layouts/Event'; import TravelColumns from '../../../containers/TravelColumns'; import NewTravelDialog from '../../../containers/NewTravelDialog'; import VehicleChoiceDialog from '../../../containers/VehicleChoiceDialog'; -import WelcomeDialog from '../../../containers/WelcomeDialog'; -import EventBar from '../../../containers/EventBar'; -import Loading from '../../../containers/Loading'; -import OnBoardingTour from '../../../containers/OnBoardingTour'; import { - useUpdateEventMutation, - Event as EventType, - useEventByUuidQuery, EventByUuidDocument, - EditEventInput, useFindUserVehiclesQuery, } from '../../../generated/graphql'; -import ErrorPage from '../../_error'; import useProfile from '../../../hooks/useProfile'; import Fab from '../../../containers/Fab'; -import useMediaQuery from '@material-ui/core/useMediaQuery'; import useBannerStore from '../../../stores/useBannerStore'; -import DrawerMenu from '../../../containers/DrawerMenu'; - -const POLL_INTERVAL = 10000; +import {initializeApollo} from '../../../lib/apolloClient'; interface Props { - event: EventType; eventUUID: string; } -const EventPage = props => { - const {t} = useTranslation(); - const {event} = props; - if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />; - return <Event {...props} />; +const Page = (props: PropsWithChildren<Props>) => { + return <EventLayout {...props} Tab={TravelsTab} />; }; -const Event = (props: Props) => { - const {eventUUID} = props; +const TravelsTab: TabComponent = (props: {event}) => { const bannerOffset = useBannerStore(s => s.offset); const classes = useStyles({bannerOffset}); const {t} = useTranslation(); const {user} = useProfile(); const {data: {me: {profile: {vehicles = []} = {}} = {}} = {}, loading} = useFindUserVehiclesQuery(); - const addToast = useToastStore(s => s.addToast); - const setEvent = useEventStore(s => s.setEvent); - const eventUpdate = useEventStore(s => s.event); - const setIsEditing = useEventStore(s => s.setIsEditing); - const [updateEvent] = useUpdateEventMutation(); - const [isAddToMyEvent, setIsAddToMyEvent] = useState(false); const [openNewTravelContext, toggleNewTravel] = useState({opened: false}); const [openVehicleChoice, toggleVehicleChoice] = useReducer(i => !i, false); - const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({ - pollInterval: POLL_INTERVAL, - variables: {uuid: eventUUID}, - }); - - const onSave = async e => { - try { - const {uuid, ...data} = eventUpdate; - const {id, __typename, travels, users, waitingList, ...input} = data; - await updateEvent({ - variables: {uuid, eventUpdate: input as EditEventInput}, - refetchQueries: ['eventByUUID'], - }); - setIsEditing(false); - } catch (error) { - console.error(error); - addToast(t('event.errors.cant_update')); - } - }; - - useEffect(() => { - if (event) setEvent(event as EventType); - }, [event]); const addTravelClickHandler = user && vehicles?.length != 0 ? toggleVehicleChoice : () => toggleNewTravel({opened: true}); - if (!event || loading) return <Loading />; - return ( - <Layout - className={classes.layout} - pageTitle={t('event.title', {title: event.name})} - menuTitle={t('event.title', {title: event.name})} - displayMenu={false} - > - <EventBar event={event} onAdd={setIsAddToMyEvent} onSave={onSave} /> - <DrawerMenu /> + <> <TravelColumns toggle={addTravelClickHandler} /> <Fab onClick={addTravelClickHandler}

@@ -117,17 +58,22 @@ toggle={toggleVehicleChoice}

toggleNewTravel={toggleNewTravel} vehicles={vehicles} /> - <AddToMyEventDialog - event={event} - open={isAddToMyEvent} - onClose={() => setIsAddToMyEvent(false)} - /> - <WelcomeDialog /> - <OnBoardingTour /> - </Layout> + </> ); }; +const useStyles = makeStyles(theme => ({ + bottomRight: { + bottom: 0, + right: theme.spacing(6), + + [theme.breakpoints.down('sm')]: { + right: theme.spacing(1), + bottom: 56, + }, + }, +})); + export async function getServerSideProps(ctx) { const {uuid} = ctx.query; const apolloClient = initializeApollo();

@@ -150,19 +96,4 @@ },

}; } -const useStyles = makeStyles(theme => ({ - layout: ({bannerOffset}) => ({ - paddingTop: theme.mixins.toolbar.minHeight + bannerOffset, - }), - bottomRight: { - bottom: 0, - right: theme.spacing(6), - - [theme.breakpoints.down('sm')]: { - right: theme.spacing(1), - bottom: 56, - }, - }, -})); - -export default EventPage; +export default Page;
M frontend/pages/e/[uuid]/waitingList.tsxfrontend/pages/e/[uuid]/waitingList.tsx

@@ -1,89 +1,29 @@

-import {useState, useEffect, useMemo} from 'react'; -import {makeStyles} from '@material-ui/core/styles'; -import {useTranslation} from 'react-i18next'; -import {initializeApollo} from '../../../lib/apolloClient'; -import useToastStore from '../../../stores/useToastStore'; -import useEventStore from '../../../stores/useEventStore'; -import Layout from '../../../layouts/Default'; -import {Travel as TravelType} from '../../../generated/graphql'; -import EventBar from '../../../containers/EventBar'; -import Loading from '../../../containers/Loading'; +import {useState, useMemo, PropsWithChildren} from 'react'; +import EventLayout, { TabComponent } from '../../../layouts/Event'; import { - useUpdateEventMutation, - Event as EventType, - useEventByUuidQuery, EventByUuidDocument, - EditEventInput, - useFindUserVehiclesQuery, } from '../../../generated/graphql'; -import ErrorPage from '../../_error'; import useProfile from '../../../hooks/useProfile'; -import useBannerStore from '../../../stores/useBannerStore'; -import DrawerMenu from '../../../containers/DrawerMenu'; import WaitingList from '../../../containers/WaitingList'; -import { - AddPassengerToTravel, - AddPassengerToWaitingList, -} from '../../../containers/NewPassengerDialog'; -import AddToMyEventDialog from '../../../containers/AddToMyEventDialog'; - -const POLL_INTERVAL = 10000; +import {AddPassengerToWaitingList} from '../../../containers/NewPassengerDialog'; +import {initializeApollo} from '../../../lib/apolloClient'; interface NewPassengerDialogContext { addSelf: boolean; } interface Props { - event: EventType; eventUUID: string; } -const EventPage = props => { - const {t} = useTranslation(); - const {event} = props; - if (!event) return <ErrorPage statusCode={404} title={t`event.not_found`} />; - return <Event {...props} />; +const Page = (props: PropsWithChildren<Props>) => { + return <EventLayout {...props} Tab={WaitingListTab} />; }; -const Event = (props: Props) => { - const {eventUUID} = props; - const bannerOffset = useBannerStore(s => s.offset); - const classes = useStyles({bannerOffset}); - const {t} = useTranslation(); +const WaitingListTab: TabComponent = (props: {event}) => { const {user} = useProfile(); - const {data: {me: {profile: {vehicles = []} = {}} = {}} = {}, loading} = - useFindUserVehiclesQuery(); - const addToast = useToastStore(s => s.addToast); - const setEvent = useEventStore(s => s.setEvent); - const eventUpdate = useEventStore(s => s.event); - const setIsEditing = useEventStore(s => s.setIsEditing); - const [isAddToMyEvent, setIsAddToMyEvent] = useState(false); const [addPassengerToWaitingListContext, toggleNewPassengerToWaitingList] = useState<NewPassengerDialogContext | null>(null); - const [updateEvent] = useUpdateEventMutation(); - const {data: {eventByUUID: event} = {}} = useEventByUuidQuery({ - pollInterval: POLL_INTERVAL, - variables: {uuid: eventUUID}, - }); - - useEffect(() => { - if (event) setEvent(event as EventType); - }, [event]); - - const onSave = async e => { - try { - const {uuid, ...data} = eventUpdate; - const {id, __typename, travels, users, waitingList, ...input} = data; - await updateEvent({ - variables: {uuid, eventUpdate: input as EditEventInput}, - refetchQueries: ['eventByUUID'], - }); - setIsEditing(false); - } catch (error) { - console.error(error); - addToast(t('event.errors.cant_update')); - } - }; const canAddSelf = useMemo(() => { if (!user) return false;

@@ -96,27 +36,13 @@ );

return !(isInWaitingList || isInTravel); }, [event, user]); - if (!event || loading) return <Loading />; - return ( - <Layout - className={classes.layout} - pageTitle={t('event.title', {title: event.name})} - menuTitle={t('event.title', {title: event.name})} - displayMenu={false} - > - <EventBar event={event} onAdd={setIsAddToMyEvent} onSave={onSave} /> - <DrawerMenu /> + <> <WaitingList canAddSelf={canAddSelf} getToggleNewPassengerDialogFunction={(addSelf: boolean) => () => toggleNewPassengerToWaitingList({addSelf})} /> - <AddToMyEventDialog - event={event} - open={isAddToMyEvent} - onClose={() => setIsAddToMyEvent(false)} - /> {!!addPassengerToWaitingListContext && ( <AddPassengerToWaitingList open={!!addPassengerToWaitingListContext}

@@ -124,7 +50,7 @@ toggle={() => toggleNewPassengerToWaitingList(null)}

addSelf={addPassengerToWaitingListContext.addSelf} /> )} - </Layout> + </> ); };

@@ -150,10 +76,4 @@ },

}; } -const useStyles = makeStyles(theme => ({ - layout: ({bannerOffset}) => ({ - paddingTop: theme.mixins.toolbar.minHeight + bannerOffset, - }), -})); - -export default EventPage; +export default Page;