diff --git a/src/app/page.tsx b/src/app/page.tsx index fc62889..e6c8f33 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,7 +2,7 @@ import { NewsletterForm } from '@/components/NewsletterForm'; export default function Home() { return ( -
+
); diff --git a/src/components/NewsletterForm.tsx b/src/components/NewsletterForm.tsx index ed65a72..f6f0d05 100644 --- a/src/components/NewsletterForm.tsx +++ b/src/components/NewsletterForm.tsx @@ -36,12 +36,35 @@ import { newsletterFormSchema, FrameworksSchema, } from '@/schemas/newsletterSchemas'; -import { useMemo, useState } from 'react'; +import { useState } from 'react'; import { cn } from '@/lib/utils'; import useWindowSize from 'react-use/lib/useWindowSize'; +import { z } from 'zod'; +import { motion } from 'framer-motion'; + +const steps = [ + { + fields: ['firstName', 'lastName'], + }, + { + fields: ['framework'], + }, + { + fields: ['email'], + }, +]; + +type Inputs = z.infer; +type FieldName = keyof Inputs; export const NewsletterForm = () => { - const [step, setStep] = useState(0); + const [step, setStep] = useState({ + current: 0, + previous: 0, + }); + // we need delta to determine way of transition animation + const delta = step.current - step.previous; + const [submitted, setSubmitted] = useState(false); const { width, height } = useWindowSize(); @@ -61,98 +84,34 @@ export const NewsletterForm = () => { console.log(values); } - const steps = useMemo( - () => [ - { - markup: ( -
- ( - - First name - - - - - - )} - /> - ( - - Last name - - - - - - )} - /> -
- ), - validate: ['firstName'], - }, - { - markup: ( -
- ( - - Your preferred JS framework - - - - )} - /> -
- ), - validate: ['framework'], - }, - { - markup: ( -
- ( - - Your email - - - - - - )} - /> -
- ), - validate: ['email'], - }, - ], - [] - ); + const next = async () => { + const fields = steps[step.current].fields; + const output = await form.trigger(fields as FieldName[], { + shouldFocus: false, + }); + + if (!output) return; + + if (step.current < steps.length - 1) { + if (step.current === steps.length - 2) { + await form.handleSubmit(console.log)(); + } + + setStep((prevState) => ({ + previous: prevState.current, + current: prevState.current + 1, + })); + } + }; + + const prev = () => { + if (step.current > 0) { + setStep((prevState) => ({ + previous: prevState.current, + current: prevState.current - 1, + })); + } + }; if (submitted) return ( @@ -180,8 +139,101 @@ export const NewsletterForm = () => {
-
- {steps[step].markup} +
+ {step.current === 0 && ( + = 0 ? '50%' : '-50%', opacity: 0 }} + animate={{ x: 0, opacity: 1 }} + transition={{ duration: 0.3, ease: 'easeInOut' }} + > + ( + + First name + + + + + + )} + /> + ( + + Last name + + + + + + )} + /> + + )} + {step.current === 1 && ( + = 0 ? '50%' : '-50%', opacity: 0 }} + animate={{ x: 0, opacity: 1 }} + transition={{ duration: 0.3, ease: 'easeInOut' }} + > + ( + + Your preferred JS framework + + + + )} + /> + + )} + {step.current === 2 && ( + = 0 ? '50%' : '-50%', opacity: 0 }} + animate={{ x: 0, opacity: 1 }} + transition={{ duration: 0.3, ease: 'easeInOut' }} + > + ( + + Your email + + + + + + )} + /> + + )}
@@ -190,41 +242,26 @@ export const NewsletterForm = () => {