Files
sam-portal/src/lib/sam.ts
T

211 lines
7.9 KiB
TypeScript

// ============================================================
// SAM - Tipos, manifiesto de funciones API y helpers de UI
// Las funciones por módulo reflejan los controllers del
// backend compartido (SAM.API). El routing de ASP.NET Core
// es case-insensitive, por eso los paths van en minúsculas.
// ============================================================
export interface LastDeploy {
sha: string;
time: string;
ok: boolean;
log: string;
}
export interface ModuleState {
name: string;
repoUrl: string;
branch: string;
subdomain: string;
port: number;
active: boolean;
category?: string;
lastDeploy?: LastDeploy;
container?: string | null;
}
export interface ApiResponse {
backend: {
repoUrl: string;
branch: string;
container: string | null;
lastDeploy: LastDeploy | null;
};
modules: ModuleState[];
}
export interface ApiFunction {
label: string;
icon: string;
path: string;
desc: string;
}
export interface MenuItem {
label: string;
icon: string;
href: string;
}
const A = (
label: string,
icon: string,
path: string,
desc: string
): ApiFunction => ({ label, icon, path, desc });
// --- Conjuntos de funciones por familia de módulo ---
const CORE: ApiFunction[] = [
A("Alumnos", "bx-group", "api/alumnos", "Ficha, matrícula y sesiones de alumnos"),
A("Cursos", "bx-book", "api/cursos", "Catálogo, apertura y horarios de cursos"),
A("Profesores", "bx-pencil", "api/profesores", "Ficha y periodos de profesores"),
A("Empresas", "bx-buildings", "api/empresas/extra", "Empresas en convenio y propuestas"),
A("Pagos", "bx-money", "api/pagos", "Caja, cotizaciones y vouchers"),
A("Contratos", "bx-file", "api/contratos", "Contratos firmados y por firmar"),
A("Informes", "bx-bar-chart-alt-2", "api/informes", "Reportes académicos y de gestión"),
];
const FUNCTION_SETS: Record<string, ApiFunction[]> = {
academico: [
A("Cursos", "bx-book", "api/cursos", "Catálogo, apertura y horarios"),
A("Alumnos", "bx-group", "api/alumnos/extra", "Ficha, matrícula y sesiones"),
A("Apoderados", "bx-user", "api/apoderados", "Apoderados y contactos"),
A("Horarios", "bx-time", "api/horarios", "Bloques horarios y salas"),
A("Jornadas", "bx-sun", "api/jornadas", "Jornadas diurno / vespertino"),
A("Feriados", "bx-calendar", "api/feriados", "Calendario de feriados"),
A("Placement Test", "bx-edit", "api/placement-test", "Pruebas de nivel"),
A("Plan Anual", "bx-calendar-alt", "api/plan-anual", "Planificación anual"),
],
profesores: [
A("Profesores", "bx-pencil", "api/profesores", "Ficha y periodos"),
A("Funciones Extra", "bx-plus-circle", "api/profesores/extra", "Operaciones extendidas"),
A("Horarios", "bx-time", "api/horarios", "Bloques horarios y salas"),
A("Jornadas", "bx-sun", "api/jornadas", "Jornadas diurno / vespertino"),
],
empresas: [
A("Propuestas", "bx-briefcase", "api/propuestas-empresa", "Propuestas a empresas"),
A("Empresas", "bx-buildings", "api/empresas/extra", "Empresas en convenio"),
A("Comercial", "bx-trending-up", "api/comercial/extra", "Gestión comercial"),
A("Contratos", "bx-file", "api/contratos/extra", "Contratos con empresas"),
],
ventas: [
A("Comercial", "bx-trending-up", "api/comercial/extra", "Gestión comercial"),
A("Leads", "bx-target-lock", "api/leads/extra", "Prospectos y seguimiento"),
A("Ventas", "bx-cart", "api/ventas", "Ventas y cotizaciones"),
A("Cotizaciones", "bx-receipt", "api/cotizaciones", "Cotizaciones emitidas"),
A("Ejecutivos", "bx-user-voice", "api/ejecutivos", "Ejecutivos de venta"),
],
pagos: [
A("Portal Pagos", "bx-credit-card", "api/portal-pagos", "Pagos en línea"),
A("Pagos", "bx-money", "api/pagos", "Caja y vouchers"),
A("WebPay", "bx-card", "api/webpay", "Transacciones Transbank"),
A("Boletas", "bx-receipt", "api/boletas", "Boletas y facturación"),
A("Arqueo", "bx-calculator", "api/arqueocaja", "Arqueo de caja"),
],
contabilidad: [
A("Contabilidad", "bx-detail", "api/contabilidad", "Movimientos contables"),
A("Libros", "bx-book-open", "api/libros", "Libros de compra / venta"),
A("DTE", "bx-file-blank", "api/dte", "Documentos tributarios"),
A("Documentos", "bx-folder", "api/documentos", "Repositorio documental"),
],
};
const MODULE_FAMILY: Record<string, string> = {
academico: "academico",
"academico-empresas": "empresas",
portal: "empresas",
empresas: "empresas",
ventas: "ventas",
comercial: "ventas",
pagos: "pagos",
contabilidad: "contabilidad",
profesores: "profesores",
};
export function getModuleFunctions(name: string): ApiFunction[] {
const key = name.toLowerCase();
const family =
MODULE_FAMILY[key] ??
Object.keys(FUNCTION_SETS).find((f) => key.includes(f));
if (family && FUNCTION_SETS[family]) return FUNCTION_SETS[family];
return CORE;
}
// --- Meta visual por módulo (iconos boxicons + fondo) ---
const iconMap: Record<string, { icon: string; bg: string }> = {
sam: { icon: "bx-layer", bg: "bg-primary" },
ventas: { icon: "bx-money", bg: "bg-success" },
comercial: { icon: "bx-money", bg: "bg-success" },
finanzas: { icon: "bx-detail", bg: "bg-danger" },
contabilidad: { icon: "bx-detail", bg: "bg-danger" },
academico: { icon: "bx-user", bg: "bg-primary" },
"academico-empresas": { icon: "bx-briefcase", bg: "bg-primary" },
profesor: { icon: "bx-pencil", bg: "bg-warning text-dark" },
profesores: { icon: "bx-pencil", bg: "bg-warning text-dark" },
empresas: { icon: "bx-building", bg: "bg-info" },
portal: { icon: "bx-building", bg: "bg-info" },
pagos: { icon: "bx-credit-card", bg: "bg-success" },
default: { icon: "bx-cube", bg: "bg-secondary" },
};
export function getModuleMeta(name: string) {
return iconMap[name.toLowerCase()] || iconMap.default;
}
export function getStatusInfo(m: ModuleState) {
if (!m.container) return { label: "Detenido", cls: "status-unhealthy" };
if (m.container.includes("healthy"))
return { label: "Activo", cls: "status-healthy" };
if (m.container.includes("starting"))
return { label: "Iniciando", cls: "status-starting" };
return { label: "Activo", cls: "status-healthy" };
}
export function displayName(name: string) {
return name.charAt(0).toUpperCase() + name.slice(1).replace(/-/g, " ");
}
export function moduleUrl(m: ModuleState) {
return `https://${m.subdomain}.devops.norteamericano.cl`;
}
// ============================================================
// Secciones del índice: dónde aparece cada módulo.
// - Todo módulo nuevo cae en "apps" (Aplicaciones) automáticamente.
// - Para mover un módulo a otra sección, agrégalo a MODULE_SECTION.
// - Para crear una sección futura: agrega una entrada en SECTIONS
// (id, título, icono) y la regla en MODULE_SECTION o en
// sectionOf(). El índice la renderiza sola si tiene módulos.
// ============================================================
export interface Section {
id: string;
title: string;
icon: string;
}
export const SECTIONS: Section[] = [
{ id: "pagina-web", title: "Página Web", icon: "bx-globe" },
{ id: "sam", title: "SAM", icon: "bx-layer" },
{ id: "profesores", title: "Profesores", icon: "bx-pencil" },
{ id: "otras-apps", title: "Otras Aplicaciones", icon: "bx-cube" },
];
// Categoría que pregunta la integración (default del deployer: otras-apps).
// "Otras Aplicaciones" concentra la revisión prod/dev: módulos
// integrados + backend + gestión.
export function sectionOf(name: string, category?: string): string {
const c = (category || "").trim().toLowerCase();
if (c && SECTIONS.some((s) => s.id === c)) return c;
void name;
return "otras-apps";
}
// Rama main/master = producción, resto = desarrollo.
export function envOf(branch: string) {
const b = (branch || "").trim().toLowerCase();
return b === "main" || b === "master" || b === "prod" || b === "production"
? { label: "Prod", cls: "bg-success" }
: { label: "Dev", cls: "bg-warning text-dark" };
}