finished reset password & other changes
This commit is contained in:
@@ -3,6 +3,8 @@ import { Card, CardContent, CardFooter, CardHeader } from '@/components/ui/card'
|
||||
import { Header } from '@/components/auth/header'
|
||||
import { Social } from '@/components/auth/social'
|
||||
import { BackButton } from '@/components/auth/back-button'
|
||||
import { Suspense } from 'react'
|
||||
import { Loading } from '@/components/loading'
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode
|
||||
@@ -24,32 +26,31 @@ export const CardWrapper = ({
|
||||
continueWithLabel,
|
||||
}: Props) => {
|
||||
return (
|
||||
<Card
|
||||
className={`max-w-[430px] w-[100%] shadow-md md:min-w-[430px] sm:w-full`}>
|
||||
<CardHeader>
|
||||
<Header label={headerLabel} title={headerTitle}/>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{children}
|
||||
</CardContent>
|
||||
{showSocial && <CardFooter className="flex-wrap">
|
||||
<div className="relative flex-none w-[100%] mb-4"
|
||||
style={{ display: 'block' }}>
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<span className="w-full border-t"></span>
|
||||
</div>
|
||||
<div className="relative flex justify-center text-xs uppercase">
|
||||
<Suspense fallback={<Loading/>}>
|
||||
<Card
|
||||
className="border-8 border-muted shadow-2xl max-w-[430px] w-full sm:min-w-[430px]">
|
||||
<CardHeader>
|
||||
<Header label={headerLabel} title={headerTitle}/>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{children}
|
||||
</CardContent>
|
||||
{showSocial && <CardFooter className="flex-wrap">
|
||||
<div className="relative flex-none w-[100%] mb-4" style={{ background: 'block' }}>
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<span className="w-full border-t"></span>
|
||||
</div>
|
||||
<div className="relative flex justify-center text-xs uppercase">
|
||||
<span
|
||||
className="bg-background px-2 text-muted-foreground">{continueWithLabel}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/*<Separator className="my-4"/>*/}
|
||||
<Social/>
|
||||
</CardFooter>}
|
||||
<CardFooter>
|
||||
<BackButton label={backButtonLabel} href={backButtonHref}/>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<Social/>
|
||||
</CardFooter>}
|
||||
<CardFooter>
|
||||
<BackButton label={backButtonLabel} href={backButtonHref}/>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
@@ -14,9 +14,9 @@ const ErrorCard = () => {
|
||||
backButtonLabel={t('auth.form.error.back_button_label')}
|
||||
backButtonHref={AUTH_LOGIN_URL}
|
||||
>
|
||||
<div className="w-full flex items-center justify-center">
|
||||
<TriangleAlert className="w-4 h-4 text-destructive"/>
|
||||
<p>ssss</p>
|
||||
<div className="w-full flex items-center justify-center text-destructive">
|
||||
<TriangleAlert className="w-4 h-4 mr-1.5"/>
|
||||
<p>Hush little baby... this is prohibited zone!</p>
|
||||
</div>
|
||||
</CardWrapper>
|
||||
)
|
||||
|
||||
@@ -21,7 +21,8 @@ import FormError from '@/components/form-error'
|
||||
import FormSuccess from '@/components/form-success'
|
||||
import { login } from '@/actions/login'
|
||||
import { LoginSchema } from '@/schemas'
|
||||
import { AUTH_REGISTER_URL } from '@/config/routes'
|
||||
import { AUTH_REGISTER_URL, AUTH_RESET_PASSWORD_URL } from '@/config/routes'
|
||||
import Link from 'next/link'
|
||||
|
||||
export const LoginForm = () => {
|
||||
const t = useI18n()
|
||||
@@ -61,12 +62,12 @@ export const LoginForm = () => {
|
||||
backButtonLabel={t('auth.form.login.back_button_label')}
|
||||
backButtonHref={AUTH_REGISTER_URL}
|
||||
showSocial
|
||||
continueWithLabel={t('form.label.continue_with')}
|
||||
continueWithLabel={t('auth.form.label.continue_with')}
|
||||
>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="space-y-6"
|
||||
className="space-y-0"
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<FormField control={form.control} name="email"
|
||||
@@ -78,7 +79,7 @@ export const LoginForm = () => {
|
||||
disabled={isPending}
|
||||
placeholder={t('form.placeholder.email')}
|
||||
type="email"
|
||||
autoComplete="username"
|
||||
autoComplete="email"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage className="text-xs"/>
|
||||
@@ -96,9 +97,14 @@ export const LoginForm = () => {
|
||||
autoComplete="current-password"
|
||||
/>
|
||||
</FormControl>
|
||||
<Button variant="link" size="sm" asChild
|
||||
className="mt-0 p-0 items-start font-light text-sky-900">
|
||||
<Link href={AUTH_RESET_PASSWORD_URL}>{t('auth.form.login.reset_password_link_text')}</Link>
|
||||
</Button>
|
||||
<FormMessage className="text-xs"/>
|
||||
</FormItem>)}/>
|
||||
</div>
|
||||
|
||||
<FormSuccess message={success}/>
|
||||
<FormError message={error || urlError}/>
|
||||
<Button type="submit" className="w-full" disabled={isPending}>
|
||||
@@ -107,6 +113,4 @@ export const LoginForm = () => {
|
||||
</form>
|
||||
</Form>
|
||||
</CardWrapper>)
|
||||
}
|
||||
|
||||
//1:30:00
|
||||
}
|
||||
88
components/auth/new-password-form.tsx
Normal file
88
components/auth/new-password-form.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
'use client'
|
||||
|
||||
import { infer as zInfer } from 'zod'
|
||||
import { useState, useTransition } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { CardWrapper } from '@/components/auth/card-wrapper'
|
||||
import { useI18n } from '@/locales/client'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import FormError from '@/components/form-error'
|
||||
import FormSuccess from '@/components/form-success'
|
||||
import { NewPasswordSchema } from '@/schemas'
|
||||
import { AUTH_LOGIN_URL } from '@/config/routes'
|
||||
import { newPassword } from '@/actions/new-password'
|
||||
|
||||
export const NewPasswordForm = ({ token }: { token: string }) => {
|
||||
const t = useI18n()
|
||||
|
||||
const [error, setError] = useState<string | undefined>('')
|
||||
const [success, setSuccess] = useState<string | undefined>('')
|
||||
const [isPending, startTransition] = useTransition()
|
||||
|
||||
const form = useForm<zInfer<typeof NewPasswordSchema>>({
|
||||
resolver: zodResolver(NewPasswordSchema), defaultValues: {
|
||||
password: '',
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = (values: zInfer<typeof NewPasswordSchema>) => {
|
||||
setError('')
|
||||
setSuccess('')
|
||||
|
||||
startTransition(() => {
|
||||
newPassword(values, token).then((data) => {
|
||||
// @ts-ignore
|
||||
setError(t(data?.error))
|
||||
// @ts-ignore
|
||||
setSuccess(t(data?.success))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return (<CardWrapper
|
||||
headerTitle={t('auth.title')}
|
||||
headerLabel={t('auth.form.new_password.header_label')}
|
||||
backButtonLabel={t('auth.form.new_password.back_button_label')}
|
||||
backButtonHref={AUTH_LOGIN_URL}
|
||||
>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="space-y-4"
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<FormField control={form.control} name="password"
|
||||
render={({ field }) => (<FormItem>
|
||||
<FormLabel>{t('form.label.password')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
disabled={isPending}
|
||||
type="password"
|
||||
placeholder="******"
|
||||
autoComplete="new-password"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage className="text-xs"/>
|
||||
</FormItem>)}/>
|
||||
</div>
|
||||
|
||||
<FormSuccess message={success}/>
|
||||
<FormError message={error}/>
|
||||
<Button type="submit" className="w-full" disabled={isPending}>
|
||||
{t('auth.form.new_password.button')}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
</CardWrapper>)
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import { RegisterSchema } from '@/schemas'
|
||||
import { AUTH_LOGIN_URL } from '@/config/routes'
|
||||
|
||||
export const RegisterForm = () => {
|
||||
// TODO: create repeat password field
|
||||
// const [currentPassword, setCurrentPassword] = useState('')
|
||||
// const [password, setPassword] = useState('')
|
||||
// const [passwordConfirmation, setPasswordConfirmation] = useState('')
|
||||
@@ -59,7 +60,7 @@ export const RegisterForm = () => {
|
||||
backButtonLabel={t('auth.form.register.back_button_label')}
|
||||
backButtonHref={AUTH_LOGIN_URL}
|
||||
showSocial
|
||||
continueWithLabel={t('form.label.continue_with')}
|
||||
continueWithLabel={t('auth.form.label.continue_with')}
|
||||
>
|
||||
<Form {...form}>
|
||||
<form
|
||||
@@ -91,7 +92,7 @@ export const RegisterForm = () => {
|
||||
disabled={isPending}
|
||||
placeholder={t('form.placeholder.email')}
|
||||
type="email"
|
||||
autoComplete="username"
|
||||
autoComplete="email"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage className="text-xs"/>
|
||||
@@ -115,7 +116,7 @@ export const RegisterForm = () => {
|
||||
<FormSuccess message={success}/>
|
||||
<FormError message={error}/>
|
||||
<Button type="submit" className="w-full" disabled={isPending}>
|
||||
{t('form.label.register')}
|
||||
{t('auth.form.register.button')}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
|
||||
88
components/auth/reset-form.tsx
Normal file
88
components/auth/reset-form.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
'use client'
|
||||
|
||||
import { infer as zInfer } from 'zod'
|
||||
import { useState, useTransition } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { CardWrapper } from '@/components/auth/card-wrapper'
|
||||
import { useI18n } from '@/locales/client'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import FormError from '@/components/form-error'
|
||||
import FormSuccess from '@/components/form-success'
|
||||
import { ResetSchema } from '@/schemas'
|
||||
import { AUTH_LOGIN_URL } from '@/config/routes'
|
||||
import { reset } from '@/actions/reset'
|
||||
|
||||
export const ResetForm = () => {
|
||||
const t = useI18n()
|
||||
|
||||
const [error, setError] = useState<string | undefined>('')
|
||||
const [success, setSuccess] = useState<string | undefined>('')
|
||||
const [isPending, startTransition] = useTransition()
|
||||
|
||||
const form = useForm<zInfer<typeof ResetSchema>>({
|
||||
resolver: zodResolver(ResetSchema), defaultValues: {
|
||||
email: '',
|
||||
},
|
||||
})
|
||||
|
||||
const onSubmit = (values: zInfer<typeof ResetSchema>) => {
|
||||
setError('')
|
||||
setSuccess('')
|
||||
|
||||
startTransition(() => {
|
||||
reset(values).then((data) => {
|
||||
// @ts-ignore
|
||||
setError(t(data?.error))
|
||||
// @ts-ignore
|
||||
setSuccess(t(data?.success))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return (<CardWrapper
|
||||
headerTitle={t('auth.title')}
|
||||
headerLabel={t('auth.form.reset.header_label')}
|
||||
backButtonLabel={t('auth.form.reset.back_button_label')}
|
||||
backButtonHref={AUTH_LOGIN_URL}
|
||||
>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="space-y-4"
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<FormField control={form.control} name="email"
|
||||
render={({ field }) => (<FormItem>
|
||||
<FormLabel>{t('form.label.email')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
disabled={isPending}
|
||||
placeholder={t('form.placeholder.email')}
|
||||
type="email"
|
||||
autoComplete="email"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage className="text-xs"/>
|
||||
</FormItem>)}/>
|
||||
</div>
|
||||
|
||||
<FormSuccess message={success}/>
|
||||
<FormError message={error}/>
|
||||
<Button type="submit" className="w-full" disabled={isPending}>
|
||||
{t('auth.form.reset.button')}
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
</CardWrapper>)
|
||||
}
|
||||
@@ -11,12 +11,12 @@ export const Social = () => {
|
||||
|
||||
return (
|
||||
<div className="flex items-center w-full gap-x-2">
|
||||
<Button size="lg" className="w-full" variant="outline"
|
||||
onClick={() => SignInProvider('google')}>
|
||||
<Button size="lg" className="w-full" variant="outline" role="button"
|
||||
onClick={() => SignInProvider('google')} aria-label="Sign in with Google">
|
||||
<FcGoogle className="w-5 h-5"/>
|
||||
</Button>
|
||||
<Button size="lg" className="w-full" variant="outline"
|
||||
onClick={() => SignInProvider('github')}>
|
||||
<Button size="lg" className="w-full" variant="outline" role="button"
|
||||
onClick={() => SignInProvider('github')} aria-label="Sign in with Github">
|
||||
<FaGithub className="w-5 h-5"/>
|
||||
</Button>
|
||||
{/*<Button size="lg" className="w-full" variant="outline" onClick={() => {}}>
|
||||
|
||||
Reference in New Issue
Block a user