Files
FROM-SQL-INYEC/src/components/Login.jsx
beseira13 b85c365412 INICIO
2026-01-19 12:03:44 -03:00

327 lines
12 KiB
JavaScript

import React, { useState } from 'react';
import { User, Lock, LogIn, Database, ShieldCheck, Loader2, AlertCircle } from 'lucide-react';
import { authService } from '../services/api';
export default function Login({ onLoginSuccess }) {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
setError(null);
try {
const response = await authService.login(username, password);
// Assuming the API returns { success: true, token: '...', user: { ... } }
if (response.success) {
localStorage.setItem('auth_token', response.token);
localStorage.setItem('user_data', JSON.stringify(response.user));
onLoginSuccess(response.user);
} else {
setError(response.message || 'Credenciales inválidas');
}
} catch (err) {
console.error('Login error:', err);
setError(err.message || 'Error al conectar con el servidor');
} finally {
setLoading(false);
}
};
return (
<div className="login-page">
<div className="login-card">
<div className="login-header">
<div className="login-logo">
<Database size={32} className="logo-icon" />
</div>
<h1>ADVICOM SQL Manager</h1>
<p>Bienvenido. Ingrese sus credenciales para continuar.</p>
</div>
<form onSubmit={handleSubmit} className="login-form">
{error && (
<div className="error-alert">
<AlertCircle size={18} />
<span>{error}</span>
</div>
)}
<div className="input-group">
<label htmlFor="username">Usuario</label>
<div className="input-wrapper">
<User className="input-icon" size={18} />
<input
id="username"
type="text"
placeholder="ej: admin"
value={username}
onChange={(e) => setUsername(e.target.value)}
required
/>
</div>
</div>
<div className="input-group">
<label htmlFor="password">Contraseña</label>
<div className="input-wrapper">
<Lock className="input-icon" size={18} />
<input
id="password"
type="password"
placeholder="••••••••"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
</div>
<button
type="submit"
className="login-btn"
disabled={loading}
>
{loading ? (
<Loader2 className="animate-spin" size={20} />
) : (
<>
<LogIn size={20} />
<span>Iniciar Sesión</span>
</>
)}
</button>
</form>
<div className="login-footer">
<div className="secure-badge">
<ShieldCheck size={14} />
<span>Conexión segura SSL</span>
</div>
<p>© 2026 Advicom Group v1.0.0</p>
</div>
</div>
<style>{`
.login-page {
height: 100vh;
width: 100vw;
background: radial-gradient(circle at top right, #1e293b, #0f172a);
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
overflow: hidden;
position: relative;
}
.login-page::before {
content: '';
position: absolute;
top: -10%;
right: -10%;
width: 40%;
height: 40%;
background: radial-gradient(circle, rgba(59, 130, 246, 0.1) 0%, transparent 70%);
z-index: 0;
}
.login-page::after {
content: '';
position: absolute;
bottom: -10%;
left: -10%;
width: 30%;
height: 30%;
background: radial-gradient(circle, rgba(59, 130, 246, 0.05) 0%, transparent 70%);
z-index: 0;
}
.login-card {
width: 100%;
max-width: 420px;
background: rgba(30, 41, 59, 0.7);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 1.5rem;
padding: 2.5rem;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
z-index: 1;
animation: slideUp 0.6s ease-out;
}
@keyframes slideUp {
from { transform: translateY(20px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.login-header {
text-align: center;
margin-bottom: 2rem;
}
.login-logo {
width: 64px;
height: 64px;
background: linear-gradient(135deg, var(--accent), var(--accent-hover));
border-radius: 1.25rem;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 1.5rem;
box-shadow: 0 10px 15px -3px rgba(59, 130, 246, 0.5);
}
.logo-icon {
color: white;
}
.login-header h1 {
font-size: 1.75rem;
font-weight: 800;
color: white;
margin: 0;
letter-spacing: -0.025em;
}
.login-header p {
color: var(--text-secondary);
font-size: 0.875rem;
margin-top: 0.5rem;
}
.login-form {
display: flex;
flex-direction: column;
gap: 1.25rem;
}
.error-alert {
background: rgba(239, 68, 68, 0.1);
border: 1px solid rgba(239, 68, 68, 0.2);
padding: 0.75rem 1rem;
border-radius: 0.75rem;
color: #fca5a5;
font-size: 0.8125rem;
display: flex;
align-items: center;
gap: 0.75rem;
}
.input-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.input-group label {
font-size: 0.8125rem;
font-weight: 600;
color: var(--text-secondary);
margin-left: 0.25rem;
}
.input-wrapper {
position: relative;
display: flex;
align-items: center;
}
.input-icon {
position: absolute;
left: 1rem;
color: var(--text-muted);
pointer-events: none;
}
.input-wrapper input {
width: 100%;
background: var(--bg-input);
border: 1px solid var(--border);
color: white;
padding: 0.875rem 1rem 0.875rem 2.875rem;
border-radius: 1rem;
font-size: 0.875rem;
transition: all 0.2s;
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.05);
}
.input-wrapper input:focus {
outline: none;
border-color: var(--accent);
background: rgba(2, 6, 23, 0.8);
box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15);
}
.login-btn {
margin-top: 1rem;
background: linear-gradient(135deg, var(--accent), var(--accent-hover));
color: white;
border: none;
padding: 0.875rem;
border-radius: 1rem;
font-weight: 700;
font-size: 1rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
transition: all 0.3s;
box-shadow: 0 10px 15px -3px rgba(59, 130, 246, 0.3);
}
.login-btn:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 20px 25px -5px rgba(59, 130, 246, 0.4);
}
.login-btn:active:not(:disabled) {
transform: translateY(0);
}
.login-btn:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.login-footer {
margin-top: 2rem;
text-align: center;
}
.secure-badge {
display: inline-flex;
align-items: center;
gap: 0.375rem;
color: var(--success);
font-size: 0.75rem;
font-weight: 600;
margin-bottom: 1rem;
padding: 0.375rem 0.75rem;
background: rgba(16, 185, 129, 0.1);
border-radius: 2rem;
}
.login-footer p {
color: var(--text-muted);
font-size: 0.75rem;
margin: 0;
}
.animate-spin {
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
`}</style>
</div>
);
}