diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 2380c70..25095c4 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -50,5 +50,10 @@ "select": "Select language", "es": "Spanish", "en": "English" + }, + "theme": { + "light": "Light theme", + "dark": "Dark theme", + "select": "Select theme" } } \ No newline at end of file diff --git a/public/locales/es/common.json b/public/locales/es/common.json index cc8fdf2..a120bc4 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -50,5 +50,10 @@ "select": "Seleccionar idioma", "es": "Español", "en": "Inglés" + }, + "theme": { + "light": "Tema claro", + "dark": "Tema oscuro", + "select": "Seleccionar tema" } } \ No newline at end of file diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts index 9606b7e..60fbae3 100644 --- a/src/app/api/auth/login/route.ts +++ b/src/app/api/auth/login/route.ts @@ -4,8 +4,13 @@ import { loginUser } from "@/controllers/authController"; export async function POST(request: NextRequest) { try { const body = await request.json(); + const { email, password, rememberMe } = body; - const { token, user, error, status } = await loginUser(body); + const { token, user, error, status } = await loginUser({ + email, + password, + rememberMe, + }); if (error) { return NextResponse.json({ error }, { status: status || 500 }); diff --git a/src/app/auth/login/page.tsx b/src/app/auth/login/page.tsx index b896151..2b4f4e3 100644 --- a/src/app/auth/login/page.tsx +++ b/src/app/auth/login/page.tsx @@ -13,12 +13,20 @@ export default function Login() { email: '', password: '' }); + const [rememberMe, setRememberMe] = useState(false); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); const handleChange = (e: React.ChangeEvent) => { - const { name, value } = e.target; - setFormData(prev => ({ ...prev, [name]: value })); + const { name, value, type, checked } = e.target; + + if (type === 'checkbox') { + if (name === 'remember-me') { + setRememberMe(checked); + } + } else { + setFormData(prev => ({ ...prev, [name]: value })); + } }; const handleSubmit = async (e: React.FormEvent) => { @@ -30,6 +38,7 @@ export default function Login() { const result = await login({ email: formData.email, password: formData.password, + rememberMe: rememberMe }); if (result.error) { @@ -54,26 +63,26 @@ export default function Login() { if (isLoading) return null; return ( -
+
-
-
-

{t('auth.login.title')}

-

+

+
+

{t('auth.login.title')}

+

{t('auth.login.subtitle')}

{error && ( -
+
{error}
)}
-
-
@@ -118,9 +127,11 @@ export default function Login() { id="remember-me" name="remember-me" type="checkbox" - className="h-4 w-4 text-blue-600 focus:ring-0 border-gray-300 rounded" + checked={rememberMe} + onChange={handleChange} + className="h-4 w-4 text-blue-600 focus:ring-0 border-gray-300 dark:border-gray-600 rounded" /> -
@@ -145,10 +156,10 @@ export default function Login() {
-
-

+

+

{t('auth.login.noAccount')}{' '} - + {t('auth.login.signUp')}

diff --git a/src/app/auth/register/page.tsx b/src/app/auth/register/page.tsx index b928af6..b6e4715 100644 --- a/src/app/auth/register/page.tsx +++ b/src/app/auth/register/page.tsx @@ -67,26 +67,26 @@ export default function Register() { if (isLoading) return null; return ( -
+
-
-
-

{t('auth.register.title')}

-

+

+
+

{t('auth.register.title')}

+

{t('auth.register.subtitle')}

{error && ( -
+
{error}
)}
-
-
-
-
@@ -174,10 +174,10 @@ export default function Register() {
-
-

+

+

{t('auth.register.haveAccount')}{' '} - + {t('auth.register.login')}

diff --git a/src/app/globals.css b/src/app/globals.css index e0e9fd8..ff7cf0b 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -7,11 +7,9 @@ --foreground: #171717; } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } +.dark { + --background: #0a0a0a; + --foreground: #ededed; } body { @@ -20,6 +18,8 @@ body { font-family: Arial, Helvetica, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + color: var(--foreground); + background-color: var(--background); } * { @@ -31,4 +31,9 @@ body { a { color: inherit; text-decoration: none; +} + +/* Transición suave al cambiar de tema */ +.dark *, * { + transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease; } \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 20b1d4f..a4ebc1a 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -3,6 +3,7 @@ import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; import { LanguageProvider } from "@/lib/i18n/language-context"; +import { ThemeProvider } from "@/lib/theme-context"; import { useEffect, useState } from "react"; const geistSans = Geist({ @@ -35,9 +36,11 @@ export default function RootLayout({ return ( - - {children} - + + + {children} + + ); diff --git a/src/app/page.tsx b/src/app/page.tsx index 6777c3c..258f9f1 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,6 +2,7 @@ import Link from 'next/link'; import LanguageSwitcher from '@/components/LanguageSwitcher'; +import ThemeSwitcher from '@/components/ThemeSwitcher'; import { useI18n } from '@/lib/i18n/useI18n'; export default function Home() { @@ -10,15 +11,16 @@ export default function Home() { if (isLoading) return null; return ( -
-
+
+
-
Draw
+
Draw