aef8791151
- Added Appshell component with responsive navbar and main content area - Integrated ColorSchemeToggle for light/dark mode switching - Created Welcome component with styled title and introductory text - Developed ChatPage for LLM interaction with WebSocket support - Implemented Biblioteca for managing notes with rich text editor - Added LoginPage for user authentication with error handling - Introduced MessageList and MessageBubble components for chat messages - Styled components with CSS modules for consistent design
67 lines
2.2 KiB
TypeScript
67 lines
2.2 KiB
TypeScript
import { useState } from 'react';
|
|
import { TextInput, PasswordInput, Button, Paper, Title, Container, Group, Alert } from '@mantine/core';
|
|
import UserIcon from '../../assets/icons/outlined/user.svg?react';
|
|
import LockIcon from '../../assets/icons/outlined/lock.svg?react';
|
|
|
|
export function LoginPage() {
|
|
const [email, setEmail] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [error, setError] = useState('');
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setLoading(true);
|
|
setError('');
|
|
// Aquí deberías llamar a tu endpoint de login (ajusta la URL y payload)
|
|
try {
|
|
const res = await fetch('/api/v1/usuarios/login', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ email, password })
|
|
});
|
|
if (!res.ok) throw new Error('Credenciales incorrectas');
|
|
// Aquí puedes guardar el usuario/token en el estado global o localStorage
|
|
window.location.href = '/';
|
|
} catch (err: any) {
|
|
setError(err.message);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Container size={420} my={40}>
|
|
<Title align="center" mb={20}>Iniciar sesión</Title>
|
|
<Paper withBorder shadow="md" p={30} mt={30} radius="md">
|
|
<form onSubmit={handleSubmit}>
|
|
<TextInput
|
|
label="Email"
|
|
placeholder="tucorreo@ejemplo.com"
|
|
icon={<UserIcon style={{ width: 18, height: 18 }} />}
|
|
value={email}
|
|
onChange={e => setEmail(e.target.value)}
|
|
required
|
|
mb={10}
|
|
/>
|
|
<PasswordInput
|
|
label="Contraseña"
|
|
placeholder="Tu contraseña"
|
|
icon={<LockIcon style={{ width: 18, height: 18 }} />}
|
|
value={password}
|
|
onChange={e => setPassword(e.target.value)}
|
|
required
|
|
mb={20}
|
|
/>
|
|
{error && <Alert color="red" mb={10}>{error}</Alert>}
|
|
<Group mt="md">
|
|
<Button type="submit" loading={loading} fullWidth>
|
|
Entrar
|
|
</Button>
|
|
</Group>
|
|
</form>
|
|
</Paper>
|
|
</Container>
|
|
);
|
|
}
|