Skip to content

Commit

Permalink
added waillist form (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
arkhurst authored Mar 6, 2024
1 parent 2bc5cb9 commit 8d7647b
Show file tree
Hide file tree
Showing 5 changed files with 308 additions and 1 deletion.
2 changes: 1 addition & 1 deletion apps/wait-list/app/components/spring-modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const SpringModal = ({
isOpen,
setIsOpen,
children,
className = 'bg-white text-gray-800 p-6 rounded-lg w-full max-w-lg shadow-xl cursor-default relative overflow-hidden',
className = 'bg-white text-gray-800 p-6 rounded-lg w-full max-w-xl shadow-xl cursor-default relative overflow-hidden',
}: Props) => {
return (
<AnimatePresence>
Expand Down
104 changes: 104 additions & 0 deletions apps/wait-list/app/modules/landing-page/components/account-type.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {RadioGroup} from '@headlessui/react'
import {CheckCircleIcon} from '@heroicons/react/20/solid'
import {classNames} from '@/lib/classNames.ts'

export type AccountTypeOption = {
id: number
title: string
description: string
value: User
}

const accountTypeList: AccountTypeOption[] = [
{
id: 1,
title: 'Photographer/Creator',
description: 'For photographers or content creator.',
value: 'CREATOR',
},
{
id: 2,
title: 'Client',
description: 'For users who are a client seeking services.',
value: 'CLIENT',
},
]

type Props = {
selectedAccountType: AccountTypeOption | undefined
setSelectedAccountType: React.Dispatch<
React.SetStateAction<AccountTypeOption | undefined>
>
}

export default function AccountType({
selectedAccountType,
setSelectedAccountType,
}: Props) {
return (
<RadioGroup value={selectedAccountType} onChange={setSelectedAccountType}>
<RadioGroup.Label className="block text-sm font-medium leading-6 text-gray-900 mt-3">
Select your user type
</RadioGroup.Label>

<div className="mt-2 grid grid-cols-1 gap-y-4 lg:gap-y-6 sm:grid-cols-2 sm:gap-x-4">
{accountTypeList.map(mailingList => (
<RadioGroup.Option
key={mailingList.id}
value={mailingList}
className={({active}) =>
classNames(
active
? 'border-blue-600 ring-2 ring-blue-600'
: 'border-gray-300',
'relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-none focus:outline-none',
)
}
>
{({checked, active}) => (
<>
<span className="flex flex-1">
<span className="flex flex-col">
<RadioGroup.Label
as="span"
className="block text-sm font-medium text-gray-900"
>
{mailingList.title}
</RadioGroup.Label>
<RadioGroup.Description
as="span"
className="mt-1 flex items-center text-xs lg:text-sm text-gray-500"
>
{mailingList.description}
</RadioGroup.Description>
{/* <RadioGroup.Description
as="span"
className="mt-6 text-sm font-medium text-gray-900"
>
{mailingList.users}
</RadioGroup.Description> */}
</span>
</span>
<CheckCircleIcon
className={classNames(
Boolean(!checked) ? 'invisible' : '',
'h-5 w-5 text-blue-600',
)}
aria-hidden="true"
/>
<span
className={classNames(
active ? 'border' : 'border-2',
checked ? 'border-blue-600' : 'border-transparent',
'pointer-events-none absolute -inset-px rounded-lg',
)}
aria-hidden="true"
/>
</>
)}
</RadioGroup.Option>
))}
</div>
</RadioGroup>
)
}
10 changes: 10 additions & 0 deletions apps/wait-list/app/modules/landing-page/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ import {PhotoGrid} from '@/components/image-slider/index.jsx'
import {BackgroundContainer} from '@/components/layout/container.tsx'
import {Header} from '@/components/layout/header.tsx'
import {MovingBorderButton} from '@/components/moving-border/index.tsx'
import {useBoolean} from '@/hooks/use-boolean.ts'
import WaitListForm from './modals/wait-list-form/index.tsx'

export const LandingPageModule = () => {
const {value: showWaitListForm, setValue, setFalse, setTrue} = useBoolean()

return (
<BackgroundContainer>
<div className="h-[60dvh] md:h-[50vh] lg:h-[50vh] flex flex-col justify-center items-center">
Expand All @@ -19,6 +23,7 @@ export const LandingPageModule = () => {
</p>
<MovingBorderButton
borderRadius="1.25rem"
onClick={setTrue}
className="bg-white text-base font-medium text-black border-gray-200 border "
>
Join waitlist{' '}
Expand All @@ -29,6 +34,11 @@ export const LandingPageModule = () => {
</div>
</div>
<PhotoGrid />
<WaitListForm
show={showWaitListForm}
setShow={setValue}
handleClose={setFalse}
/>
</BackgroundContainer>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import * as Yup from 'yup'
import {SpringModal} from '@/components/spring-modal/index.tsx'
import {useForm} from 'react-hook-form'
import {yupResolver} from '@hookform/resolvers/yup'
import {classNames} from '@/lib/classNames.ts'
import {ExclamationCircleIcon} from '@heroicons/react/24/outline'
import {Button} from '@/components/button/index.tsx'
import {useCallback, useEffect, useState} from 'react'
import AccountType, {
type AccountTypeOption,
} from '../../components/account-type.tsx'

type Props = {
show: boolean
setShow: React.Dispatch<React.SetStateAction<boolean>>
handleClose: () => void
}

interface FormValues {
role: User
name: string
email?: string
phoneNumber: string
}

const schema = Yup.object().shape({
role: Yup.string()
.oneOf(['CLIENT', 'CREATOR'])
.default('CLIENT')
.required('Role is required'),
name: Yup.string().required('Full name is required'),
phoneNumber: Yup.string().required('Phone number is required'),
email: Yup.string(),
})

export default function WaitListForm({show, setShow, handleClose}: Props) {
const [selectedAccountType, setSelectedAccountType] = useState<
AccountTypeOption | undefined
>()
const {
register,
handleSubmit,
formState: {errors},
setValue,
} = useForm<FormValues>({
resolver: yupResolver(schema),
})

useEffect(() => {
if (selectedAccountType) {
setValue('role', selectedAccountType.value)
}
}, [selectedAccountType, setValue])

const onSubmit = useCallback((data: FormValues) => {
console.log(data)
}, [])

return (
<SpringModal isOpen={show} setIsOpen={setShow}>
<form onSubmit={handleSubmit(onSubmit)}>
<h3 className="lg:text-xl text-lg font-medium leading-6 text-center text-gray-900">
Join Our Waitlist
</h3>
<div className="mt-2">
<p className="lg:text-base text-sm text-center text-gray-500 max-w-2xl mx-auto">
Sign up now to join our waitlist and be among the first to access
exclusive features and updates!
</p>

<div className="mt-3">
<div className="flex justify-between">
<label
htmlFor="name"
className="block text-sm font-medium leading-6 text-gray-900"
>
Full Name
</label>
</div>
<div className="relative mt-2">
<input
type="text"
{...register('name')}
className={classNames(
'block w-full rounded-md border-0 py-2.5 lg:py-2 text-gray-900 shadow-nome ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 text-xs lg:text-sm sm:leading-6 ',
errors.name ? 'ring-red-500' : '',
)}
placeholder="Enter your full name"
aria-describedby="name"
/>
{errors.name ? (
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
<ExclamationCircleIcon
className="h-5 w-5 text-red-500"
aria-hidden="true"
/>
</div>
) : null}
</div>
</div>

<div className="mt-3">
<div className="flex justify-between">
<label
htmlFor="phoneNumber"
className="block text-sm font-medium leading-6 text-gray-900"
>
Phone Number
</label>
</div>
<div className="relative mt-2">
<input
type="text"
{...register('phoneNumber')}
className={classNames(
'block w-full rounded-md border-0 py-2.5 lg:py-2 text-gray-900 shadow-nome ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 text-xs lg:text-sm sm:leading-6 ',
errors.phoneNumber ? 'ring-red-500' : '',
)}
placeholder="Enter your phone number"
aria-describedby="phoneNumber"
/>
{errors.phoneNumber ? (
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
<ExclamationCircleIcon
className="h-5 w-5 text-red-500"
aria-hidden="true"
/>
</div>
) : null}
</div>
</div>

<div className="mt-3">
<div className="flex flex-row items-center justify-between">
<label
htmlFor="email"
className="block text-sm font-medium leading-6 text-gray-900"
>
Email Address
</label>
<span className="block text-xs font-medium leading-6 text-red-600">
Optional
</span>
</div>
<div className="relative mt-2">
<input
type="text"
{...register('email')}
className={classNames(
'block w-full rounded-md border-0 py-2.5 lg:py-2 text-gray-900 shadow-nome ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 text-xs lg:text-sm sm:leading-6 ',
errors.email ? 'ring-red-500' : '',
)}
placeholder="Enter your email address"
aria-describedby="email-optional"
/>
{errors.email ? (
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
<ExclamationCircleIcon
className="h-5 w-5 text-red-500"
aria-hidden="true"
/>
</div>
) : null}
</div>
</div>
<AccountType
selectedAccountType={selectedAccountType}
setSelectedAccountType={setSelectedAccountType}
/>
</div>

<div className="mt-8">
<Button
variant="unstyled"
type="submit"
externalClassName="inline-flex justify-center rounded-md border border-transparent bg-blue-100 px-4 py-2.5 lg:py-2 text-sm font-medium text-blue-800 hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
>
Join Waitlist!
</Button>
<Button
variant="outline"
type="button"
externalClassName=" ml-2 "
onClick={handleClose}
>
Close
</Button>
</div>
</form>
</SpringModal>
)
}
1 change: 1 addition & 0 deletions apps/wait-list/types/user.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
type User = 'CLIENT' | 'CREATOR'

0 comments on commit 8d7647b

Please sign in to comment.