merge Sam
This commit is contained in:
@@ -107,6 +107,7 @@ const FormProfesor = () => {
|
||||
activo,
|
||||
lineasInvestigacion,
|
||||
proyectosAcademicos,
|
||||
foto: fotoBase64,
|
||||
};
|
||||
|
||||
const token = localStorage.getItem('Token');
|
||||
@@ -143,7 +144,7 @@ const FormProfesor = () => {
|
||||
const onDrop = useCallback(acceptedFiles => {
|
||||
const file = acceptedFiles[0];
|
||||
setFoto(file);
|
||||
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
const base64String = reader.result;
|
||||
@@ -193,13 +194,11 @@ const FormProfesor = () => {
|
||||
<h2>Datos Académicos</h2>
|
||||
<div className="form-group">
|
||||
<label>Grado Maximo <span className="required">*</span></label>
|
||||
<input type="email" name="grado_maximo" required
|
||||
onChange={handleInputChange} />
|
||||
<input type="email" name="grado_maximo" required onChange={handleInputChange} />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label>Grados Obtenidos <span className="required">*</span></label>
|
||||
<input type="email" name="grados_obtenidos" required
|
||||
onChange={handleInputChange} />
|
||||
<input type="email" name="grados_obtenidos" required onChange={handleInputChange} />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label>Correo Pcpuma <span className="required">*</span></label>
|
||||
@@ -279,8 +278,8 @@ const FormProfesor = () => {
|
||||
onChange={(e) => handleSelectChange(e, setActivo)}
|
||||
className="form-control m-2"
|
||||
>
|
||||
<option value = {true} >Sí</option>
|
||||
<option value= {false} >No</option>
|
||||
<option value={true}>Sí</option>
|
||||
<option value={false}>No</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
@@ -294,7 +293,7 @@ const FormProfesor = () => {
|
||||
)}
|
||||
</div>
|
||||
{foto && <p>Archivo seleccionado: {foto.name}</p>}
|
||||
{fotoBase64 && <img src={fotoBase64} alt="Foto seleccionada" style={{ maxWidth: '200px', marginTop: '10px' }} />}
|
||||
{fotoBase64 && <img src={fotoBase64} alt="Preview" style={{ width: '100px', height: '100px' }} />}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -398,5 +397,4 @@ const FormProfesor = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default FormProfesor;
|
||||
|
||||
export default FormProfesor;
|
||||
@@ -0,0 +1,139 @@
|
||||
/* components/LoginForm.css */
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
max-width: 300px;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
padding: 1.5em;
|
||||
background: white;
|
||||
box-shadow: 0 4px 8px 2px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
h1.text-warning {
|
||||
color: #ffc107;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h2.m-3 {
|
||||
margin: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 0.5em;
|
||||
color: #333333;
|
||||
display: block;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.login input[type="text"],
|
||||
.login input[type="password"] {
|
||||
border: 1px solid #CCCCCC;
|
||||
padding: 0.4em;
|
||||
font-size: 0.9em;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border-radius: 5px;
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 2px 4px 1px rgba(0, 0, 0, 0.1);
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.login input[type="text"]:focus,
|
||||
.login input[type="password"]:focus {
|
||||
box-shadow: 0 0 8px 2px rgba(0, 123, 255, 0.5);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.remember-me-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.remember-me-label {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
width: 18px !important; /* Incremento de tamaño */
|
||||
height: 18px !important; /* Incremento de tamaño */
|
||||
border: 1px solid #CCCCCC !important;
|
||||
border-radius: 3px !important;
|
||||
background-color: #fff;
|
||||
appearance: none;
|
||||
cursor: pointer !important;
|
||||
position: relative !important;
|
||||
transition: background-color 0.3s ease, border-color 0.3s ease !important;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked::before {
|
||||
content: '✔';
|
||||
font-size: 14px;
|
||||
color: #007bff !important;
|
||||
position: absolute !important;
|
||||
top: 50% !important;
|
||||
left: 50% !important;
|
||||
transform: translate(-50%, -55%) !important; /* Ajuste para centrar la paloma */
|
||||
}
|
||||
|
||||
input[type="checkbox"]:focus {
|
||||
box-shadow: 0 0 5px 2px rgba(0, 123, 255, 0.5);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.btn-group .btn {
|
||||
padding: 0.6em 1em;
|
||||
border: 1px solid #007bff;
|
||||
border-radius: 0.25em;
|
||||
background-color: transparent;
|
||||
color: #007bff;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
}
|
||||
|
||||
.btn-group .btn.active {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
button[type="submit"] {
|
||||
width: 100%;
|
||||
padding: 0.75em;
|
||||
border: none;
|
||||
border-radius: 1em;
|
||||
background-color: #002B7A;
|
||||
color: #fff;
|
||||
font-size: 0.9em;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
button[type="submit"]:hover {
|
||||
background-color: #0056b3;
|
||||
box-shadow: 0 6px 12px 4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
button[type="submit"]:disabled {
|
||||
background-color: #007bff;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: center;
|
||||
margin-top: 1em;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { PrivateRoutes } from '../../models/routes';
|
||||
import './LoginForm.css';
|
||||
|
||||
const LoginForm = () => {
|
||||
const [usuario, setUsuario] = useState('');
|
||||
const [contraseña, setContraseña] = useState('');
|
||||
const [rememberMe, setRememberMe] = useState(false); // Estado para el botón de mantener sesión
|
||||
const [error, setError] = useState(null); // Estado para manejar errores
|
||||
const [loading, setLoading] = useState(false); // Estado para manejar el estado de carga
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
setLoading(true); // Activar el estado de carga
|
||||
setError(null); // Limpiar errores previos
|
||||
|
||||
// Validar si los campos están vacíos
|
||||
if (!usuario || !contraseña) {
|
||||
setError('Es necesario rellenar el usuario y la contraseña.');
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`http://localhost:3000/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ usuario, contraseña }),
|
||||
});
|
||||
|
||||
if (response.status === 401) {
|
||||
setError('Usuario o contraseña inválido.');
|
||||
} else if (response.status === 500) {
|
||||
setError('Error con la conexión de la API.');
|
||||
} else if (!response.ok) {
|
||||
throw new Error('Error en el inicio de sesión');
|
||||
} else {
|
||||
const data = await response.json();
|
||||
console.log('Response:', data);
|
||||
window.location.href = PrivateRoutes.INTERFACE;
|
||||
localStorage.setItem('Token', data.token);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
setError('Error en el inicio de sesión');
|
||||
} finally {
|
||||
setLoading(false); // Desactivar el estado de carga
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<Link to={"/profesor/perfil/36"}>Hola mundo</Link>
|
||||
<h1 className="text-warning">Bienvenido al directorio de profesores</h1>
|
||||
<h2 className='m-3'>Iniciar sesión</h2>
|
||||
<form onSubmit={handleSubmit} className="login-form" style={{ background: '#f9f9f9', borderRadius: '1em' }}>
|
||||
<div className="input-group">
|
||||
<label htmlFor="username">Nombre de Usuario:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
value={usuario}
|
||||
onChange={(e) => setUsuario(e.target.value)}
|
||||
disabled={loading} // Desactivar input mientras carga
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="input-group">
|
||||
<label htmlFor="password">Contraseña:</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
value={contraseña}
|
||||
onChange={(e) => setContraseña(e.target.value)}
|
||||
disabled={loading} // Desactivar input mientras carga
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="input-group remember-me-group">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="rememberMe"
|
||||
checked={rememberMe}
|
||||
onChange={() => setRememberMe(!rememberMe)}
|
||||
disabled={loading} // Desactivar checkbox mientras carga
|
||||
/>
|
||||
<label htmlFor="rememberMe" className="remember-me-label">Mantener la sesión</label>
|
||||
</div>
|
||||
<button type="submit" disabled={loading}>Ingresar</button>
|
||||
{loading && <p>Cargando...</p>}
|
||||
{error && <p style={{ color: 'red' }}>{error}</p>}
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginForm;
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import './FormEditProfesor.css';
|
||||
|
||||
const FormEditProfesor = () => {
|
||||
@@ -13,13 +14,15 @@ const FormEditProfesor = () => {
|
||||
const [edificio, setEdificio] = useState('');
|
||||
const [adscripcion, setAdscripcion] = useState('');
|
||||
const [categoria, setCategoria] = useState('');
|
||||
const [activo, setActivo] = useState();
|
||||
const [activo, setActivo] = useState(true);
|
||||
const [foto, setFoto] = useState(null);
|
||||
const [fotoBase64, setFotoBase64] = useState('');
|
||||
const [lineasInvestigacion, setLineasInvestigacion] = useState([]);
|
||||
const [proyectosAcademicos, setProyectosAcademicos] = useState([]);
|
||||
|
||||
|
||||
const [photo, setPhoto] = useState(null);
|
||||
const [preview, setPreview] = useState(null);
|
||||
|
||||
const handlePageChange = (newPage) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
@@ -60,7 +63,6 @@ const FormEditProfesor = () => {
|
||||
setProyectosAcademicos(data.proyectosAcademicos);
|
||||
})
|
||||
.catch(error => console.error('Error fetching profesor:', error));
|
||||
console.log(profesor)
|
||||
}, [id_profesor]);
|
||||
|
||||
const handleInputChange = (event) => {
|
||||
@@ -155,9 +157,13 @@ const FormEditProfesor = () => {
|
||||
reader.readAsDataURL(file);
|
||||
}, []);
|
||||
|
||||
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
||||
onDrop,
|
||||
accept: 'image/jpeg, image/png'
|
||||
const { getRootProps, getInputProps } = useDropzone({
|
||||
accept: '.jpg,.png',
|
||||
onDrop: (acceptedFiles) => {
|
||||
const file = acceptedFiles[0];
|
||||
setPhoto(file);
|
||||
setPreview(URL.createObjectURL(file));
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -400,4 +406,3 @@ const FormEditProfesor = () => {
|
||||
};
|
||||
|
||||
export default FormEditProfesor;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user