all repos — caroster @ 9266a128ea9415a64c55fdc8e98990f815e0be66

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

frontend/hooks/useTour.ts (view raw)

  1import {useEffect, useMemo} from 'react';
  2import {useTranslation} from 'react-i18next';
  3import {CallBackProps, STATUS, EVENTS, ACTIONS} from 'react-joyride';
  4import {useUpdateMeMutation} from '../generated/graphql';
  5import useOnboardingStore from '../stores/useOnboardingStore';
  6import useTourStore from '../stores/useTourStore';
  7import useEventStore from '../stores/useEventStore';
  8import useAddToEvents from '../hooks/useAddToEvents';
  9import useProfile from './useProfile';
 10
 11const STEP_SETTINGS = {
 12  disableBeacon: true,
 13  disableOverlayClose: true,
 14  hideCloseButton: true,
 15  hideFooter: false,
 16  spotlightClicks: false,
 17  showSkipButton: true,
 18  styles: {
 19    options: {
 20      zIndex: 10000,
 21    },
 22  },
 23};
 24
 25const useTour = () => {
 26  const {t} = useTranslation();
 27  const isCreator = useTourStore(s => s.isCreator);
 28  const run = useTourStore(s => s.run);
 29  const step = useTourStore(s => s.step);
 30  const prev = useTourStore(s => s.prev);
 31  const setTour = useTourStore(s => s.setTour);
 32  const onboardingUser = useOnboardingStore(s => s.onboardingUser);
 33  const onboardingCreator = useOnboardingStore(s => s.onboardingCreator);
 34  const setOnboarding = useOnboardingStore(s => s.setOnboarding);
 35  const {profile, isReady} = useProfile();
 36  const event = useEventStore(s => s.event);
 37  const {eventsToBeAdded} = useAddToEvents();
 38  const [updateProfile] = useUpdateMeMutation();
 39
 40  // Check if user is the event creator
 41  useEffect(() => {
 42    if (!isReady || !event) return;
 43
 44    let newIsCreator = eventsToBeAdded.includes(event?.id);
 45    if (profile) newIsCreator = profile.events.map(e => e.id).includes(event?.id);
 46
 47    setTour({isCreator: newIsCreator});
 48  }, [isReady, event, eventsToBeAdded, profile]);
 49
 50  const steps = useMemo(() => {
 51    if (isCreator === null) return [];
 52    return isCreator
 53      ? [
 54          {content: t`tour.creator.step1`, target: '.tour_event_infos'},
 55          {content: t`tour.creator.step2`, target: '.tour_event_edit'},
 56          {content: t`tour.creator.step3`, target: '.tour_event_share'},
 57          {content: t`tour.creator.step4`, target: '.tour_waiting_list'},
 58          {content: t`tour.creator.step5`, target: '.tour_travel_add'},
 59        ].map(currentStep => ({...currentStep, ...STEP_SETTINGS}))
 60      : [
 61          {content: t`tour.user.step1`, target: '.tour_travel_add'},
 62          {content: t`tour.user.step2`, target: '.tour_waiting_list'},
 63          {content: t`tour.user.step3`, target: '.tour_event_infos'},
 64          {content: t`tour.user.step4`, target: '.tour_event_share'},
 65        ].map(currentStep => ({...currentStep, ...STEP_SETTINGS}));
 66  }, [isCreator]);
 67
 68  // On step change : wait for the UI a little and run it
 69  useEffect(() => {
 70    let timer;
 71    if (step >= 0 && step !== prev)
 72      timer = setTimeout(() => setTour({run: true}), 250);
 73    return () => clearTimeout(timer);
 74  }, [step]);
 75
 76  const onFinish = () => {
 77    if (profile) {
 78      if (isCreator && !profile.onboardingCreator)
 79        updateProfile({variables: {userUpdate: {onboardingCreator: true}}});
 80      else if (!isCreator && !profile.onboardingUser)
 81        updateProfile({variables: {userUpdate: {onboardingUser: true}}});
 82    } else {
 83      if (isCreator && !onboardingCreator)
 84        setOnboarding({onboardingCreator: true});
 85      else if (!isCreator && !onboardingUser)
 86        setOnboarding({onboardingUser: true});
 87    }
 88  };
 89
 90  const onTourChange = (data: CallBackProps) => {
 91    const {action, index, type, status} = data;
 92
 93    if (
 94      ([EVENTS.STEP_AFTER, EVENTS.TARGET_NOT_FOUND] as string[]).includes(type)
 95    ) {
 96      if (action === ACTIONS.CLOSE) {
 97        setTour({run: false, step: -1, prev: -1});
 98      } else {
 99        setTour({
100          run: false,
101          step: index + (action === ACTIONS.PREV ? -1 : 1),
102          prev: index,
103        });
104      }
105    } else if (
106      ([STATUS.FINISHED, STATUS.SKIPPED] as string[]).includes(status)
107    ) {
108      setTour({run: false, step: -1, prev: -1});
109      if (status === STATUS.FINISHED) onFinish();
110    }
111  };
112
113  return {
114    run,
115    steps,
116    step,
117    onTourChange,
118  };
119};
120
121export default useTour;