// ============================================================ // 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 = { 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 = { 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 = { 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" }; }