Fase 2: Creatción de la UI (React + Vite). Implementación de Log In reemplazando texto plano. Y creación de tool para migrar contraseñas.

This commit is contained in:
2025-05-05 15:49:01 -03:00
parent 9b1de95404
commit da7b544372
81 changed files with 12260 additions and 99 deletions

View File

@@ -0,0 +1,23 @@
import React from 'react';
import { Typography, Container } from '@mui/material';
// import { useLocation } from 'react-router-dom'; // Para obtener el estado 'firstLogin'
const ChangePasswordPage: React.FC = () => {
// const location = useLocation();
// const isFirstLogin = location.state?.firstLogin;
return (
<Container>
<Typography variant="h4" component="h1" gutterBottom>
Cambiar Contraseña
</Typography>
{/* {isFirstLogin && <Alert severity="warning">Debes cambiar tu contraseña inicial.</Alert>} */}
{/* Aquí irá el formulario de cambio de contraseña */}
<Typography variant="body1">
Formulario de cambio de contraseña irá aquí...
</Typography>
</Container>
);
};
export default ChangePasswordPage;

View File

@@ -0,0 +1,17 @@
import React from 'react';
import { Typography, Container } from '@mui/material';
const HomePage: React.FC = () => {
return (
<Container>
<Typography variant="h4" component="h1" gutterBottom>
Bienvenido al Sistema
</Typography>
<Typography variant="body1">
Seleccione una opción del menú principal para comenzar.
</Typography>
</Container>
);
};
export default HomePage;

View File

@@ -0,0 +1,112 @@
import React, { useState } from 'react';
import axios from 'axios'; // Importar axios
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';
import apiClient from '../services/apiClient'; // Nuestro cliente axios
import type { LoginRequestDto } from '../models/dtos/LoginRequestDto'; // Usar type
import type { LoginResponseDto } from '../models/dtos/LoginResponseDto'; // Usar type
// Importaciones de Material UI
import { Container, TextField, Button, Typography, Box, Alert } from '@mui/material';
const LoginPage: React.FC = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const { login } = useAuth();
const navigate = useNavigate();
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
setError(null);
setLoading(true);
const loginData: LoginRequestDto = { Username: username, Password: password };
try {
const response = await apiClient.post<LoginResponseDto>('/auth/login', loginData);
login(response.data); // Guardar token y estado de usuario en el contexto
// TODO: Verificar si response.data.DebeCambiarClave es true y redirigir
// a '/change-password' si es necesario.
// if (response.data.DebeCambiarClave) {
// navigate('/change-password', { state: { firstLogin: true } }); // Pasar estado si es necesario
// } else {
navigate('/'); // Redirigir a la página principal
// }
} catch (err: any) {
console.error("Login error:", err);
if (axios.isAxiosError(err) && err.response) {
// Intenta obtener el mensaje de error de la API, si no, usa uno genérico
setError(err.response.data?.message || 'Error al iniciar sesión. Verifique sus credenciales.');
} else {
setError('Ocurrió un error inesperado.');
}
} finally {
setLoading(false);
}
};
return (
<Container component="main" maxWidth="xs">
<Box
sx={{
marginTop: 8,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Typography component="h1" variant="h5">
Iniciar Sesión
</Typography>
<Box component="form" onSubmit={handleSubmit} noValidate sx={{ mt: 1 }}>
<TextField
margin="normal"
required
fullWidth
id="username"
label="Usuario"
name="username"
autoComplete="username"
autoFocus
value={username}
onChange={(e) => setUsername(e.target.value)}
disabled={loading}
/>
<TextField
margin="normal"
required
fullWidth
name="password"
label="Contraseña"
type="password"
id="password"
autoComplete="current-password"
value={password}
onChange={(e) => setPassword(e.target.value)}
disabled={loading}
/>
{error && (
<Alert severity="error" sx={{ mt: 2, width: '100%' }}>
{error}
</Alert>
)}
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
disabled={loading}
>
{loading ? 'Ingresando...' : 'Ingresar'}
</Button>
</Box>
</Box>
</Container>
);
};
export default LoginPage;