+
+
- )}
+ )}
- {SECTIONS.map((section) => {
- const list = bySection[section.id] ?? [];
- const isReview = section.id === "otras-apps";
- if (!isReview && list.length === 0) return null;
- return (
-
-
-
-
-
- {" "}
- {section.title}
-
- {list.length > 0 && (
-
- {list.length} módulo
- {list.length !== 1 ? "s" : ""}
-
- )}
-
-
-
- {list.map(renderModuleCard)}
-
- {section.id === "sam" &&
- REFERENCE_APPS.filter(
- (a) =>
- !list.some((m) => m.name.toLowerCase() === a.name)
- ).map(renderRefCard)}
-
- {isReview && backend && (
- <>
-
-
-
-
-
- |
-
- |
-
-
- API Backend
-
-
- {backend.container ? "Activo" : "Detenido"} · {backend.branch}
-
- |
-
-
-
-
-
-
-
-
-
-
- |
-
- |
-
-
- Gestionar Módulos
-
-
- Subir / actualizar proyectos
-
- |
-
-
-
-
-
- >
- )}
+ {error && (
+
+
+
+ Error: {error}
+
- );
- })}
+ )}
-
-
- Auto-actualizado cada 15s ·{" "}
- { e.preventDefault(); fetchModules(); }}>
- actualizar ahora
-
-
+ {!loading && !error && (
+
+ {modules.length === 0 && (
+
+
+
+
+ No hay módulos integrados. ¡Sube tu primer proyecto!
+
+
+
Subir Proyecto
+
+
+
+ )}
+
+ {SECTIONS.map((section) => {
+ const list = bySection[section.id] ?? [];
+ const isReview = section.id === "otras-apps";
+ if (!isReview && list.length === 0) return null;
+ return (
+
+
+
+
+
+ {" "}
+ {section.title}
+
+ {list.length > 0 && (
+
+ {list.length} módulo
+ {list.length !== 1 ? "s" : ""}
+
+ )}
+
+
+
+ {list.map(renderModuleCard)}
+
+ {section.id === "sam" &&
+ REFERENCE_APPS.filter(
+ (a) =>
+ !list.some((m) => m.name.toLowerCase() === a.name)
+ ).map(renderRefCard)}
+
+ {isReview && backend && (
+ <>
+
+
+
+
+
+ |
+
+ |
+
+
+ API Backend
+
+
+ {backend.container ? "Activo" : "Detenido"} · {backend.branch}
+
+ |
+
+
+
+
+
+
+
+
+
+
+ |
+
+ |
+
+
+ Gestionar Módulos
+
+
+ Subir / actualizar proyectos
+
+ |
+
+
+
+
+
+ >
+ )}
+
+
+ );
+ })}
+
+
+
+ )}
- )}
-
+
+ >
);
}
diff --git a/src/app/tablero/page.tsx b/src/app/tablero/page.tsx
index 604f627..ad9010d 100644
--- a/src/app/tablero/page.tsx
+++ b/src/app/tablero/page.tsx
@@ -2,17 +2,31 @@
import SamShell from "@/components/SamShell";
import TableroView from "@/components/TableroView";
+import { useModules } from "@/lib/store";
+import { displayName, getModuleMeta } from "@/lib/sam";
-const menu = [
- { label: "Resumen", icon: "bx-grid-alt", href: "#resumen" },
- { label: "Aplicaciones", icon: "bx-layer", href: "/" },
-];
-
+// App IT: sidebar con todas sus opciones (resumen, aplicaciones,
+// tableros por módulo y gestión). Se sirve en /tablero y en
+// it.sam.devops.norteamericano.cl
export default function Tablero() {
+ const { data } = useModules();
+ const modules = data?.modules ?? [];
+
+ const menu = [
+ { label: "Resumen", icon: "bx-grid-alt", href: "#resumen" },
+ { label: "Aplicaciones", icon: "bx-layer", href: "/" },
+ ...modules.map((m) => ({
+ label: displayName(m.name),
+ icon: getModuleMeta(m.name).icon,
+ href: `/m/${m.name}`,
+ })),
+ { label: "Nuevo Módulo", icon: "bx-plus", href: "/upload" },
+ ];
+
return (