Skip to content

Instantly share code, notes, and snippets.

@DevanB
Last active April 17, 2024 13:02
Show Gist options
  • Save DevanB/b75f27154e345498699441664c7d3d3a to your computer and use it in GitHub Desktop.
Save DevanB/b75f27154e345498699441664c7d3d3a to your computer and use it in GitHub Desktop.
Zod + RW Form issues
import { useEffect } from 'react'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import {
EmailField,
FieldError,
Form,
Label,
Submit,
SubmitHandler,
useForm,
} from '@redwoodjs/forms'
import { navigate, routes } from '@redwoodjs/router'
import { Metadata } from '@redwoodjs/web'
import { toast, Toaster } from '@redwoodjs/web/toast'
import { useAuth } from 'src/auth'
const ForgotPasswordSchema = z.object({
email: z
.string({ required_error: 'Please enter an email address' })
.email({ message: 'Please enter a valid email address' }),
})
type ForgotPasswordType = z.infer<typeof ForgotPasswordSchema>
const ForgotPasswordPage = () => {
const { isAuthenticated, forgotPassword } = useAuth()
const formMethods = useForm<ForgotPasswordType>({
mode: 'onBlur',
resolver: zodResolver(ForgotPasswordSchema),
})
useEffect(() => {
if (isAuthenticated) navigate(routes.dashboard())
}, [isAuthenticated])
const onSubmit: SubmitHandler<ForgotPasswordType> = async (data) => {
const response = await forgotPassword(data.email)
if (response.error) {
toast.error(response.error)
} else {
// The function `forgotPassword.handler` in api/src/functions/auth.js has
// been invoked, let the user know how to get the link to reset their
// password (sent in email, perhaps?)
toast.success(
'A link to reset your password was sent to ' + response.email
)
navigate(routes.logIn())
}
}
return (
<>
<Metadata title="Forgot Password" />
<Toaster toastOptions={{ className: 'rw-toast', duration: 6000 }} />
<div className="flex min-h-full flex-1 flex-col justify-center bg-gray-50 py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<h2 className="mt-6 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
Forgot your password?
</h2>
</div>
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px]">
<div className="border bg-white px-6 py-12 sm:rounded-lg sm:px-12">
<Form
className="space-y-6"
formMethods={formMethods}
onSubmit={onSubmit}
>
{/* Email */}
<div>
<Label
name="email"
className="block text-sm font-medium leading-6 text-gray-900"
errorClassName="block text-sm font-medium leading-6 text-red-700"
>
Email address
</Label>
<div className="mt-2">
<EmailField
name="email"
autoComplete="email"
autoCapitalize="off"
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-700 sm:text-sm sm:leading-6"
errorClassName="block w-full rounded-md border-0 py-1.5 text-red-900 shadow-sm ring-1 ring-inset ring-red-300 transition duration-150 ease-in-out placeholder:text-red-300 focus:ring-2 focus:ring-inset focus:ring-red-500 sm:text-sm sm:leading-6"
/>
<FieldError name="email" className="text-sm text-red-600" />
</div>
</div>
<div>
<Submit className="flex w-full justify-center rounded-md bg-gray-900 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm transition duration-150 ease-in-out hover:bg-gray-800 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-700">
Continue
</Submit>
</div>
</Form>
</div>
</div>
</div>
</>
)
}
export default ForgotPasswordPage
import { useEffect } from 'react'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import {
EmailField,
FieldError,
Form,
Label,
PasswordField,
Submit,
SubmitHandler,
useForm,
} from '@redwoodjs/forms'
import { navigate, routes } from '@redwoodjs/router'
import { Metadata } from '@redwoodjs/web'
import { toast, Toaster } from '@redwoodjs/web/toast'
import { useAuth } from 'src/auth'
const LogInSchema = z.object({
email: z
.string({ required_error: 'Please enter an email address' })
.email({ message: 'Please enter a valid email address' }),
password: z.string({ required_error: 'Please enter a password' }),
})
type LogInType = z.infer<typeof LogInSchema>
const LogInPage = () => {
const { isAuthenticated, logIn } = useAuth()
const formMethods = useForm<LogInType>({
mode: 'onBlur',
resolver: zodResolver(LogInSchema),
})
useEffect(() => {
if (isAuthenticated) navigate(routes.dashboard())
}, [isAuthenticated])
const onSubmit: SubmitHandler<LogInType> = async (data) => {
const response = await logIn({
username: data.email,
password: data.password,
})
if (response.message) {
// auth details good, but user not logged in
toast(response.message)
} else if (response.error) {
// error while authenticating
toast.error(response.error)
} else {
// user logged in
toast.success('Welcome back!')
}
}
return (
<>
<Metadata title="Log In" />
<Toaster toastOptions={{ className: 'rw-toast', duration: 6000 }} />
<div className="flex min-h-full flex-1 flex-col justify-center bg-gray-50 py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<h2 className="mt-6 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
Log in to your account
</h2>
</div>
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px]">
<div className="border bg-white px-6 py-12 sm:rounded-lg sm:px-12">
<Form
className="space-y-6"
formMethods={formMethods}
onSubmit={onSubmit}
>
{/* Email */}
<div>
<Label
name="email"
className="block text-sm font-medium leading-6 text-gray-900"
errorClassName="block text-sm font-medium leading-6 text-red-700"
>
Email address
</Label>
<div className="mt-2">
<EmailField
name="email"
autoComplete="email"
autoCapitalize="off"
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-700 sm:text-sm sm:leading-6"
errorClassName="block w-full rounded-md border-0 py-1.5 text-red-900 shadow-sm ring-1 ring-inset ring-red-300 transition duration-150 ease-in-out placeholder:text-red-300 focus:ring-2 focus:ring-inset focus:ring-red-500 sm:text-sm sm:leading-6"
/>
<FieldError name="email" className="text-sm text-red-600" />
</div>
</div>
{/* Password */}
<div>
<Label
name="password"
className="block text-sm font-medium leading-6 text-gray-900"
errorClassName="block text-sm font-medium leading-6 text-red-700"
>
Password
</Label>
<div className="mt-2">
<PasswordField
name="password"
autoComplete="current-password"
autoCapitalize="off"
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-700 sm:text-sm sm:leading-6"
errorClassName="block w-full rounded-md border-0 py-1.5 text-red-900 shadow-sm ring-1 ring-inset ring-red-300 transition duration-150 ease-in-out placeholder:text-red-300 focus:ring-2 focus:ring-inset focus:ring-red-500 sm:text-sm sm:leading-6"
/>
<FieldError
name="password"
className="text-sm text-red-600"
/>
</div>
</div>
<div>
<Submit className="flex w-full justify-center rounded-md bg-gray-900 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm transition duration-150 ease-in-out hover:bg-gray-800 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-700">
Log in
</Submit>
</div>
</Form>
</div>
</div>
</div>
</>
)
}
export default LogInPage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment