utn-cli 2.0.96 → 2.0.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "utn-cli",
3
- "version": "2.0.96",
3
+ "version": "2.0.97",
4
4
  "description": "Herramienta CLI unificada para la gestión de plantillas en SIGU.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -60,6 +60,48 @@ class ReporteHTML {
60
60
  }
61
61
 
62
62
  GenerarReporteHTMLRegistrosVerticales(ElementosParaLaTabla, ParametrosExcluidos = [], ParametrosExtra = [], MostrarEncabezado = true) {
63
+ //Ejemplo ElementosParaLaTabla:
64
+ // [
65
+ // {
66
+ // "Fecha del traslado": "16-03-2026",
67
+ // "Justificacion": "Traslado por mantenimiento",
68
+ // "Dependencia que entrega": "Juan Pérez",
69
+ // "Dependencia que recibe": "María Gómez",
70
+ // Placa: "ABC123",
71
+ // "Descripción": "Laptop Dell",
72
+ // "Código de activo": "ACT-001",
73
+ // "N° de serie": "SN123456",
74
+ // Marca: "Dell",
75
+ // Modelo: "Latitude 5420",
76
+ // Estado: "Bueno",
77
+ // IdentificadorOrigen: 101,
78
+ // IdentificadorDestino: 202
79
+ // },
80
+ // {
81
+ // "Fecha del traslado": "16-03-2026",
82
+ // "Justificacion": "Traslado por mantenimiento",
83
+ // "Dependencia que entrega": "Juan Pérez",
84
+ // "Dependencia que recibe": "María Gómez",
85
+ // Placa: "XYZ789",
86
+ // "Descripción": "Monitor Samsung",
87
+ // "Código de activo": "ACT-002",
88
+ // "N° de serie": "SN654321",
89
+ // Marca: "Samsung",
90
+ // Modelo: "S24F350",
91
+ // Estado: "Excelente",
92
+ // IdentificadorOrigen: 101,
93
+ // IdentificadorDestino: 202
94
+ // }
95
+ // ]
96
+ // Espera un Array
97
+ //Ejemplo ParametrosExcluidos:
98
+ //const ParametrosExcluidos = ['IdentificadorOrigen', 'Justificacion', 'IdentificadorDestino'];
99
+ //Valores devueltos por el QUERY que no sean necesarios mostrar en la tabla.
100
+
101
+ //Ejemplo ParametrosExtra:
102
+ //const ParametrosExtra = ['Toma física'];
103
+ //En caso de necesitar un espacio extra en la tabla que no se encuentra en la lista principal.
104
+
63
105
  if (!ElementosParaLaTabla?.length) return '<p>No hay datos para mostrar.</p>';
64
106
 
65
107
  const baseColumnas = Object.keys(ElementosParaLaTabla[0]).filter(col => !ParametrosExcluidos.includes(col));
@@ -186,6 +228,48 @@ class ReporteHTML {
186
228
  }
187
229
 
188
230
  GenerarReporteHTMLTablas(ElementosParaLaTabla, ParametrosExcluidos = [], ParametrosExtra = []) {
231
+ //Ejemplo ElementosParaLaTabla:
232
+ // [
233
+ // {
234
+ // "Fecha del traslado": "16-03-2026",
235
+ // "Justificacion": "Traslado por mantenimiento",
236
+ // "Dependencia que entrega": "Juan Pérez",
237
+ // "Dependencia que recibe": "María Gómez",
238
+ // Placa: "ABC123",
239
+ // "Descripción": "Laptop Dell",
240
+ // "Código de activo": "ACT-001",
241
+ // "N° de serie": "SN123456",
242
+ // Marca: "Dell",
243
+ // Modelo: "Latitude 5420",
244
+ // Estado: "Bueno",
245
+ // IdentificadorOrigen: 101,
246
+ // IdentificadorDestino: 202
247
+ // },
248
+ // {
249
+ // "Fecha del traslado": "16-03-2026",
250
+ // "Justificacion": "Traslado por mantenimiento",
251
+ // "Dependencia que entrega": "Juan Pérez",
252
+ // "Dependencia que recibe": "María Gómez",
253
+ // Placa: "XYZ789",
254
+ // "Descripción": "Monitor Samsung",
255
+ // "Código de activo": "ACT-002",
256
+ // "N° de serie": "SN654321",
257
+ // Marca: "Samsung",
258
+ // Modelo: "S24F350",
259
+ // Estado: "Excelente",
260
+ // IdentificadorOrigen: 101,
261
+ // IdentificadorDestino: 202
262
+ // }
263
+ // ]
264
+ // Espera un Array
265
+ //Ejemplo ParametrosExcluidos:
266
+ //const ParametrosExcluidos = ['IdentificadorOrigen', 'Justificacion', 'IdentificadorDestino'];
267
+ //Valores devueltos por el QUERY que no sean necesarios mostrar en la tabla.
268
+
269
+ //Ejemplo ParametrosExtra:
270
+ //const ParametrosExtra = ['Toma física'];
271
+ //En caso de necesitar un espacio extra en la tabla que no se encuentra en la lista principal.
272
+
189
273
  if (!ElementosParaLaTabla?.length) return '';
190
274
 
191
275
  const baseColumnas = Object.keys(ElementosParaLaTabla[0]).filter(col => !ParametrosExcluidos.includes(col));
@@ -225,6 +309,37 @@ class ReporteHTML {
225
309
  </table>`;
226
310
  }
227
311
 
312
+ GenerarReporteHTMLDatosEnAgrupacion(titulo, valores) {
313
+ // Ejemplo titulo:
314
+ // "Residencia: Atenas 123"
315
+ // Espera un String. Puede contener texto simple o etiquetas HTML básicas.
316
+
317
+ // Ejemplo valores:
318
+ // {
319
+ // "Descripción": "Residencias principales del recinto",
320
+ // "Total de habitaciones disponibles": 3,
321
+ // "Estado": "Activo"
322
+ // }
323
+ // Espera un Objeto (JSON plano) donde cada par llave:valor será una línea en la agrupación.
324
+ // IMPORTANTE: Se recomienda construir este objeto a mano mapeando solo los datos necesarios
325
+ // de la base de datos, para evitar imprimir por error arreglos u objetos complejos anidados.
326
+
327
+ let htmlTarjeta = `
328
+ <div style="margin-bottom: 25px; padding: 15px; background-color: #f4f6f9; border-left: 4px solid #002f6b; border-radius: 4px;">
329
+ <h3 style="margin-top: 0; margin-bottom: 8px; color: #002f6b; font-size: 16px; font-weight: bold;">${titulo}</h3>
330
+ `;
331
+
332
+ const llaves = Object.keys(valores);
333
+ llaves.forEach((llave, index) => {
334
+ const margenInferior = (index === llaves.length - 1) ? '0' : '6px';
335
+ const valor = valores[llave] ?? '-';
336
+ htmlTarjeta += `<p style="margin: 0 0 ${margenInferior} 0; font-size: 13px; color: #444; line-height: 1.4;"><strong>${llave}:</strong> ${valor}</p>`;
337
+ });
338
+
339
+ htmlTarjeta += `</div>`;
340
+ return htmlTarjeta;
341
+ }
342
+
228
343
  GenerarReporteHTMLPie() {
229
344
  return `
230
345
  </body>
@@ -232,4 +347,4 @@ class ReporteHTML {
232
347
  }
233
348
  }
234
349
 
235
- module.exports = new ReporteHTML();
350
+ module.exports = new ReporteHTML();
@@ -460,6 +460,86 @@ class ReportePDF {
460
460
  }
461
461
  }
462
462
 
463
+ generarDatosEnAgrupacion(doc, titulo, valores) {
464
+ if (!valores || typeof valores !== 'object') return;
465
+
466
+ const margin = this.config.margin;
467
+ const pageWidth = doc.page.width;
468
+ const availableWidth = pageWidth - 2 * margin;
469
+
470
+ // Medidas
471
+ const padding = 15;
472
+ const gapTitulo = 8;
473
+ const gapLinea = 6;
474
+ const borderLeftWidth = 4;
475
+
476
+ // Calcular el alto necesario sin alterar doc.y ni doc.x aún
477
+ doc.fontSize(11).font(this.config.fuenteNegrita);
478
+ const tituloHeight = doc.heightOfString(titulo || '', { width: availableWidth - padding * 2 });
479
+
480
+ let contentHeight = 0;
481
+ const llaves = Object.keys(valores);
482
+
483
+ // Configurar fuente para medir contenido
484
+ doc.fontSize(this.config.fontSizeCuerpo);
485
+
486
+ llaves.forEach((llave, index) => {
487
+ const valor = valores[llave] ?? '-';
488
+ const text = `${llave}: ${valor}`;
489
+
490
+ // Se utiliza la misma fuente para calcular la altura (la negrita no suele cambiar el alto de la línea en Helvetica)
491
+ doc.font(this.config.fuenteNegrita);
492
+ const height = doc.heightOfString(text, { width: availableWidth - padding * 2 });
493
+
494
+ const margenInferior = (index === llaves.length - 1) ? 0 : gapLinea;
495
+ contentHeight += height + margenInferior;
496
+ });
497
+
498
+ const totalHeight = padding + tituloHeight + gapTitulo + contentHeight + padding;
499
+
500
+ // Revisar si cabe en la página actual
501
+ if (doc.y + totalHeight > doc.page.height - doc.page.margins.bottom - 20) {
502
+ doc.addPage();
503
+ }
504
+
505
+ const currentY = doc.y;
506
+
507
+ // Fondo contenedor (#f4f6f9)
508
+ doc.save();
509
+ doc.rect(margin, currentY, availableWidth, totalHeight).fill("#f4f6f9");
510
+ // Borde izquierdo (#002f6b)
511
+ doc.rect(margin, currentY, borderLeftWidth, totalHeight).fill("#002f6b");
512
+ doc.restore();
513
+
514
+ let textY = currentY + padding;
515
+ const textX = margin + padding;
516
+ const textWidth = availableWidth - padding * 2;
517
+
518
+ // Dibujar Título
519
+ doc.fillColor("#002f6b").fontSize(11).font(this.config.fuenteNegrita);
520
+ doc.text(titulo || '', textX, textY, { width: textWidth });
521
+ textY = doc.y + gapTitulo;
522
+
523
+ // Dibujar Valores
524
+ doc.fillColor("#444444").fontSize(this.config.fontSizeCuerpo);
525
+
526
+ llaves.forEach((llave, index) => {
527
+ const valor = valores[llave] ?? '-';
528
+
529
+ doc.font(this.config.fuenteNegrita);
530
+ doc.text(`${llave}: `, textX, textY, { continued: true, width: textWidth });
531
+
532
+ doc.font(this.config.fuenteBase);
533
+ doc.text(`${valor}`, { continued: false });
534
+
535
+ const margenInferior = (index === llaves.length - 1) ? 0 : gapLinea;
536
+ textY = doc.y + margenInferior;
537
+ });
538
+
539
+ // Mover cursor abajo dejando margen inferior
540
+ doc.y = currentY + totalHeight + 15;
541
+ }
542
+
463
543
  generarTabla(doc, datos, metadatos) {
464
544
  if (!datos || datos.length === 0) return;
465
545
 
@@ -1,29 +1,41 @@
1
- .contenedor { /* This is the outermost div in graficos.component.html */
1
+ .contenedor {
2
+ /* This is the outermost div in graficos.component.html */
2
3
  display: flex;
3
4
  flex-wrap: wrap;
4
5
  gap: 1rem;
5
6
  justify-content: center;
6
7
  width: 100%;
7
- /* Remove height: 100% from here */
8
+ height: 100%;
8
9
  }
9
10
 
10
- .grafico { /* This is the div containing the h3 and canvas */
11
+ .grafico {
12
+ /* This is the div containing the h3 and canvas */
11
13
  position: relative;
12
- width: 100%; /* Take 100% of parent's width */
13
- height: 100%; /* Allow height to stretch based on parent */
14
- max-height: 50vh; /* Further reduce max-height to 50% of viewport height for increased vertical responsiveness */
14
+ width: 100%;
15
+ /* Take 100% of parent's width */
16
+ height: 100%;
17
+ /* Allow height to stretch based on parent */
18
+ max-height: 50vh;
19
+ /* Further reduce max-height to 50% of viewport height for increased vertical responsiveness */
15
20
  padding: 0.5rem;
16
21
  box-sizing: border-box;
17
- overflow: hidden; /* Prevent content from spilling outside */
18
- }
19
-
20
- .grafico canvas {
21
- width: 100% !important;
22
- height: 100% !important;
23
- display: block; /* Remove any default inline spacing */
22
+ display: flex;
23
+ flex-direction: column;
24
24
  }
25
25
 
26
26
  h3 {
27
27
  text-align: center;
28
28
  margin-bottom: 0.5rem;
29
+ flex-shrink: 0;
30
+ }
31
+
32
+ .canvas-container {
33
+ position: relative;
34
+ flex: 1;
35
+ min-height: 0;
36
+ width: 100%;
37
+ }
38
+
39
+ .grafico canvas {
40
+ display: block;
29
41
  }
@@ -1,45 +1,42 @@
1
1
  <div class="contenedor">
2
2
 
3
3
  @if(sinDatosReales) {
4
- <div style="text-align:center; padding: 20px;">
5
- <p><b>No se encontraron datos</b></p>
6
- </div>
4
+ <div style="text-align:center; padding: 20px;">
5
+ <p><b>No se encontraron datos</b></p>
6
+ </div>
7
7
  } @else {
8
8
 
9
- @if(Datos && TipoDeGrafico==='Barras') {
10
- <div class="grafico">
11
- <h3>{{Titulo}}</h3>
12
- <canvas baseChart
13
- [data]="barChartData"
14
- [options]="barChartOptions"
15
- [type]="'bar'"
16
- [plugins]="[pluginMostrarValores]">
17
- </canvas>
18
- </div>
19
- }
9
+ @if(Datos && TipoDeGrafico==='Barras') {
10
+ <div class="grafico">
11
+ <h3>{{Titulo}}</h3>
12
+ <div class="canvas-container">
13
+ <canvas baseChart [data]="barChartData" [options]="barChartOptions" [type]="'bar'"
14
+ [plugins]="[pluginMostrarValores]">
15
+ </canvas>
16
+ </div>
17
+ </div>
18
+ }
20
19
 
21
- @if(Datos && TipoDeGrafico==='Pie') {
22
- <div class="grafico">
23
- <h3>{{Titulo}}</h3>
24
- <canvas baseChart
25
- [data]="pieChartData"
26
- [options]="pieChartOptions"
27
- [type]="'pie'">
28
- </canvas>
29
- </div>
30
- }
20
+ @if(Datos && TipoDeGrafico==='Pie') {
21
+ <div class="grafico">
22
+ <h3>{{Titulo}}</h3>
23
+ <div class="canvas-container">
24
+ <canvas baseChart [data]="pieChartData" [options]="pieChartOptions" [type]="'pie'">
25
+ </canvas>
26
+ </div>
27
+ </div>
28
+ }
31
29
 
32
- @if(Datos && TipoDeGrafico==='Línea') {
33
- <div class="grafico">
34
- <h3>{{Titulo}}</h3>
35
- <canvas baseChart
36
- [data]="lineChartData"
37
- [options]="lineChartOptions"
38
- [type]="'line'">
39
- </canvas>
40
- </div>
41
- }
30
+ @if(Datos && TipoDeGrafico==='Línea') {
31
+ <div class="grafico">
32
+ <h3>{{Titulo}}</h3>
33
+ <div class="canvas-container">
34
+ <canvas baseChart [data]="lineChartData" [options]="lineChartOptions" [type]="'line'">
35
+ </canvas>
36
+ </div>
37
+ </div>
38
+ }
42
39
 
43
40
  }
44
41
 
45
- </div>
42
+ </div>
@@ -83,7 +83,12 @@ export class GraficosComponent {
83
83
  // =========================
84
84
  public pieChartOptions: ChartConfiguration<'pie'>['options'] = {
85
85
  responsive: true,
86
- maintainAspectRatio: false
86
+ maintainAspectRatio: false,
87
+ layout: {
88
+ padding: {
89
+ bottom: 20
90
+ }
91
+ }
87
92
  };
88
93
 
89
94
  public pieChartData: ChartData<'pie', number[], string | string[]> = {
@@ -7,10 +7,10 @@
7
7
  width: 100%;
8
8
  }
9
9
 
10
- /* Forzamos 4 columnas calculando el espacio disponible */
10
+ /* Pantallas grandes: se adaptan dinámicamente, máximo 300px, caben tantas como sea posible */
11
11
  .contenido>div[cdkDrag] {
12
- width: calc(25% - 12px);
13
- /* 25% menos una parte del gap (16px * 3 / 4) */
12
+ flex: 1 1 300px;
13
+ max-width: 300px;
14
14
  box-sizing: border-box;
15
15
  }
16
16
 
@@ -43,12 +43,16 @@
43
43
  /* Responsividad: 2 columnas en tablets, 1 en móviles */
44
44
  @media (max-width: 1200px) {
45
45
  .contenido>div[cdkDrag] {
46
+ flex: none;
47
+ max-width: none;
46
48
  width: calc(50% - 8px);
47
49
  }
48
50
  }
49
51
 
50
52
  @media (max-width: 600px) {
51
53
  .contenido>div[cdkDrag] {
54
+ flex: none;
55
+ max-width: none;
52
56
  width: 100%;
53
57
  }
54
58
  }
@@ -7,6 +7,8 @@ import { TarjetaPersonalizadaComponent } from "../../Componentes/Nucleo/tarjeta-
7
7
  import { HttpClient } from "@angular/common/http";
8
8
  import { DatosGlobalesService } from '../../datos-globales.service';
9
9
  import { DragDropModule, CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
10
+ import { forkJoin, of } from 'rxjs';
11
+ import { catchError } from 'rxjs/operators';
10
12
 
11
13
  interface BaseTarjetaConfig {
12
14
  type: 'single' | 'multiple' | 'report' | 'custom';
@@ -195,31 +197,63 @@ export class ContenedorPrincipalComponent implements OnInit {
195
197
  }
196
198
  ];
197
199
 
198
- // // 2. Check for extra permissions (Personas card)
199
- // this.http.get(`${this.datosGlobalesService.ObtenerURL()}Personas/PermisoExtra`).subscribe({
200
- // next: (datos: any) => {
201
- // if (datos.body) {
202
- // const personasCard: TarjetaMultipleConfig = {
203
- // type: 'multiple',
204
- // position: 25,
205
- // titulo: 'Personas',
206
- // descripcion: 'Módulo para el mantenimiento de los datos relacionados con personas',
207
- // rutas: [
208
- // { nombre: 'Personas', ruta: 'tablaPersonas' },
209
- // { nombre: 'Correos', ruta: 'tablaCorreosPersonas' },
210
- // { nombre: 'Cuentas bancarias', ruta: 'tablaCuentasPersonas' },
211
- // { nombre: 'Teléfonos', ruta: 'tablaTelefonosPersonas' },
212
- // { nombre: 'Ubicación', ruta: 'tablaUbicacionPersona' },
213
- // ]
214
- // };
215
- // baseTarjetas.push(personasCard);
216
- // }
217
- // },
218
- // error: (error) => {
219
- // console.error('Problemas al intentar obtener los datos: ', error);
220
- // this.tarjetas = baseTarjetas.sort((a, b) => a.position - b.position);
221
- // },
222
- // });
200
+ forkJoin({
201
+ permisoExtra: this.http.get(`${this.datosGlobalesService.ObtenerURL()}Personas/PermisoExtra`).pipe(
202
+ catchError(error => {
203
+ console.error('Problemas al intentar obtener los datos de PermisoExtra: ', error);
204
+ return of({ body: null });
205
+ })
206
+ ),
207
+ // configuracion: this.http.get(`${this.datosGlobalesService.ObtenerURL()}ConfiguracionDeTarjetas/obtener`).pipe(
208
+ // catchError(error => {
209
+ // console.error('Error al obtener configuración de tarjetas:', error);
210
+ // return of({ body: [] });
211
+ // })
212
+ // )
213
+ }).subscribe({
214
+ next: (results: any) => {
215
+ // // 2. Handle extra permissions
216
+ // if (results.permisoExtra && results.permisoExtra.body) {
217
+ // const personasCard: TarjetaMultipleConfig = {
218
+ // type: 'multiple',
219
+ // position: 25,
220
+ // titulo: 'Personas',
221
+ // descripcion: 'Módulo para el mantenimiento de los datos relacionados con personas',
222
+ // rutas: [
223
+ // { nombre: 'Personas', ruta: 'tablaPersonas' },
224
+ // { nombre: 'Correos', ruta: 'tablaCorreosPersonas' },
225
+ // { nombre: 'Cuentas bancarias', ruta: 'tablaCuentasPersonas' },
226
+ // { nombre: 'Teléfonos', ruta: 'tablaTelefonosPersonas' },
227
+ // { nombre: 'Ubicación', ruta: 'tablaUbicacionPersona' },
228
+ // ]
229
+ // };
230
+ // if (!baseTarjetas.find(t => t.titulo === 'Personas')) {
231
+ // baseTarjetas.push(personasCard);
232
+ // }
233
+ // }
234
+
235
+ // 3. Apply saved configurations
236
+ if (results.configuracion && results.configuracion.body && results.configuracion.body.length > 0) {
237
+ const savedConfigs = results.configuracion.body;
238
+ baseTarjetas.forEach(tarjeta => {
239
+ const config = savedConfigs.find((c: any) => c.Titulo === tarjeta.titulo);
240
+ if (config) {
241
+ tarjeta.position = config.Posicion;
242
+ if (config.ColorDeBorde) {
243
+ tarjeta.ColorDeBorde = config.ColorDeBorde;
244
+ }
245
+ }
246
+ });
247
+ }
248
+ this.tarjetas = baseTarjetas.sort((a, b) => a.position - b.position);
249
+ },
250
+ error: (error) => {
251
+ console.error('Error crítico en el proceso de inicialización:', error);
252
+ this.tarjetas = baseTarjetas.sort((a, b) => a.position - b.position);
253
+ }
254
+ });
255
+ }
256
+
223
257
  // 3. Load user-specific positions from backend
224
258
  this.http.get(`${this.datosGlobalesService.ObtenerURL()}ConfiguracionDeTarjetas/obtener`).subscribe({
225
259
  next: (res: any) => {
@@ -7,10 +7,10 @@
7
7
  width: 100%;
8
8
  }
9
9
 
10
- /* Forzamos 4 columnas calculando el espacio disponible */
10
+ /* Pantallas grandes: se adaptan dinámicamente, máximo 300px, caben tantas como sea posible */
11
11
  .contenido>* {
12
- width: calc(25% - 12px);
13
- /* 25% menos una parte del gap (16px * 3 / 4) */
12
+ flex: 1 1 300px;
13
+ max-width: 300px;
14
14
  box-sizing: border-box;
15
15
  }
16
16
 
@@ -43,12 +43,16 @@
43
43
  /* Responsividad: 2 columnas en tablets, 1 en móviles */
44
44
  @media (max-width: 1200px) {
45
45
  .contenido>* {
46
+ flex: none;
47
+ max-width: none;
46
48
  width: calc(50% - 8px);
47
49
  }
48
50
  }
49
51
 
50
52
  @media (max-width: 600px) {
51
53
  .contenido>* {
54
+ flex: none;
55
+ max-width: none;
52
56
  width: 100%;
53
57
  }
54
58
  }
@@ -4,10 +4,53 @@
4
4
  left: 0;
5
5
  width: 100%;
6
6
  height: 100%;
7
- background: rgba(255,255,255,0.8);
7
+ background: rgba(255, 255, 255, 0.8);
8
8
  display: flex;
9
9
  flex-direction: column;
10
10
  justify-content: center;
11
11
  align-items: center;
12
12
  z-index: 2000;
13
13
  }
14
+
15
+ .contenedor {
16
+ display: flex;
17
+ flex-direction: column;
18
+ height: calc(100vh - 64px);
19
+ overflow: hidden;
20
+ padding: 0;
21
+ box-sizing: border-box;
22
+ }
23
+
24
+ .grid-graficos {
25
+ display: flex;
26
+ flex-direction: column;
27
+ flex: 1;
28
+ justify-content: flex-start;
29
+ align-items: center;
30
+ padding: 1rem 2rem 2rem 2rem;
31
+ box-sizing: border-box;
32
+ width: 100%;
33
+ gap: 3rem;
34
+ min-height: 0;
35
+ overflow-y: auto;
36
+ }
37
+
38
+ .grid-graficos app-graficos {
39
+ width: 100%;
40
+ max-width: 800px;
41
+ height: 400px;
42
+ flex-shrink: 0;
43
+ display: flex;
44
+ flex-direction: column;
45
+ }
46
+
47
+ @media (max-width: 768px) {
48
+ .contenedor {
49
+ height: 100vh;
50
+ }
51
+
52
+ .grid-graficos {
53
+ padding: 1rem;
54
+ gap: 2rem;
55
+ }
56
+ }
@@ -1,4 +1,4 @@
1
- <div>
1
+ <div class="contenedor">
2
2
  <!-- <h3>Gráficos sobre módulos del SIGU</h3> -->
3
3
  @if(cargando) {
4
4
  <div class="cargando-overlay">
@@ -6,8 +6,10 @@
6
6
  <p>Procesando, por favor espere...</p>
7
7
  </div>
8
8
  } @else {
9
- <app-graficos [TipoDeGrafico]="'Pie'" [Datos]="datosParaElGraficoPie" [Titulo]="'Módulos desarrollados en SIGU'" />
10
- <app-graficos [TipoDeGrafico]="'Barras'" [Datos]="datosParaElGraficoBarras"
11
- [Titulo]="'Total de nacimientos por mes'" />
9
+ <div class="grid-graficos">
10
+ <app-graficos [TipoDeGrafico]="'Pie'" [Datos]="datosParaElGraficoPie" [Titulo]="'Módulos desarrollados en SIGU'" />
11
+ <app-graficos [TipoDeGrafico]="'Barras'" [Datos]="datosParaElGraficoBarras"
12
+ [Titulo]="'Total de nacimientos por mes'" />
13
+ </div>
12
14
  }
13
15
  </div>