Files
proyectos/src/app/login/page.tsx
T

132 lines
4.5 KiB
TypeScript

"use client";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { useAuth } from "@/lib/auth";
/**
* Acceso al módulo. Valida contra sige_sam_v3.usuario en el backend
* (POST /api/proyectos/auth/login), igual que el resto de módulos SAM.
*
* Estructura idéntica a la de sam-portal (ventas/login.aspx): sidenav azul
* sólido #00285d con la marca a la izquierda, y el formulario en .main,
* que a partir de 768px se desplaza el 40% del sidenav.
*/
export default function LoginPage() {
const router = useRouter();
const { user, loading, login } = useAuth();
const [idUsuario, setIdUsuario] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState<string | null>(null);
const [submitting, setSubmitting] = useState(false);
// Si ya hay sesión, no tiene sentido mostrar el login.
useEffect(() => {
if (!loading && user) router.replace("/inbox");
}, [loading, user, router]);
async function handleSubmit(event: React.FormEvent) {
event.preventDefault();
if (submitting) return;
setError(null);
setSubmitting(true);
try {
await login(idUsuario, password);
router.push("/inbox");
} catch (err) {
setError(err instanceof Error ? err.message : "Error al ingresar");
setSubmitting(false);
}
}
return (
<div className="login-page">
<div className="sidenav">
<div className="login-main-text text-center">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="/studio-logo.png"
alt="Instituto Chileno Norteamericano"
className="login-brand"
/>
<h1 className="fw-bold">Proyectos</h1>
<h3>Welcome | Bienvenido/a</h3>
<h3>Gestión de Proyectos</h3>
</div>
</div>
<div className="main">
<div
className="row justify-content-center align-items-center"
style={{ minHeight: "85vh" }}
>
<div className="col-md-12">
<div className="col-md-12 text-center">
<div className="row">
<div className="col-md-2" />
<div className="col-md-8">
<div className="card alert alert-secondary">
<div className="card-body">
<div className="mb-3">
<strong>USUARIO | CLAVE</strong>
</div>
<form onSubmit={handleSubmit}>
{error && (
<div className="alert alert-danger py-2 mb-2">
<i className="bx bx-error me-1" />
{error}
</div>
)}
<input
name="TextBoxRut"
type="text"
value={idUsuario}
onChange={(event) => setIdUsuario(event.target.value)}
className="form-control shadow mb-2"
required
placeholder="Usuario"
autoComplete="username"
autoFocus
/>
<input
name="TextBoxClave"
type="password"
value={password}
onChange={(event) => setPassword(event.target.value)}
className="form-control shadow mb-2"
required
placeholder="Clave"
autoComplete="current-password"
/>
<div className="d-grid">
<button
type="submit"
disabled={submitting}
className="btn btn-success btn-sm"
>
{submitting ? (
<span className="spinner-border spinner-border-sm" />
) : (
"Ingresar"
)}
</button>
</div>
</form>
</div>
</div>
</div>
<div className="col-md-2" />
</div>
</div>
</div>
</div>
</div>
</div>
);
}