141 lines
4.2 KiB
TypeScript
141 lines
4.2 KiB
TypeScript
'use client';
|
|
|
|
import { Link, useRouter } from '@/shared/config/i18n/navigation';
|
|
import { setToken, setUser } from '@/shared/lib/token';
|
|
import { Button } from '@/shared/ui/button';
|
|
import {
|
|
Form,
|
|
FormControl,
|
|
FormField,
|
|
FormItem,
|
|
FormMessage,
|
|
} from '@/shared/ui/form';
|
|
import { Input } from '@/shared/ui/input';
|
|
import { Label } from '@/shared/ui/label';
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import { Loader2, User } from 'lucide-react';
|
|
import { useTranslations } from 'next-intl';
|
|
import { useForm } from 'react-hook-form';
|
|
import { toast } from 'sonner';
|
|
import z from 'zod';
|
|
import { auth_api } from '../lib/api';
|
|
import { authForm } from '../lib/form';
|
|
|
|
const Login = () => {
|
|
const router = useRouter();
|
|
const t = useTranslations();
|
|
const form = useForm<z.infer<typeof authForm>>({
|
|
resolver: zodResolver(authForm),
|
|
defaultValues: {
|
|
password: '',
|
|
username: '',
|
|
},
|
|
});
|
|
const queryClient = useQueryClient();
|
|
|
|
const { mutate, isPending } = useMutation({
|
|
mutationFn: (body: {
|
|
username: string;
|
|
password: string;
|
|
tg_id?: string;
|
|
}) => auth_api.login(body),
|
|
onSuccess: (res) => {
|
|
setToken(res.data.access);
|
|
setUser(form.getValues('username'));
|
|
router.push('/');
|
|
queryClient.refetchQueries({ queryKey: ['product_list'] });
|
|
},
|
|
onError: () => {
|
|
toast.error(t('Username yoki parol xato kiritildi'), {
|
|
richColors: true,
|
|
position: 'top-center',
|
|
});
|
|
},
|
|
});
|
|
|
|
function onSubmit(values: z.infer<typeof authForm>) {
|
|
mutate({
|
|
password: values.password,
|
|
username: values.username,
|
|
});
|
|
}
|
|
|
|
return (
|
|
<div className="custom-container flex justify-center items-center h-[85vh]">
|
|
<div className="bg-white rounded-2xl shadow-2xl w-full max-w-md overflow-hidden">
|
|
{/* Header */}
|
|
<div className="bg-gradient-to-r from-blue-600 to-indigo-600 p-8 text-white text-center">
|
|
<div className="w-20 h-20 bg-white bg-opacity-20 rounded-full flex items-center justify-center mx-auto mb-4">
|
|
<User className="w-10 h-10 text-blue-500" />
|
|
</div>
|
|
<p className="text-blue-100 text-2xl font-semibold">
|
|
{t('Tizimga kirish')}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Form */}
|
|
<Form {...form}>
|
|
<form
|
|
className="p-8 space-y-4"
|
|
onSubmit={form.handleSubmit(onSubmit)}
|
|
>
|
|
<FormField
|
|
control={form.control}
|
|
name="username"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<Label>{t('Username')}</Label>
|
|
<FormControl>
|
|
<Input
|
|
placeholder={t('Username')}
|
|
className="h-12"
|
|
{...field}
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
|
|
<FormField
|
|
control={form.control}
|
|
name="password"
|
|
render={({ field }) => (
|
|
<FormItem>
|
|
<Label>{t('Parol')}</Label>
|
|
<FormControl>
|
|
<Input
|
|
placeholder={t('Parol')}
|
|
className="h-12"
|
|
{...field}
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
<p className="text-muted-foreground font-semibold mt-5 text-sm">
|
|
{t(
|
|
"Agarda sizda kirish uchun login va parol yo'q bolsa iltimos bizga murojat qiling",
|
|
)}{' '}
|
|
<Link href={'/about/#contact'} className="text-blue-500">
|
|
{t('Murojat qilish')}
|
|
</Link>
|
|
</p>
|
|
<Button
|
|
disabled={isPending}
|
|
type="submit"
|
|
className="w-full h-12 text-md"
|
|
>
|
|
{isPending ? <Loader2 className="animate-spin" /> : t('Kirish')}
|
|
</Button>
|
|
</form>
|
|
</Form>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Login;
|