171 lines
6.1 KiB
TypeScript
171 lines
6.1 KiB
TypeScript
import { authClient } from '@/lib/auth-client';
|
|
import { m } from '@/paraglide/messages';
|
|
import { useForm } from '@tanstack/react-form';
|
|
import { useQueryClient } from '@tanstack/react-query';
|
|
import { createLink, useNavigate } from '@tanstack/react-router';
|
|
import i18next from 'i18next';
|
|
import { toast } from 'sonner';
|
|
import z from 'zod';
|
|
import { Button } from '../ui/button';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
|
|
import { Field, FieldError, FieldGroup, FieldLabel } from '../ui/field';
|
|
import { Input } from '../ui/input';
|
|
|
|
const SignInFormSchema = z.object({
|
|
email: z
|
|
.string()
|
|
.nonempty(m.common_is_required({ field: m.login_page_form_email }))
|
|
.email(m.login_page_messages_email_invalid()),
|
|
password: z.string().nonempty(
|
|
m.common_is_required({
|
|
field: m.login_page_form_password(),
|
|
}),
|
|
),
|
|
});
|
|
|
|
const ButtonLink = createLink(Button);
|
|
|
|
const SignInForm = () => {
|
|
const navigate = useNavigate();
|
|
const queryClient = useQueryClient();
|
|
const form = useForm({
|
|
defaultValues: {
|
|
email: '',
|
|
password: '',
|
|
},
|
|
validators: {
|
|
onSubmit: SignInFormSchema,
|
|
onChange: SignInFormSchema,
|
|
},
|
|
onSubmit: async ({ value }) => {
|
|
await authClient.signIn.email(
|
|
{
|
|
email: value.email,
|
|
password: value.password,
|
|
},
|
|
{
|
|
onSuccess: () => {
|
|
navigate({ to: '/' });
|
|
queryClient.invalidateQueries({ queryKey: ['auth', 'session'] });
|
|
toast.success(m.login_page_messages_login_success(), {
|
|
richColors: true,
|
|
});
|
|
},
|
|
onError: (ctx) => {
|
|
toast.error(i18next.t(`backend.${ctx.error.code}` as any), {
|
|
richColors: true,
|
|
});
|
|
},
|
|
},
|
|
);
|
|
},
|
|
});
|
|
|
|
return (
|
|
<div className="flex flex-col gap-6">
|
|
<Card>
|
|
<CardHeader className="text-center">
|
|
<CardTitle className="text-xl">
|
|
{m.login_page_ui_welcome_back()}
|
|
</CardTitle>
|
|
{/* <CardDescription>Login with your Google account</CardDescription> */}
|
|
</CardHeader>
|
|
<CardContent>
|
|
<form
|
|
id="sign-in-form"
|
|
onSubmit={(e) => {
|
|
e.preventDefault();
|
|
form.handleSubmit();
|
|
}}
|
|
>
|
|
<FieldGroup>
|
|
{/* <Field>
|
|
<Button variant="outline" type="button">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
|
<path
|
|
d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z"
|
|
fill="currentColor"
|
|
/>
|
|
</svg>
|
|
Login with Google
|
|
</Button>
|
|
</Field>
|
|
<FieldSeparator>Or continue with</FieldSeparator> */}
|
|
<form.Field
|
|
name="email"
|
|
children={(field) => {
|
|
const isInvalid =
|
|
field.state.meta.isTouched && !field.state.meta.isValid;
|
|
return (
|
|
<Field data-invalid={isInvalid}>
|
|
<FieldLabel htmlFor={field.name}>
|
|
{m.login_page_form_email()}
|
|
</FieldLabel>
|
|
<Input
|
|
id={field.name}
|
|
name={field.name}
|
|
value={field.state.value}
|
|
onBlur={field.handleBlur}
|
|
onChange={(e) => field.handleChange(e.target.value)}
|
|
aria-invalid={isInvalid}
|
|
type="email"
|
|
placeholder="m@example.com"
|
|
autoComplete="off"
|
|
/>
|
|
{isInvalid && (
|
|
<FieldError errors={field.state.meta.errors} />
|
|
)}
|
|
</Field>
|
|
);
|
|
}}
|
|
/>
|
|
<form.Field
|
|
name="password"
|
|
children={(field) => {
|
|
const isInvalid =
|
|
field.state.meta.isTouched && !field.state.meta.isValid;
|
|
return (
|
|
<Field data-invalid={isInvalid}>
|
|
<FieldLabel htmlFor={field.name}>
|
|
{m.login_page_form_password()}
|
|
</FieldLabel>
|
|
<Input
|
|
id={field.name}
|
|
name={field.name}
|
|
value={field.state.value}
|
|
onBlur={field.handleBlur}
|
|
onChange={(e) => field.handleChange(e.target.value)}
|
|
aria-invalid={isInvalid}
|
|
type="password"
|
|
/>
|
|
{isInvalid && (
|
|
<FieldError errors={field.state.meta.errors} />
|
|
)}
|
|
</Field>
|
|
);
|
|
}}
|
|
/>
|
|
<Field>
|
|
<Button type="submit">{m.ui_login_btn()}</Button>
|
|
<ButtonLink to="/" variant="outline">
|
|
{m.ui_cancel_btn()}
|
|
</ButtonLink>
|
|
{/* <FieldDescription className="text-center">
|
|
{t('loginPage.ui.not_have_account')}{' '}
|
|
<Link to="/sign-up">{t('ui.signup_btn')}</Link>
|
|
</FieldDescription> */}
|
|
</Field>
|
|
</FieldGroup>
|
|
</form>
|
|
</CardContent>
|
|
</Card>
|
|
{/* <FieldDescription className="px-6 text-center">
|
|
By clicking continue, you agree to our <a href="#">Terms of Service</a>{' '}
|
|
and <a href="#">Privacy Policy</a>.
|
|
</FieldDescription> */}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SignInForm;
|