132 lines
4.5 KiB
TypeScript
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>
|
|
);
|
|
}
|