diff --git a/src/components/client/one-time-donation/FormikStepper.tsx b/src/components/client/one-time-donation/FormikStepper.tsx index 3a270b8fa..968758d1a 100644 --- a/src/components/client/one-time-donation/FormikStepper.tsx +++ b/src/components/client/one-time-donation/FormikStepper.tsx @@ -35,11 +35,14 @@ export type GenericFormProps = PropsWithChildren> export function FormikStepper({ children, ...props }: GenericFormProps) { const childrenArray = React.Children.toArray(children) as React.ReactElement[] - const { step, setStep } = useContext(StepsContext) + const { step, setStep, updateDonationSession, clearDonationSession } = useContext(StepsContext) const router = useRouter() const mobile = useMediaQuery('(max-width:568px)') useEffect(() => { - router.query.success === 'false' || router.query.success === 'true' ? setStep(3) : null + if (router.query.success === 'true' || router.query.success === 'false') { + setStep(3) + router.query.success === 'true' && clearDonationSession() + } }, [router.query.success]) const currentChild = childrenArray[step] const { data: session } = useSession() @@ -59,6 +62,7 @@ export function FormikStepper({ children, ...props }: GenericFormProps { @@ -67,13 +71,15 @@ export function FormikStepper({ children, ...props }: GenericFormProps { + updateDonationSession(values, step + 1) if (isLastStep()) { values.isAnonymous = isLogged() === false ? true : values.isAnonymous ?? !isLogged() await props.onSubmit(values, helpers) @@ -84,7 +90,7 @@ export function FormikStepper({ children, ...props }: GenericFormProps - {({ isSubmitting, handleSubmit, isValid, values: { isAnonymous } }) => ( + {({ isSubmitting, handleSubmit, isValid, values }) => (
{ + updateDonationSession(values, step - 1) setStep((s) => s - 1) }}> {t('btns.back')} @@ -124,7 +131,7 @@ export function FormikStepper({ children, ...props }: GenericFormProps const { campaign } = data @@ -152,18 +155,20 @@ export default function DonationStepper({ onStepChange }: DonationStepperProps) validate: null, }, ] - const [step, setStep] = React.useState(0) + + const [step, setStep] = React.useState(donateSession?.step ?? 0) React.useEffect(() => { onStepChange() }, [step]) return ( - + {isLoading ? ( ) : ( - + {steps.map(({ label, component, validate }) => ( {component} diff --git a/src/components/client/one-time-donation/helpers/donateSession.ts b/src/components/client/one-time-donation/helpers/donateSession.ts new file mode 100644 index 000000000..04df6771c --- /dev/null +++ b/src/components/client/one-time-donation/helpers/donateSession.ts @@ -0,0 +1,65 @@ +import { OneTimeDonation } from 'gql/donations' +import { useState } from 'react' + +const PREFIX = 'donation-session-' + +type DonationSession = { + values: OneTimeDonation + step: number +} + +function createSessionObject( + campaignSlug: string, + values: OneTimeDonation, + step: number, +): DonationSession { + const donationSession = sessionStorage.getItem(PREFIX + campaignSlug) + //Session already exists do nothing + if (donationSession) return JSON.parse(donationSession) + const sessionObj = { values, step } + sessionStorage.setItem(PREFIX + campaignSlug, JSON.stringify(sessionObj)) + return sessionObj +} + +function updateSessionObject( + campaignSlug: string, + values: OneTimeDonation, + step: number, +): DonationSession { + const donationSession = sessionStorage.getItem(PREFIX + campaignSlug) + if (!donationSession) { + // if session does not exist create new one. + return createSessionObject(campaignSlug, values, step) + } + + const newSessionObj = { values, step } + sessionStorage.setItem(PREFIX + campaignSlug, JSON.stringify(newSessionObj)) + return newSessionObj +} + +function getSessionObject(campaignSlug: string): DonationSession | null { + const donationSession = sessionStorage.getItem(PREFIX + campaignSlug) + if (!donationSession) return null + return JSON.parse(donationSession) +} + +function destroySessionObject(campaignSlug: string): void { + sessionStorage.removeItem(PREFIX + campaignSlug) +} + +export function useDonationStepSession(campaignSlug: string) { + const sessionObj = getSessionObject(campaignSlug) + const [donationSession, setDonationSession] = useState(sessionObj) + + const updateDonationSession = (value: OneTimeDonation, step: number) => { + const newSessionObj = updateSessionObject(campaignSlug, value, step) + setDonationSession(newSessionObj) + } + + const clearDonationSession = () => { + destroySessionObject(campaignSlug) + setDonationSession(null) + } + + return [donationSession, { updateDonationSession, clearDonationSession }] as const +} diff --git a/src/components/client/one-time-donation/helpers/stepperContext.ts b/src/components/client/one-time-donation/helpers/stepperContext.ts index 327981246..7477c3ba3 100644 --- a/src/components/client/one-time-donation/helpers/stepperContext.ts +++ b/src/components/client/one-time-donation/helpers/stepperContext.ts @@ -1,9 +1,12 @@ import { createContext } from 'react' import { CampaignResponse } from 'gql/campaigns' +import { OneTimeDonation } from 'gql/donations' type Steps = { step: number setStep: React.Dispatch> campaign: CampaignResponse + updateDonationSession: (value: OneTimeDonation, step: number) => void + clearDonationSession: () => void } export const StepsContext = createContext({} as Steps)