feat: frontend alumnos sam-pruebas (RUT+clave, rendir y mis resultados)
This commit is contained in:
commit
e6d283e184
26 files changed
+2555
No files matched your search
@@ -0,0 +1,133 @@
|
||||
// Cliente del backend SAM: GET /api/sam-pruebas/* (repo ICHN/sam, prod desplegado).
|
||||
const API_BASE = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:5000";
|
||||
const B = `${API_BASE}/api/sam-pruebas`;
|
||||
|
||||
async function req(path: string, init?: RequestInit) {
|
||||
const r = await fetch(B + path, { cache: "no-store", ...init });
|
||||
if (!r.ok) {
|
||||
const t = await r.text().catch(() => "");
|
||||
throw new Error(t.slice(0, 300) || `HTTP ${r.status}`);
|
||||
}
|
||||
if (r.status === 204) return null;
|
||||
return r.json();
|
||||
}
|
||||
|
||||
export const apiGet = (path: string) => req(path);
|
||||
export const apiPost = (path: string, body: unknown) =>
|
||||
req(path, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) });
|
||||
export const apiPut = (path: string, body: unknown) =>
|
||||
req(path, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) });
|
||||
|
||||
/** JSON.parse tolerante (columnas ::text que pueden venir null o malformadas). */
|
||||
export function parseJSON(s: string | null | undefined): any {
|
||||
if (!s) return null;
|
||||
try {
|
||||
return JSON.parse(s);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export interface Creador {
|
||||
idUsuario: string;
|
||||
nombres: string;
|
||||
apPaterno: string;
|
||||
apMaterno?: string;
|
||||
email: string;
|
||||
tipo?: string;
|
||||
}
|
||||
export interface Curso {
|
||||
idCursos: number;
|
||||
nombreCurso: string;
|
||||
nivelCurso?: number;
|
||||
duracion?: number;
|
||||
}
|
||||
export interface Alumno {
|
||||
idAlumno: string;
|
||||
nombres: string;
|
||||
apPaterno: string;
|
||||
apMaterno?: string;
|
||||
email: string;
|
||||
idCursoAbierto: number;
|
||||
idCursos: number;
|
||||
nombreCurso: string;
|
||||
}
|
||||
export interface Template {
|
||||
id: string;
|
||||
nombre: string;
|
||||
descripcion?: string;
|
||||
idCursos?: number;
|
||||
nivel?: string;
|
||||
tipoCurso: string;
|
||||
tipoPrueba: string;
|
||||
duracionMin: number;
|
||||
puntajeAprobacion: number;
|
||||
puntajeTotal: number;
|
||||
instrucciones?: string;
|
||||
usoCount: number;
|
||||
creadoPor?: string;
|
||||
}
|
||||
export interface Pregunta {
|
||||
id: string;
|
||||
templateId: string;
|
||||
sectionId?: string;
|
||||
orden: number;
|
||||
tipoPregunta: string;
|
||||
pregunta: string;
|
||||
opciones?: string;
|
||||
respuestaCorrecta?: string;
|
||||
explicacion?: string;
|
||||
puntaje: number;
|
||||
metadata?: string;
|
||||
}
|
||||
export interface BancoItem {
|
||||
id: string;
|
||||
pregunta: string;
|
||||
tipoPregunta: string;
|
||||
puntaje: number;
|
||||
dificultad: string;
|
||||
skill?: string;
|
||||
activo: boolean;
|
||||
usoCount: number;
|
||||
}
|
||||
export interface Asignacion {
|
||||
id: string;
|
||||
templateId: string;
|
||||
origen: string;
|
||||
idCursos?: number;
|
||||
idCursoAbierto?: number;
|
||||
fechaInicio?: string;
|
||||
fechaFin?: string;
|
||||
activo: boolean;
|
||||
asignadoPor?: string;
|
||||
}
|
||||
export interface Rendicion {
|
||||
id: string;
|
||||
asignacionId: string;
|
||||
idAlumno: string;
|
||||
intento: number;
|
||||
puntajeObtenido?: number;
|
||||
puntajeMaximo?: number;
|
||||
aprobado?: boolean;
|
||||
inicio: string;
|
||||
termino?: string;
|
||||
respuestas: string;
|
||||
}
|
||||
|
||||
export const TIPOS_PRUEBA = ["CA", "MWT", "MOT", "FOT", "FWT"];
|
||||
export const TIPOS_PREGUNTA = [
|
||||
"multiple-choice",
|
||||
"true-false",
|
||||
"short-answer",
|
||||
"essay",
|
||||
"matching",
|
||||
"ordering",
|
||||
"fill-in-the-blanks",
|
||||
"audio-response"
|
||||
];
|
||||
/** Tipos con corrección automática en el frontend. */
|
||||
export const AUTO_TYPES = ["multiple-choice", "true-false", "short-answer"];
|
||||
|
||||
export function nombreCompleto(a: { nombres: string; apPaterno: string; apMaterno?: string }) {
|
||||
return `${a.nombres} ${a.apPaterno}${a.apMaterno ? " " + a.apMaterno : ""}`;
|
||||
}
|
||||
Reference in new issue
Block a user