Skip to content

Commit

Permalink
move useNavigationHelpers to its own file
Browse files Browse the repository at this point in the history
  • Loading branch information
jthrilly committed Jan 11, 2024
1 parent def37c9 commit 94fc619
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 153 deletions.
135 changes: 2 additions & 133 deletions lib/interviewer/components/Navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,140 +1,9 @@
import React, { useCallback, useEffect } from 'react';
import { useEffect } from 'react';
import ProgressBar from '~/lib/ui/components/ProgressBar';
import { ChevronDown, ChevronUp, SettingsIcon } from 'lucide-react';
import { cn } from '~/utils/shadcn';
import { useDispatch, useSelector } from 'react-redux';
import { getNavigationInfo } from '../selectors/session';
import { getSkipMap } from '../selectors/skip-logic';
import { parseAsInteger, useQueryState } from 'next-usequerystate';
import { actionCreators as sessionActions } from '../ducks/modules/session';
import useReadyForNextStage from '../hooks/useReadyForNextStage';
import usePrevious from '~/hooks/usePrevious';

export const useNavigationHelpers = (
currentStage: number,
setCurrentStage: (stage: number) => void,
) => {
const dispatch = useDispatch();
const skipMap = useSelector(getSkipMap);

const { isReady: isReadyForNextStage } = useReadyForNextStage();

const {
progress,
currentStep,
isLastPrompt,
isFirstPrompt,
isLastStage,
promptIndex,
canMoveBackward,
canMoveForward,
} = useSelector(getNavigationInfo);

// const prevStageIndex = usePrevious(currentStep);

const calculateNextStage = useCallback(() => {
const nextStage = Object.keys(skipMap).find(
(stage) =>
parseInt(stage) > currentStage && skipMap[parseInt(stage)] === false,
);

if (!nextStage) {
return currentStage;
}

return parseInt(nextStage);
}, [currentStage, skipMap]);

const calculatePreviousStage = useCallback(() => {
const previousStage = Object.keys(skipMap)
.reverse()
.find((stage) => parseInt(stage) < currentStage);

if (!previousStage) {
return currentStage;
}

return parseInt(previousStage);
}, [currentStage, skipMap]);

const validateCurrentStage = useCallback(() => {
if (!skipMap[currentStage] === false) {
const previousValidStage = calculatePreviousStage();

if (previousValidStage) {
setCurrentStage(previousValidStage);
}
}
}, [calculatePreviousStage, setCurrentStage, currentStage, skipMap]);

const moveForward = useCallback(() => {
if (isLastPrompt) {
const nextStage = calculateNextStage();
setCurrentStage(nextStage);
return;
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
dispatch(sessionActions.updatePrompt(promptIndex + 1));
}, [
dispatch,
isLastPrompt,
promptIndex,
calculateNextStage,
setCurrentStage,
]);

// Move to the previous available stage in the interview based on the current stage and skip logic
const moveBackward = () => {
if (isFirstPrompt) {
const previousStage = calculatePreviousStage();
setCurrentStage(previousStage);
return;
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
dispatch(sessionActions.updatePrompt(promptIndex - 1));
};

const prevCurrentStage = usePrevious(currentStage);

const needToDispatch = useCallback(() => {
if (currentStage === prevCurrentStage) {
return false;
}

if (currentStage === currentStep) {
return false;
}

return true;
}, [currentStage, prevCurrentStage, currentStep]);

useEffect(() => {
if (!needToDispatch()) {
return;
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
dispatch(sessionActions.updateStage(currentStage));
}, [currentStage, dispatch, needToDispatch]);

return {
progress,
isReadyForNextStage,
canMoveForward,
canMoveBackward,
moveForward,
moveBackward,
validateCurrentStage,
isFirstPrompt,
isLastPrompt,
isLastStage,
};
};
import { useNavigationHelpers } from '../hooks/useNavigationHelpers';

const NavigationButton = ({
disabled,
Expand Down
6 changes: 4 additions & 2 deletions lib/interviewer/containers/Interfaces/EgoForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,14 +234,16 @@ EgoForm.propTypes = {
form: PropTypes.object.isRequired,
introductionPanel: PropTypes.object.isRequired,
ego: PropTypes.object,
currentStep: PropTypes.number.isRequired,
stage: PropTypes.shape({
id: PropTypes.string.isRequired,
}).isRequired,
submitForm: PropTypes.func.isRequired,
updateEgo: PropTypes.func.isRequired,
};

function mapStateToProps(state, props) {
const ego = getNetworkEgo(state);
const formName = getFormName(props.currentStep);
const formName = getFormName(props.stage.id);
const isFormValid = isValid(formName)(state);
const isFormDirty = () => isDirty(formName)(state);
const { isFirstStage } = getSessionProgress(state);
Expand Down
19 changes: 14 additions & 5 deletions lib/interviewer/containers/ProtocolScreen.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { AnimatePresence, motion } from 'framer-motion';
import { parseAsInteger, useQueryState } from 'next-usequerystate';
import { useState } from 'react';
import { useRef, useState } from 'react';
import { useSelector } from 'react-redux';
import Navigation, { useNavigationHelpers } from '../components/Navigation';
import { getCurrentStage } from '../selectors/session';
import Stage from './Stage';
import { get } from '../utils/lodash-replacements';

const ProtocolScreen = () => {
let beforeNextFunctions = {};
const beforeNextFunctions = useRef({});
const currentStage = useSelector(getCurrentStage);
const [pendingDirection, setPendingDirection] = useState(1);
const [currentStageNumber, setCurrentStageNumber] = useQueryState(
Expand All @@ -22,6 +22,7 @@ const ProtocolScreen = () => {
);

const onComplete = (directionOverride) => {
console.log('onComplete', directionOverride);
const nextDirection = directionOverride || pendingDirection;
const beforeNext = get(beforeNextFunctions, currentStage?.id);

Expand All @@ -38,11 +39,19 @@ const ProtocolScreen = () => {
setPendingDirection(1);
};

const registerBeforeNext = (beforeNext, stageId) => {
if (beforeNext === null) return;
beforeNextFunctions = { ...beforeNextFunctions, [stageId]: beforeNext };
const registerBeforeNext = (beforeNext) => {
console.log('registerbeforenext', currentStage.id);

if (beforeNext === null || !currentStage.id) return;

// Ignore if function already exists
if (beforeNextFunctions.current[currentStage.id]) return;

beforeNextFunctions.current = { ...beforeNextFunctions.current, [currentStage.id]: beforeNext };
};

console.log('beforeNextFunctions', beforeNextFunctions.current);

return (
<motion.div
className="flex w-full flex-1 flex-row"
Expand Down
14 changes: 1 addition & 13 deletions lib/interviewer/containers/Stage.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,7 @@ import { motion } from 'framer-motion';


const Stage = (props) => {
const { stage, registerBeforeNext: register } = props;

const registerBeforeNext = useCallback((beforeNext) => register(
beforeNext,
stage.id,
), [register, stage.id]);

useLayoutEffect(() => {
return () => {
register(null, stage.id)
}
}, [register, stage.id])

const { stage, registerBeforeNext } = props;
const CurrentInterface = getInterface(stage.type);

return (
Expand Down
133 changes: 133 additions & 0 deletions lib/interviewer/hooks/useNavigationHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getNavigationInfo } from '../selectors/session';
import { getSkipMap } from '../selectors/skip-logic';
import { actionCreators as sessionActions } from '../ducks/modules/session';
import useReadyForNextStage from '../hooks/useReadyForNextStage';
import usePrevious from '~/hooks/usePrevious';

export const useNavigationHelpers = (
currentStage: number,
setCurrentStage: (stage: number) => void,
) => {
const dispatch = useDispatch();
const skipMap = useSelector(getSkipMap);

const { isReady: isReadyForNextStage } = useReadyForNextStage();

const {
progress,
currentStep,
isLastPrompt,
isFirstPrompt,
isLastStage,
promptIndex,
canMoveBackward,
canMoveForward,
} = useSelector(getNavigationInfo);

// const prevStageIndex = usePrevious(currentStep);

const calculateNextStage = useCallback(() => {
const nextStage = Object.keys(skipMap).find(
(stage) =>
parseInt(stage) > currentStage && skipMap[parseInt(stage)] === false,
);

if (!nextStage) {
return currentStage;
}

return parseInt(nextStage);
}, [currentStage, skipMap]);

const calculatePreviousStage = useCallback(() => {
const previousStage = Object.keys(skipMap)
.reverse()
.find((stage) => parseInt(stage) < currentStage);

if (!previousStage) {
return currentStage;
}

return parseInt(previousStage);
}, [currentStage, skipMap]);

const validateCurrentStage = useCallback(() => {
if (!skipMap[currentStage] === false) {
const previousValidStage = calculatePreviousStage();

if (previousValidStage) {
setCurrentStage(previousValidStage);
}
}
}, [calculatePreviousStage, setCurrentStage, currentStage, skipMap]);

const moveForward = useCallback(() => {
if (isLastPrompt) {
const nextStage = calculateNextStage();
setCurrentStage(nextStage);
return;
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
dispatch(sessionActions.updatePrompt(promptIndex + 1));
}, [
dispatch,
isLastPrompt,
promptIndex,
calculateNextStage,
setCurrentStage,
]);

// Move to the previous available stage in the interview based on the current stage and skip logic
const moveBackward = () => {
if (isFirstPrompt) {
const previousStage = calculatePreviousStage();
setCurrentStage(previousStage);
return;
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
dispatch(sessionActions.updatePrompt(promptIndex - 1));
};

const prevCurrentStage = usePrevious(currentStage);

const needToDispatch = useCallback(() => {
if (currentStage === prevCurrentStage) {
return false;
}

if (currentStage === currentStep) {
return false;
}

return true;
}, [currentStage, prevCurrentStage, currentStep]);

useEffect(() => {
if (!needToDispatch()) {
return;
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
dispatch(sessionActions.updateStage(currentStage));
}, [currentStage, dispatch, needToDispatch]);

return {
progress,
isReadyForNextStage,
canMoveForward,
canMoveBackward,
moveForward,
moveBackward,
validateCurrentStage,
isFirstPrompt,
isLastPrompt,
isLastStage,
};
};

0 comments on commit 94fc619

Please sign in to comment.