diff --git a/src/flow/Flow.tsx b/src/flow/Flow.tsx index a468529..b69dc0b 100644 --- a/src/flow/Flow.tsx +++ b/src/flow/Flow.tsx @@ -1,76 +1,119 @@ +import React from 'react' import { useState, FC } from 'react' export type GenericStepProps = { next?: () => void previous?: () => void updateState: (s: Partial) => void - skip?: () => void + hidden?: boolean } & S -type Direction = 'forwards' | 'backwards' - export function Flow( props: { steps: Array>> } & { updateState: (state: Partial) => void next?: () => void previous?: () => void name: string + hidden?: boolean } & S, ) { const parentPrevious = props.previous const parentNext = props.next - let nextPreviousCalledThisRender = false + // let nextPreviousCalledThisRender = false const [currentStepIndex, setCurrentStepIndex] = useState(0) - const [direction, setDirection] = useState('forwards') - const isNestedFlow = parentPrevious || parentNext - const canProgress = currentStepIndex < props.steps.length - 1 - const canRegress = currentStepIndex > 0 - - const next = canProgress - ? () => { - nextPreviousCalledThisRender = true - setDirection('forwards') - setCurrentStepIndex((currentStep) => currentStep + 1) - } - : isNestedFlow - ? parentNext - : undefined - - const previous = canRegress - ? () => { - nextPreviousCalledThisRender = true - setDirection('backwards') - setCurrentStepIndex((currentStep) => currentStep - 1) - } - : isNestedFlow - ? parentPrevious - : undefined - - const skip = direction === 'forwards' ? next : previous - - const currentStep = props.steps[currentStepIndex] - - if ( - nextPreviousCalledThisRender && - isSkippable(currentStep) && - skip && - currentStep.canSkip(props) + // calculate next step + let potentialNextStepIndex = currentStepIndex + 1 + let potentialNextStep = props.steps[potentialNextStepIndex] + + while (potentialNextStep && isSkippable(potentialNextStep) && potentialNextStep.canSkip(props)) { + potentialNextStepIndex = potentialNextStepIndex + 1 + potentialNextStep = props.steps[potentialNextStepIndex] + } + + // calculate previous step + let potentialPreviousStepIndex = currentStepIndex - 1 + let potentialPreviousStep = props.steps[potentialPreviousStepIndex] + + while ( + potentialPreviousStep && + isSkippable(potentialPreviousStep) && + potentialPreviousStep.canSkip(props) ) { - console.log(`skipping step with index ${currentStepIndex} in flow ${props.name}`) - skip() + potentialPreviousStepIndex = potentialPreviousStepIndex - 1 + potentialPreviousStep = props.steps[potentialPreviousStepIndex] + } + + const isNestedFlow = parentPrevious || parentNext + + const getNext = (stepIndex: number) => { + const canProgress = stepIndex === currentStepIndex && currentStepIndex < props.steps.length - 1 + const next = canProgress + ? () => setCurrentStepIndex(potentialNextStepIndex) + : isNestedFlow + ? parentNext + : undefined + + return next } - return + const getPrevious = (stepIndex: number) => { + const canRegress = stepIndex === currentStepIndex && currentStepIndex > 0 + + const previous = canRegress + ? () => setCurrentStepIndex(potentialPreviousStepIndex) + : isNestedFlow + ? parentPrevious + : undefined + + return previous + } + + return ( + <> + {props.steps.map((Step, stepIndex) => { + const hideStep = stepIndex !== currentStepIndex + + const next = getNext(stepIndex) + const previous = getPrevious(stepIndex) + + return ( + props.hidden || hideStep} + > + + ) + })} + + ) } +export const Hidden: React.FC<{ + hiddenIf: () => boolean + children?: React.ReactNode +}> = ({ hiddenIf, children }) => ( +
+ {children} +
+) + function isSkippable(step: IStep | ISkippableStep): step is ISkippableStep { return (step as ISkippableStep).canSkip !== undefined } export interface IStep { Component: FC> + displayName: string } export interface ISkippableStep extends IStep { diff --git a/src/flow/OpenBorrowVault.tsx b/src/flow/OpenBorrowVault.tsx index f000f98..150d916 100644 --- a/src/flow/OpenBorrowVault.tsx +++ b/src/flow/OpenBorrowVault.tsx @@ -26,7 +26,7 @@ export function OpenBorrowVault() { setViewState((oldState) => { return calculateViewModal({ ...oldState, ethPrice: Math.floor(Math.random() * 10000) }) }) - }, 1000) + }, 10000) return () => clearInterval(i) }) diff --git a/src/flow/allowance/Allowance.tsx b/src/flow/allowance/Allowance.tsx index d11d54c..3a836bf 100644 --- a/src/flow/allowance/Allowance.tsx +++ b/src/flow/allowance/Allowance.tsx @@ -4,31 +4,21 @@ import { ConfigureAllowanceAmountProps, } from './steps/ConfigureAllowanceAmount' import { Done, DoneProps } from './steps/Done' -import { useEffect, useState } from 'react' export type AllowanceProps = ConfigureAllowanceAmountProps & DoneProps export const Allowance: ISkippableStep = { Component: (props: GenericStepProps) => { - const [viewState, setViewState] = useState(props) - - useEffect(() => { - if (props.configuredAllowance) { - props.skip!() - } - }, []) - return ( - {...viewState} + {...props} name="allowance" steps={[ConfigureAllowanceAmount, Done]} - updateState={(newState) => { - setViewState((oldState) => ({ ...oldState, ...newState })) - props.updateState(newState) - }} + updateState={(newState) => props.updateState(newState)} + hidden={props.hidden} /> ) }, canSkip: (props) => !!props.configuredAllowance, + displayName: 'Allowance', } diff --git a/src/flow/allowance/steps/ConfigureAllowanceAmount.tsx b/src/flow/allowance/steps/ConfigureAllowanceAmount.tsx index 34b6a4b..7c7ae62 100644 --- a/src/flow/allowance/steps/ConfigureAllowanceAmount.tsx +++ b/src/flow/allowance/steps/ConfigureAllowanceAmount.tsx @@ -1,4 +1,4 @@ -import { GenericStepProps, IStep } from '../../Flow' +import { GenericStepProps, ISkippableStep } from '../../Flow' import { SyntheticEvent, useState } from 'react' import { useLoadingDots } from '../../hooks/useLoadingDots' @@ -9,7 +9,7 @@ export type ConfigureAllowanceAmountProps = { type AllowanceRequestState = 'not sent' | 'in progress' | 'done' -export const ConfigureAllowanceAmount: IStep = { +export const ConfigureAllowanceAmount: ISkippableStep = { Component: (props: GenericStepProps) => { const [allowanceRequestState, setAllowanceRequestState] = useState('not sent') @@ -92,4 +92,11 @@ export const ConfigureAllowanceAmount: IStep = { ) }, + canSkip: (props: ConfigureAllowanceAmountProps) => + !!( + props.configuredAllowance && + props.depositAmount && + props.configuredAllowance >= props.depositAmount + ), + displayName: 'Allowance|ConfigureAllowanceAmount', } diff --git a/src/flow/allowance/steps/Done.tsx b/src/flow/allowance/steps/Done.tsx index d5e9cd7..febd119 100644 --- a/src/flow/allowance/steps/Done.tsx +++ b/src/flow/allowance/steps/Done.tsx @@ -12,4 +12,5 @@ export const Done: IStep = { ) }, + displayName: 'Allowance|Done', } diff --git a/src/flow/create-proxy/CreateProxy.tsx b/src/flow/create-proxy/CreateProxy.tsx index f7266a8..12b842e 100644 --- a/src/flow/create-proxy/CreateProxy.tsx +++ b/src/flow/create-proxy/CreateProxy.tsx @@ -1,5 +1,4 @@ -import { Flow, GenericStepProps, ISkippableStep } from '../Flow' -import { FC, useState } from 'react' +import { Flow, ISkippableStep } from '../Flow' import { Explanation, ExplanationProps } from './steps/Explanation' import { Creation, CreationProps } from './steps/Creation' import { Done, DoneProps } from './steps/Done' @@ -7,23 +6,19 @@ import { Done, DoneProps } from './steps/Done' export type CreateProxyProps = ExplanationProps & CreationProps & DoneProps export const CreateProxy: ISkippableStep = { - Component: (props) => { - const [viewState, setViewState] = useState(props) - + Component: function CreateProxy(props) { return ( - {...viewState} + {...props} name="proxy" steps={[Explanation, Creation, Done]} - updateState={(newState) => { - setViewState((oldState) => ({ ...oldState, ...newState })) - props.updateState(newState) - }} + updateState={(newState) => props.updateState(newState)} + hidden={props.hidden} /> ) }, canSkip: (props: CreateProxyProps) => { - console.log('here') return !!props.proxyAddress }, + displayName: 'CreateProxy', } diff --git a/src/flow/create-proxy/steps/Creation.tsx b/src/flow/create-proxy/steps/Creation.tsx index 5b125b5..1053491 100644 --- a/src/flow/create-proxy/steps/Creation.tsx +++ b/src/flow/create-proxy/steps/Creation.tsx @@ -1,7 +1,6 @@ import { GenericStepProps, IStep } from '../../Flow' import { useEffect } from 'react' import { useLoadingDots } from '../../hooks/useLoadingDots' -import { clear } from '@testing-library/user-event/dist/clear' export type CreationProps = { walletAddress: string @@ -9,18 +8,19 @@ export type CreationProps = { } export const Creation: IStep = { - Component: (props: GenericStepProps) => { + Component: function Creation(props: GenericStepProps) { const dots = useLoadingDots() useEffect(() => { const i = setTimeout(() => { - console.log('updating step') - props.updateState({ proxyAddress: '0xProxyAddress' }) - console.log('calling next') - props.next!() + if (!props.hidden) { + console.log('updating step') + props.updateState({ proxyAddress: '0xProxyAddress' }) + props.next!() + } }, 3000) return () => clearTimeout(i) - }, []) + }, [props.hidden]) return ( <> @@ -30,4 +30,5 @@ export const Creation: IStep = { ) }, + displayName: 'Creation', } diff --git a/src/flow/create-proxy/steps/Done.tsx b/src/flow/create-proxy/steps/Done.tsx index be4f9ab..ee856fd 100644 --- a/src/flow/create-proxy/steps/Done.tsx +++ b/src/flow/create-proxy/steps/Done.tsx @@ -15,4 +15,5 @@ export const Done: IStep = { ) }, + displayName: 'Done', } diff --git a/src/flow/create-proxy/steps/Explanation.tsx b/src/flow/create-proxy/steps/Explanation.tsx index 6285691..e5f4433 100644 --- a/src/flow/create-proxy/steps/Explanation.tsx +++ b/src/flow/create-proxy/steps/Explanation.tsx @@ -24,4 +24,5 @@ export const Explanation: IStep = { ) }, + displayName: 'Explanation', } diff --git a/src/flow/steps/Complete.tsx b/src/flow/steps/Complete.tsx index 95beaf0..fb64f02 100644 --- a/src/flow/steps/Complete.tsx +++ b/src/flow/steps/Complete.tsx @@ -17,4 +17,5 @@ export const Complete: IStep = { ) }, + displayName: 'Complete', } diff --git a/src/flow/steps/Confirmation.tsx b/src/flow/steps/Confirmation.tsx index f37144e..475e132 100644 --- a/src/flow/steps/Confirmation.tsx +++ b/src/flow/steps/Confirmation.tsx @@ -43,4 +43,5 @@ export const Confirmation: IStep = { ) }, + displayName: 'Confirmation', } diff --git a/src/flow/steps/SimulateStep.tsx b/src/flow/steps/SimulateStep.tsx index 86a9d0c..0b63556 100644 --- a/src/flow/steps/SimulateStep.tsx +++ b/src/flow/steps/SimulateStep.tsx @@ -40,4 +40,5 @@ export const SimulateStep: IStep = { ) }, + displayName: 'SimulateStep', }