all repos — caroster @ v0.11.0

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

frontend/hooks/useTour.ts (view raw)

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