Auto commit: 2026-02-09T01:19:47.913Z

This commit is contained in:
Flatlogic Bot 2026-02-09 01:19:47 +00:00
parent 043ebe8507
commit 45f6e99770
8 changed files with 106 additions and 51 deletions

View File

@ -1,4 +1,29 @@
{ {
"menu": {
"Dashboard": "Tablero",
"Users": "Usuarios",
"Roles": "Roles",
"Permissions": "Permisos",
"Medical centers": "Centros médicos",
"Services": "Servicios",
"Patients": "Pacientes",
"Appointments": "Turnos",
"Payments": "Pagos",
"Settlements": "Liquidaciones",
"Expenses": "Gastos",
"Extra incomes": "Ingresos extras",
"Messages": "Mensajes",
"Pdf templates": "Plantillas PDF",
"Pdf documents": "Documentos PDF",
"Event logs": "Registros de eventos",
"App settings": "Configuración",
"Profile": "Perfil",
"Swagger API": "API Swagger",
"My Profile": "Mi Perfil",
"Log Out": "Cerrar sesión",
"Log out": "Cerrar sesión",
"Light/Dark": "Claro/Oscuro"
},
"pages": { "pages": {
"dashboard": { "dashboard": {
"pageTitle": "Tablero", "pageTitle": "Tablero",
@ -9,8 +34,8 @@
"login": { "login": {
"pageTitle": "Inicio de sesión", "pageTitle": "Inicio de sesión",
"sampleCredentialsAdmin": "Use {{email}} / {{password}} para iniciar sesión como Administrador", "sampleCredentialsAdmin": "Use / para iniciar sesión como Administrador",
"sampleCredentialsUser": "Use {{email}} / {{password}} para iniciar sesión como Usuario", "sampleCredentialsUser": "Use / para iniciar sesión como Usuario",
"form": { "form": {
"loginLabel": "Usuario", "loginLabel": "Usuario",
@ -20,6 +45,7 @@
"remember": "Recuérdame", "remember": "Recuérdame",
"forgotPassword": "¿Olvidó su contraseña?", "forgotPassword": "¿Olvidó su contraseña?",
"loginButton": "Acceder", "loginButton": "Acceder",
"loginWithGoogle": "Ingresar con Google",
"loading": "Cargando...", "loading": "Cargando...",
"noAccountYet": "¿Aún no tiene una cuenta?", "noAccountYet": "¿Aún no tiene una cuenta?",
"newAccount": "Crear cuenta" "newAccount": "Crear cuenta"
@ -40,7 +66,7 @@
"components": { "components": {
"widgetCreator": { "widgetCreator": {
"title": "Crear gráfico o widget", "title": "Crear gráfico o widget",
"helpText": "Describe tu nuevo widget o gráfico en lenguaje natural. Por ejemplo: \"Número de usuarios administradores\" O \"gráfico rojo con el número de contratos cerrados agrupados por mes\"", "helpText": "Describe tu nuevo widget o gráfico en lenguaje natural. Por ejemplo: \"Número de usuarios administradores\" O \"gráfico rojo con el número de contratos cerrados agrupados por mes"",
"settingsTitle": "Configuración del creador de widgets", "settingsTitle": "Configuración del creador de widgets",
"settingsDescription": "¿Para qué rol estamos mostrando y creando widgets?", "settingsDescription": "¿Para qué rol estamos mostrando y creando widgets?",
"doneButton": "Listo", "doneButton": "Listo",
@ -52,4 +78,4 @@
"minLength": "Longitud mínima: {{count}} caracteres" "minLength": "Longitud mínima: {{count}} caracteres"
} }
} }
} }

View File

@ -7,6 +7,7 @@ import AsideMenuList from './AsideMenuList'
import { MenuAsideItem } from '../interfaces' import { MenuAsideItem } from '../interfaces'
import { useAppSelector } from '../stores/hooks' import { useAppSelector } from '../stores/hooks'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useTranslation } from 'react-i18next'
type Props = { type Props = {
item: MenuAsideItem item: MenuAsideItem
@ -14,6 +15,7 @@ type Props = {
} }
const AsideMenuItem = ({ item, isDropdownList = false }: Props) => { const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
const { t } = useTranslation('common')
const [isLinkActive, setIsLinkActive] = useState(false) const [isLinkActive, setIsLinkActive] = useState(false)
const [isDropdownActive, setIsDropdownActive] = useState(false) const [isDropdownActive, setIsDropdownActive] = useState(false)
@ -50,7 +52,7 @@ const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
item.menu ? '' : 'pr-12' item.menu ? '' : 'pr-12'
} ${activeClassAddon}`} } ${activeClassAddon}`}
> >
{item.label} {t(`menu.${item.label}`, item.label)}
</span> </span>
{item.menu && ( {item.menu && (
<BaseIcon <BaseIcon
@ -99,4 +101,4 @@ const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
) )
} }
export default AsideMenuItem export default AsideMenuItem

View File

@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import Select, { components, SingleValueProps, OptionProps } from 'react-select'; import Select, { components, SingleValueProps, OptionProps } from 'react-select';
import { useTranslation } from 'react-i18next';
type LanguageOption = { label: string; value: string }; type LanguageOption = { label: string; value: string };
@ -23,28 +24,37 @@ const SingleVal = (props: SingleValueProps<LanguageOption, false>) => (
); );
const LanguageSwitcher: React.FC = () => { const LanguageSwitcher: React.FC = () => {
const { i18n } = useTranslation();
const [mounted, setMounted] = useState(false); const [mounted, setMounted] = useState(false);
const [selected, setSelected] = useState<LanguageOption>(LANGS[0]); const [selected, setSelected] = useState<LanguageOption>(LANGS.find(l => l.value === i18n.language) || LANGS[0]);
useEffect(() => { useEffect(() => {
setMounted(true); setMounted(true);
}, []); }, []);
useEffect(() => {
const currentLang = LANGS.find(l => l.value === i18n.language);
if (currentLang) {
setSelected(currentLang);
}
}, [i18n.language]);
const handleChange = (opt: LanguageOption | null) => { const handleChange = (opt: LanguageOption | null) => {
if (!opt) return; if (!opt) return;
setSelected(opt); setSelected(opt);
i18n.changeLanguage(opt.value);
}; };
if (!mounted) return null; if (!mounted) return null;
return ( return (
<div style={{ width: 88 }}> <div style={{ width: 88 }} className="mx-3">
<Select <Select
value={selected} value={selected}
options={LANGS} options={LANGS}
onChange={handleChange} onChange={handleChange}
isSearchable={false} isSearchable={false}
menuPlacement='top' menuPlacement='bottom'
components={{ components={{
Option, Option,
SingleValue: SingleVal, SingleValue: SingleVal,
@ -59,6 +69,7 @@ const LanguageSwitcher: React.FC = () => {
paddingBottom: 0, paddingBottom: 0,
borderColor: '#d1d5db', borderColor: '#d1d5db',
cursor: 'pointer', cursor: 'pointer',
backgroundColor: 'transparent',
}), }),
valueContainer: (base) => ({ valueContainer: (base) => ({
...base, ...base,
@ -93,4 +104,4 @@ const LanguageSwitcher: React.FC = () => {
); );
}; };
export default LanguageSwitcher; export default LanguageSwitcher;

View File

@ -11,12 +11,14 @@ import { setDarkMode } from '../stores/styleSlice'
import { logoutUser } from '../stores/authSlice' import { logoutUser } from '../stores/authSlice'
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import ClickOutside from "./ClickOutside"; import ClickOutside from "./ClickOutside";
import { useTranslation } from 'react-i18next'
type Props = { type Props = {
item: MenuNavBarItem item: MenuNavBarItem
} }
export default function NavBarItem({ item }: Props) { export default function NavBarItem({ item }: Props) {
const { t } = useTranslation('common')
const router = useRouter(); const router = useRouter();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const excludedRef = useRef(null); const excludedRef = useRef(null);
@ -46,7 +48,7 @@ export default function NavBarItem({ item }: Props) {
item.isDesktopNoLabel ? 'lg:w-16 lg:justify-center' : '', item.isDesktopNoLabel ? 'lg:w-16 lg:justify-center' : '',
].join(' ') ].join(' ')
const itemLabel = item.isCurrentUser ? userName : item.label const itemLabel = item.isCurrentUser ? userName : t(`menu.${item.label}`, item.label)
const handleMenuClick = () => { const handleMenuClick = () => {
if (item.menu) { if (item.menu) {
@ -77,7 +79,7 @@ export default function NavBarItem({ item }: Props) {
const NavBarItemComponentContents = ( const NavBarItemComponentContents = (
<> <>
<div <div
id={getItemId(itemLabel)} id={getItemId(item.label)}
className={`flex items-center ${ className={`flex items-center ${
item.menu item.menu
? 'bg-gray-100 dark:bg-dark-800 lg:bg-transparent lg:dark:bg-transparent p-3 lg:p-0' ? 'bg-gray-100 dark:bg-dark-800 lg:bg-transparent lg:dark:bg-transparent p-3 lg:p-0'
@ -128,4 +130,4 @@ export default function NavBarItem({ item }: Props) {
} }
return <div className={componentClass} ref={excludedRef}>{NavBarItemComponentContents}</div> return <div className={componentClass} ref={excludedRef}>{NavBarItemComponentContents}</div>
} }

View File

@ -8,7 +8,8 @@ i18n
.use(LanguageDetector) .use(LanguageDetector)
.use(initReactI18next) .use(initReactI18next)
.init({ .init({
fallbackLng: 'en', fallbackLng: 'es',
lng: 'es',
detection: { detection: {
order: ['localStorage', 'navigator'], order: ['localStorage', 'navigator'],
lookupLocalStorage: 'app_lang_', lookupLocalStorage: 'app_lang_',
@ -18,4 +19,4 @@ i18n
loadPath: '/locales/{{lng}}/{{ns}}.json', loadPath: '/locales/{{lng}}/{{ns}}.json',
}, },
interpolation: { escapeValue: false }, interpolation: { escapeValue: false },
}); });

View File

@ -15,6 +15,7 @@ import {findMe, logoutUser} from "../stores/authSlice";
import {hasPermission} from "../helpers/userPermissions"; import {hasPermission} from "../helpers/userPermissions";
import RestrictedAccess from '../components/RestrictedAccess' import RestrictedAccess from '../components/RestrictedAccess'
import LanguageSwitcher from '../components/LanguageSwitcher'
type Props = { type Props = {
@ -116,6 +117,9 @@ export default function LayoutAuthenticated({
<NavBarItemPlain useMargin> <NavBarItemPlain useMargin>
<Search /> <Search />
</NavBarItemPlain> </NavBarItemPlain>
<div className="flex items-center ml-2">
<LanguageSwitcher />
</div>
</> </>
)} )}
</NavBar> </NavBar>
@ -132,4 +136,4 @@ export default function LayoutAuthenticated({
</div> </div>
</div> </div>
) )
} }

View File

@ -12,8 +12,10 @@ import Link from "next/link";
import { hasPermission } from "../helpers/userPermissions"; import { hasPermission } from "../helpers/userPermissions";
import { useAppSelector } from '../stores/hooks'; import { useAppSelector } from '../stores/hooks';
import { useTranslation } from 'react-i18next';
const Dashboard = () => { const Dashboard = () => {
const { t } = useTranslation('common');
const iconsColor = useAppSelector((state) => state.style.iconsColor); const iconsColor = useAppSelector((state) => state.style.iconsColor);
const corners = useAppSelector((state) => state.style.corners); const corners = useAppSelector((state) => state.style.corners);
const cardsStyle = useAppSelector((state) => state.style.cardsStyle); const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
@ -49,13 +51,13 @@ const Dashboard = () => {
<> <>
<Head> <Head>
<title> <title>
{getPageTitle('Overview')} {getPageTitle(t('pages.dashboard.pageTitle'))}
</title> </title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton <SectionTitleLineWithButton
icon={icon.mdiChartTimelineVariant} icon={icon.mdiChartTimelineVariant}
title='ZURICH TM Dashboard' title={`${t('pages.dashboard.dashboardTitle', { defaultValue: 'ZURICH TM Dashboard' })}`}
main> main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
@ -67,7 +69,7 @@ const Dashboard = () => {
<div className="flex justify-between align-center"> <div className="flex justify-between align-center">
<div> <div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400"> <div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Pagos Pendientes/Parciales {t('pages.dashboard.metrics.pendingPayments', { defaultValue: 'Pagos Pendientes/Parciales' })}
</div> </div>
<div className="text-3xl leading-tight font-semibold"> <div className="text-3xl leading-tight font-semibold">
{loading ? '...' : metrics.pendingPaymentsCount} {loading ? '...' : metrics.pendingPaymentsCount}
@ -91,7 +93,7 @@ const Dashboard = () => {
<div className="flex justify-between align-center"> <div className="flex justify-between align-center">
<div> <div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400"> <div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Turnos de Hoy {t('pages.dashboard.metrics.todayAppointments', { defaultValue: 'Turnos de Hoy' })}
</div> </div>
<div className="text-3xl leading-tight font-semibold"> <div className="text-3xl leading-tight font-semibold">
{loading ? '...' : metrics.todayAppointmentsCount} {loading ? '...' : metrics.todayAppointmentsCount}
@ -115,7 +117,7 @@ const Dashboard = () => {
<div className="flex justify-between align-center"> <div className="flex justify-between align-center">
<div> <div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400"> <div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Centros Activos {t('pages.dashboard.metrics.activeCenters', { defaultValue: 'Centros Activos' })}
</div> </div>
<div className="text-3xl leading-tight font-semibold"> <div className="text-3xl leading-tight font-semibold">
{loading ? '...' : metrics.activeCentersCount} {loading ? '...' : metrics.activeCentersCount}
@ -139,7 +141,7 @@ const Dashboard = () => {
<div className="flex justify-between align-center"> <div className="flex justify-between align-center">
<div> <div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400"> <div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Total Pacientes {t('pages.dashboard.metrics.totalPatients', { defaultValue: 'Total Pacientes' })}
</div> </div>
<div className="text-3xl leading-tight font-semibold"> <div className="text-3xl leading-tight font-semibold">
{loading ? '...' : metrics.totalPatientsCount} {loading ? '...' : metrics.totalPatientsCount}
@ -163,7 +165,7 @@ const Dashboard = () => {
<div className="flex justify-between align-center"> <div className="flex justify-between align-center">
<div> <div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400"> <div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Total de Turnos {t('pages.dashboard.metrics.totalAppointments', { defaultValue: 'Total de Turnos' })}
</div> </div>
<div className="text-3xl leading-tight font-semibold"> <div className="text-3xl leading-tight font-semibold">
{loading ? '...' : metrics.totalAppointmentsCount} {loading ? '...' : metrics.totalAppointmentsCount}
@ -186,7 +188,7 @@ const Dashboard = () => {
<SectionTitleLineWithButton <SectionTitleLineWithButton
icon={icon.mdiSettingsHelper} icon={icon.mdiSettingsHelper}
title='Acceso Rápido' title={t('pages.dashboard.quickAccess', { defaultValue: 'Acceso Rápido' })}
main={false}> main={false}>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
@ -196,7 +198,7 @@ const Dashboard = () => {
<Link href="/settlements/settlements-list"> <Link href="/settlements/settlements-list">
<div className={`${corners} ${cardsStyle} p-4 flex items-center space-x-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-dark-800 transition-colors`}> <div className={`${corners} ${cardsStyle} p-4 flex items-center space-x-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-dark-800 transition-colors`}>
<BaseIcon path={icon.mdiFileDocumentMultiple} size="24" className="text-blue-600" /> <BaseIcon path={icon.mdiFileDocumentMultiple} size="24" className="text-blue-600" />
<span className="font-medium">Liquidaciones</span> <span className="font-medium">{t('menu.Settlements', { defaultValue: 'Liquidaciones' })}</span>
</div> </div>
</Link> </Link>
)} )}
@ -204,7 +206,7 @@ const Dashboard = () => {
<Link href="/expenses/expenses-list"> <Link href="/expenses/expenses-list">
<div className={`${corners} ${cardsStyle} p-4 flex items-center space-x-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-dark-800 transition-colors`}> <div className={`${corners} ${cardsStyle} p-4 flex items-center space-x-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-dark-800 transition-colors`}>
<BaseIcon path={icon.mdiReceipt} size="24" className="text-red-600" /> <BaseIcon path={icon.mdiReceipt} size="24" className="text-red-600" />
<span className="font-medium">Gastos</span> <span className="font-medium">{t('menu.Expenses', { defaultValue: 'Gastos' })}</span>
</div> </div>
</Link> </Link>
)} )}
@ -212,7 +214,7 @@ const Dashboard = () => {
<Link href="/event_logs/event_logs-list"> <Link href="/event_logs/event_logs-list">
<div className={`${corners} ${cardsStyle} p-4 flex items-center space-x-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-dark-800 transition-colors`}> <div className={`${corners} ${cardsStyle} p-4 flex items-center space-x-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-dark-800 transition-colors`}>
<BaseIcon path={icon.mdiClipboardTextClock} size="24" className="text-gray-600" /> <BaseIcon path={icon.mdiClipboardTextClock} size="24" className="text-gray-600" />
<span className="font-medium">Registro de Eventos</span> <span className="font-medium">{t('menu.Event logs', { defaultValue: 'Registro de Eventos' })}</span>
</div> </div>
</Link> </Link>
)} )}
@ -220,7 +222,7 @@ const Dashboard = () => {
<Link href="/app_settings/app_settings-list"> <Link href="/app_settings/app_settings-list">
<div className={`${corners} ${cardsStyle} p-4 flex items-center space-x-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-dark-800 transition-colors`}> <div className={`${corners} ${cardsStyle} p-4 flex items-center space-x-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-dark-800 transition-colors`}>
<BaseIcon path={icon.mdiCog} size="24" className="text-indigo-600" /> <BaseIcon path={icon.mdiCog} size="24" className="text-indigo-600" />
<span className="font-medium">Configuración</span> <span className="font-medium">{t('menu.App settings', { defaultValue: 'Configuración' })}</span>
</div> </div>
</Link> </Link>
)} )}
@ -234,4 +236,4 @@ Dashboard.getLayout = function getLayout(page: ReactElement) {
return <LayoutAuthenticated>{page}</LayoutAuthenticated> return <LayoutAuthenticated>{page}</LayoutAuthenticated>
} }
export default Dashboard export default Dashboard

View File

@ -19,8 +19,11 @@ import { useAppDispatch, useAppSelector } from '../stores/hooks';
import Link from 'next/link'; import Link from 'next/link';
import {toast, ToastContainer} from "react-toastify"; import {toast, ToastContainer} from "react-toastify";
import { getPexelsImage, getPexelsVideo } from '../helpers/pexels' import { getPexelsImage, getPexelsVideo } from '../helpers/pexels'
import { useTranslation } from 'react-i18next';
import LanguageSwitcher from '../components/LanguageSwitcher';
export default function Login() { export default function Login() {
const { t } = useTranslation('common');
const router = useRouter(); const router = useRouter();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const textColor = useAppSelector((state) => state.style.linkColor); const textColor = useAppSelector((state) => state.style.linkColor);
@ -111,8 +114,9 @@ export default function Login() {
backgroundRepeat: 'no-repeat', backgroundRepeat: 'no-repeat',
}}> }}>
<div className="flex justify-center w-full bg-blue-300/20"> <div className="flex justify-center w-full bg-blue-300/20">
<a className="text-[8px]" href={image?.photographer_url} target="_blank" rel="noreferrer">Photo <a className="text-[8px]" href={image?.photographer_url} target="_blank" rel="noreferrer">
by {image?.photographer} on Pexels</a> {t('pages.login.pexels.photoCredit', { photographer: image?.photographer })}
</a>
</div> </div>
</div> </div>
) )
@ -128,7 +132,7 @@ export default function Login() {
muted muted
> >
<source src={video.video_files[0]?.link} type='video/mp4'/> <source src={video.video_files[0]?.link} type='video/mp4'/>
Your browser does not support the video tag. {t('pages.login.pexels.videoUnsupported')}
</video> </video>
<div className='flex justify-center w-full bg-blue-300/20 z-10'> <div className='flex justify-center w-full bg-blue-300/20 z-10'>
<a <a
@ -137,7 +141,7 @@ export default function Login() {
target='_blank' target='_blank'
rel='noreferrer' rel='noreferrer'
> >
Video by {video.user.name} on Pexels {t('pages.login.pexels.videoCredit', { name: video.user.name })}
</a> </a>
</div> </div>
</div>) </div>)
@ -156,10 +160,13 @@ export default function Login() {
backgroundRepeat: 'no-repeat', backgroundRepeat: 'no-repeat',
} : {}}> } : {}}>
<Head> <Head>
<title>{getPageTitle('Login')}</title> <title>{getPageTitle(t('pages.login.pageTitle'))}</title>
</Head> </Head>
<SectionFullScreen bg='violet'> <SectionFullScreen bg='violet'>
<div className="absolute top-4 right-4 z-50">
<LanguageSwitcher />
</div>
<div className={`flex ${contentPosition === 'right' ? 'flex-row-reverse' : 'flex-row'} min-h-screen w-full`}> <div className={`flex ${contentPosition === 'right' ? 'flex-row-reverse' : 'flex-row'} min-h-screen w-full`}>
{contentType === 'image' && contentPosition !== 'background' ? imageBlock(illustrationImage) : null} {contentType === 'image' && contentPosition !== 'background' ? imageBlock(illustrationImage) : null}
{contentType === 'video' && contentPosition !== 'background' ? videoBlock(illustrationVideo) : null} {contentType === 'video' && contentPosition !== 'background' ? videoBlock(illustrationVideo) : null}
@ -172,18 +179,18 @@ export default function Login() {
<div className='flex flex-row text-gray-500 justify-between'> <div className='flex flex-row text-gray-500 justify-between'>
<div> <div>
<p className='mb-2'>Use{' '} <p className='mb-2'>{t('pages.login.sampleCredentialsAdmin', { email: '', password: '' }).split('/')[0]}
<code className={`cursor-pointer ${textColor} `} <code className={`cursor-pointer ${textColor} `}
data-password="94e48f87" data-password="94e48f87"
onClick={(e) => setLogin(e.target)}>matiasarcuri11@gmail.com</code>{' / '} onClick={(e) => setLogin(e.target)}>matiasarcuri11@gmail.com</code>{' / '}
<code className={`${textColor}`}>94e48f87</code>{' / '} <code className={`${textColor}`}>94e48f87</code>{' / '}
to login as Admin</p> {t('pages.login.sampleCredentialsAdmin', { email: '', password: '' }).split('/')[1]}</p>
<p>Use <code <p>{t('pages.login.sampleCredentialsUser', { email: '', password: '' }).split('/')[0]}<code
className={`cursor-pointer ${textColor} `} className={`cursor-pointer ${textColor} `}
data-password="d52135bedc81" data-password="d52135bedc81"
onClick={(e) => setLogin(e.target)}>client@hello.com</code>{' / '} onClick={(e) => setLogin(e.target)}>client@hello.com</code>{' / '}
<code className={`${textColor}`}>d52135bedc81</code>{' / '} <code className={`${textColor}`}>d52135bedc81</code>{' / '}
to login as User</p> {t('pages.login.sampleCredentialsUser', { email: '', password: '' }).split('/')[1]}</p>
</div> </div>
<div> <div>
<BaseIcon <BaseIcon
@ -205,15 +212,15 @@ export default function Login() {
> >
<Form> <Form>
<FormField <FormField
label='Login' label={t('pages.login.form.loginLabel')}
help='Please enter your login'> help={t('pages.login.form.loginHelp')}>
<Field name='email' /> <Field name='email' />
</FormField> </FormField>
<div className='relative'> <div className='relative'>
<FormField <FormField
label='Password' label={t('pages.login.form.passwordLabel')}
help='Please enter your password'> help={t('pages.login.form.passwordHelp')}>
<Field name='password' type={showPassword ? 'text' : 'password'} /> <Field name='password' type={showPassword ? 'text' : 'password'} />
</FormField> </FormField>
<div <div
@ -229,12 +236,12 @@ export default function Login() {
</div> </div>
<div className={'flex justify-between'}> <div className={'flex justify-between'}>
<FormCheckRadio type='checkbox' label='Remember'> <FormCheckRadio type='checkbox' label={t('pages.login.form.remember')}>
<Field type='checkbox' name='remember' /> <Field type='checkbox' name='remember' />
</FormCheckRadio> </FormCheckRadio>
<Link className={`${textColor} text-blue-600`} href={'/forgot'}> <Link className={`${textColor} text-blue-600`} href={'/forgot'}>
Forgot password? {t('pages.login.form.forgotPassword')}
</Link> </Link>
</div> </div>
@ -244,7 +251,7 @@ export default function Login() {
<BaseButton <BaseButton
className={'w-full'} className={'w-full'}
type='submit' type='submit'
label={isFetching ? 'Loading...' : 'Login'} label={isFetching ? t('pages.login.form.loading') : t('pages.login.form.loginButton')}
color='info' color='info'
disabled={isFetching} disabled={isFetching}
/> />
@ -255,7 +262,7 @@ export default function Login() {
<BaseButtons> <BaseButtons>
<BaseButton <BaseButton
className={'w-full'} className={'w-full'}
label="Ingresar con Google" label={t('pages.login.form.loginWithGoogle', { defaultValue: 'Ingresar con Google' })}
color="white" color="white"
icon={mdiGoogle} icon={mdiGoogle}
onClick={handleGoogleLogin} onClick={handleGoogleLogin}
@ -264,9 +271,9 @@ export default function Login() {
<br /> <br />
<p className={'text-center'}> <p className={'text-center'}>
Dont have an account yet?{' '} {t('pages.login.form.noAccountYet')}{' '}
<Link className={`${textColor}`} href={'/register'}> <Link className={`${textColor}`} href={'/register'}>
New Account {t('pages.login.form.newAccount')}
</Link> </Link>
</p> </p>
</Form> </Form>
@ -276,9 +283,9 @@ export default function Login() {
</div> </div>
</SectionFullScreen> </SectionFullScreen>
<div className='bg-black text-white flex flex-col text-center justify-center md:flex-row'> <div className='bg-black text-white flex flex-col text-center justify-center md:flex-row'>
<p className='py-6 text-sm'>© 2026 <span>{title}</span>. © All rights reserved</p> <p className='py-6 text-sm'>{t('pages.login.footer.copyright', { year: 2026, title: title })}</p>
<Link className='py-6 ml-4 text-sm' href='/privacy-policy/'> <Link className='py-6 ml-4 text-sm' href='/privacy-policy/'>
Privacy Policy {t('pages.login.footer.privacy')}
</Link> </Link>
</div> </div>
<ToastContainer /> <ToastContainer />
@ -288,4 +295,4 @@ export default function Login() {
Login.getLayout = function getLayout(page: ReactElement) { Login.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>; return <LayoutGuest>{page}</LayoutGuest>;
}; };