Login con idiomas
This commit is contained in:
parent
7293385550
commit
af12f841b1
@ -50,6 +50,7 @@
|
||||
"cmdk": "^1.0.0",
|
||||
"date-fns": "^3.6.0",
|
||||
"embla-carousel-react": "^8.2.0",
|
||||
"flag-icons": "^7.2.3",
|
||||
"i18next": "^23.12.2",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"joi": "^17.13.1",
|
||||
|
||||
200
client/src/app/auth/LoginPageWithLanguageSelector.tsx
Normal file
200
client/src/app/auth/LoginPageWithLanguageSelector.tsx
Normal file
@ -0,0 +1,200 @@
|
||||
import { Container, FormTextField } from "@/components";
|
||||
import { FormSubmitButton } from "@/components/Forms/FormSubmitButton";
|
||||
import { UeckoLogo } from "@/components/UeckoLogo/UeckoLogo";
|
||||
import { useLogin } from "@/lib/hooks";
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription,
|
||||
AlertTitle,
|
||||
Button,
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
Form,
|
||||
} from "@/ui";
|
||||
import { joiResolver } from "@hookform/resolvers/joi";
|
||||
import { ILogin_DTO } from "@shared/contexts";
|
||||
import Joi from "joi";
|
||||
|
||||
import { AlertCircleIcon, ChevronDownIcon } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { SubmitHandler, useForm } from "react-hook-form";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import SpanishJoiMessages from "../../spanish-joi-messages.json";
|
||||
import "/node_modules/flag-icons/css/flag-icons.min.css";
|
||||
|
||||
type LoginDataForm = ILogin_DTO;
|
||||
|
||||
const languages = [
|
||||
{ code: "en", name: "English", flag: () => <span className='fi fi-gb'></span> },
|
||||
{ code: "es", name: "Español", flag: () => <span className='fi fi-es'></span> },
|
||||
{ code: "fr", name: "Français", flag: () => <span className='fi fi-fr'></span> },
|
||||
{ code: "it", name: "Italiano", flag: () => <span className='fi fi-it'></span> },
|
||||
];
|
||||
|
||||
export const LoginPageWithLanguageSelector = () => {
|
||||
const { t, i18n } = useTranslation();
|
||||
const [language, setLanguage] = useState(i18n.language);
|
||||
|
||||
useEffect(() => {
|
||||
const browserLang = navigator.language.split("-")[0];
|
||||
const supportedLang = languages.find((lang) => lang.code === browserLang);
|
||||
if (supportedLang) {
|
||||
changeLanguage(supportedLang.code);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const changeLanguage = (lng: string) => {
|
||||
i18n.changeLanguage(lng);
|
||||
setLanguage(lng);
|
||||
};
|
||||
|
||||
const { mutate: login } = useLogin({
|
||||
onSuccess: (data) => {
|
||||
const { success, error } = data;
|
||||
if (!success && error) {
|
||||
form.setError("root", error);
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
console.debug(error);
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm<LoginDataForm>({
|
||||
mode: "onBlur",
|
||||
defaultValues: {
|
||||
email: "",
|
||||
password: "",
|
||||
},
|
||||
resolver: joiResolver(
|
||||
Joi.object({
|
||||
email: Joi.string()
|
||||
.email({ tlds: { allow: false } })
|
||||
.required(),
|
||||
password: Joi.string().min(4).alphanum().required(),
|
||||
}),
|
||||
{
|
||||
messages: SpanishJoiMessages,
|
||||
}
|
||||
),
|
||||
});
|
||||
|
||||
const onSubmit: SubmitHandler<LoginDataForm> = async (data) => {
|
||||
login({ email: data.email, password: data.password }, {});
|
||||
};
|
||||
|
||||
return (
|
||||
<Container
|
||||
variant={"full"}
|
||||
className='p-0 lg:grid lg:min-h-[600px] lg:grid-cols-2 xl:min-h-[800px] h-screen '
|
||||
>
|
||||
<div className='flex items-center justify-center py-12 '>
|
||||
<div className='mx-auto grid w-[650px] gap-6 relative '>
|
||||
<div className='absolute flex space-x-2 top-4 right-4 '>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant='outline' className='w-[140px] justify-start'>
|
||||
<span className='mr-2'>
|
||||
{languages.find((lang) => lang.code === language)?.flag()}
|
||||
</span>
|
||||
{languages.find((lang) => lang.code === language)?.name}
|
||||
<ChevronDownIcon className='w-4 h-4 ml-auto opacity-50' />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className='w-[140px]'>
|
||||
{languages.map((lang) => (
|
||||
<DropdownMenuItem key={lang.code} onSelect={() => changeLanguage(lang.code)}>
|
||||
<span className='mr-2'>{lang.flag()}</span>
|
||||
{lang.name}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
<Card className='px-12 py-6 bg-muted/50'>
|
||||
<CardHeader>
|
||||
<UeckoLogo className='inline-block m-auto mb-6 align-middle max-w-32' />
|
||||
<CardTitle>
|
||||
<Trans i18nKey='login_page.title' />
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
<Trans i18nKey='login_page.description' />
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||
<div className='grid items-start gap-6'>
|
||||
<div className='grid gap-6'>
|
||||
<FormTextField
|
||||
required
|
||||
name='email'
|
||||
label={t("login_page.email_label")}
|
||||
type='email'
|
||||
placeholder={t("login_page.email_placeholder")}
|
||||
/>
|
||||
</div>
|
||||
<div className='grid gap-6'>
|
||||
<FormTextField
|
||||
required
|
||||
name='password'
|
||||
label={t("login_page.password_label")}
|
||||
type='password'
|
||||
/>
|
||||
<div className='mb-4 -mt-2 text-sm'>
|
||||
<Trans i18nKey='login_page.forgotten_password' />
|
||||
<br />
|
||||
<Link to='https://uecko.com/distribuidores' className='underline'>
|
||||
<Trans i18nKey='login_page.contact_us' />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{form.formState.errors.root?.message && (
|
||||
<Alert variant='destructive'>
|
||||
<AlertCircleIcon className='w-4 h-4' />
|
||||
<AlertTitle>
|
||||
<Trans i18nKey='common.error' />
|
||||
</AlertTitle>
|
||||
<AlertDescription>{form.formState.errors.root?.message}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<FormSubmitButton className='w-full' label={t("login_page.login")} />
|
||||
|
||||
<div className='mt-4 text-sm text-center'>
|
||||
<Trans i18nKey='login_page.become_dealer' />
|
||||
<br />
|
||||
<Link to='https://uecko.com/distribuidores' className='underline'>
|
||||
<Trans i18nKey='login_page.contact_us' />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<img className='block w-11/12 mx-auto aspect-auto' src='/img/uecko-footer_logos.jpg' />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='hidden bg-muted lg:block'>
|
||||
<img
|
||||
src='/img/nara2.jpg'
|
||||
alt='Image'
|
||||
width='1920'
|
||||
height='1080'
|
||||
className='h-full w-full object-cover dark:brightness-[0.2] dark:grayscale'
|
||||
/>
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
@ -3308,6 +3308,11 @@ find-up@^5.0.0:
|
||||
locate-path "^6.0.0"
|
||||
path-exists "^4.0.0"
|
||||
|
||||
flag-icons@^7.2.3:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/flag-icons/-/flag-icons-7.2.3.tgz#b67f379fa0ef28c4e605319a78035131bdd8ced7"
|
||||
integrity sha512-X2gUdteNuqdNqob2KKTJTS+ZCvyWeLCtDz9Ty8uJP17Y4o82Y+U/Vd4JNrdwTAjagYsRznOn9DZ+E/Q52qbmqg==
|
||||
|
||||
flat-cache@^3.0.4:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user