feat: modulo de proyectos frontend (Next 16 + Bootstrap 5)
This commit is contained in:
commit
2dc41ed4fa
43 files changed
+5894
No files matched your search
@@ -0,0 +1,133 @@
|
||||
"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.
|
||||
*
|
||||
* Patrón visual de sam-portal / SistemaCalidad: sidenav azul con la marca
|
||||
* a la izquierda y la tarjeta de acceso a la derecha.
|
||||
*/
|
||||
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="container-fluid">
|
||||
<div className="row min-vh-100">
|
||||
{/* Marca */}
|
||||
<div className="col-md-5 sidenav d-flex flex-column justify-content-center">
|
||||
<div className="login-main-text text-center">
|
||||
<i className="bx bx-briefcase" style={{ fontSize: "5rem" }} />
|
||||
<h1 className="fw-bold mt-3">Proyectos</h1>
|
||||
<p className="mb-0" style={{ opacity: 0.8 }}>
|
||||
Gestión de proyectos · SAM
|
||||
</p>
|
||||
<p style={{ opacity: 0.5, fontSize: "0.85rem" }}>
|
||||
Organismo Técnico de Capacitación
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Formulario */}
|
||||
<div className="col-md-7 d-flex align-items-center justify-content-center">
|
||||
<div className="lp-card p-4 p-md-5" style={{ maxWidth: 420, width: "100%" }}>
|
||||
<h2 className="h5 fw-bold mb-1">Acceso al sistema</h2>
|
||||
<p className="small mb-4" style={{ color: "var(--inv-muted)" }}>
|
||||
Use su RUT y clave del sistema central (SIGE).
|
||||
</p>
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
{error && (
|
||||
<div className="alert alert-danger d-flex align-items-center gap-2 py-2" role="alert">
|
||||
<i className="bx bx-error" />
|
||||
<span className="small">{error}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="idUsuario" className="form-label">
|
||||
Usuario (RUT o legajo)
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="idUsuario"
|
||||
className="form-control"
|
||||
autoComplete="username"
|
||||
value={idUsuario}
|
||||
onChange={(event) => setIdUsuario(event.target.value)}
|
||||
required
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label htmlFor="password" className="form-label">
|
||||
Clave
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
className="form-control"
|
||||
autoComplete="current-password"
|
||||
value={password}
|
||||
onChange={(event) => setPassword(event.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-accent w-100 py-2 d-flex align-items-center justify-content-center gap-2"
|
||||
disabled={submitting}
|
||||
>
|
||||
{submitting ? (
|
||||
<>
|
||||
<span className="spinner-border spinner-border-sm" role="status" />
|
||||
Verificando…
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<i className="bx bx-log-in" />
|
||||
Ingresar
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user