59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
"use client";
|
|
import { createContext, useContext, useEffect, useState } from "react";
|
|
|
|
export interface AlumnoUser {
|
|
idAlumno: string;
|
|
nombres: string;
|
|
apPaterno: string;
|
|
apMaterno?: string;
|
|
email: string;
|
|
/** De qué tabla viene: SAM (sige_sam_v3.alumnos) o EMPRESA (sige_sam_empresa.alumnos). */
|
|
origen: string;
|
|
}
|
|
|
|
interface SessionCtx {
|
|
user: AlumnoUser | null;
|
|
loading: boolean;
|
|
login: (idAlumno: string, password: string) => Promise<void>;
|
|
logout: () => Promise<void>;
|
|
}
|
|
|
|
const Ctx = createContext<SessionCtx | null>(null);
|
|
|
|
export function SessionProvider({ children }: { children: React.ReactNode }) {
|
|
const [user, setUser] = useState<AlumnoUser | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
fetch("/api/auth/me")
|
|
.then((r) => (r.ok ? r.json() : null))
|
|
.then((d) => setUser(d?.user ?? null))
|
|
.catch(() => setUser(null))
|
|
.finally(() => setLoading(false));
|
|
}, []);
|
|
|
|
async function login(idAlumno: string, password: string) {
|
|
const r = await fetch("/api/auth/login", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ idAlumno, password })
|
|
});
|
|
const d = await r.json().catch(() => null);
|
|
if (!r.ok || !d?.success) throw new Error(d?.message || "Credenciales inválidas");
|
|
setUser(d.user);
|
|
}
|
|
|
|
async function logout() {
|
|
await fetch("/api/auth/logout", { method: "POST" });
|
|
setUser(null);
|
|
}
|
|
|
|
return <Ctx.Provider value={{ user, loading, login, logout }}>{children}</Ctx.Provider>;
|
|
}
|
|
|
|
export function useSession() {
|
|
const ctx = useContext(Ctx);
|
|
if (!ctx) throw new Error("useSession fuera de SessionProvider");
|
|
return ctx;
|
|
}
|