Explorar o código

subo modal para indetidicador de campo y diseño del pdf casi listo

FREDY hai 3 meses
pai
achega
f15faba4f7

+ 36 - 18
Back/backendP-Educativa/resources/views/respuesta.blade.php

@@ -4,11 +4,19 @@
     <meta charset="utf-8">
     <title>Respuesta del Usuario</title>
     <style>
+        @page {
+            margin: 80px 40px;
+        }
+
         body {
             font-family: 'Segoe UI', sans-serif;
             font-size: 13px;
-            margin: 40px;
             color: #2c3e50;
+            margin: 0;
+        }
+
+        main {
+            padding: 40px 0;
         }
 
         h1 {
@@ -21,7 +29,7 @@
         }
 
         h2 {
-            margin-top: 40px;
+            margin-top: 30px;
             font-size: 16px;
             color: #2c3e50;
             border-bottom: 2px solid #3498db;
@@ -38,32 +46,42 @@
             font-weight: bold;
         }
 
-        .footer {
-            margin-top: 60px;
+        footer {
+            position: fixed;
+            bottom: -40px;
+            left: 0;
+            right: 0;
+            height: 30px;
             font-size: 11px;
-            text-align: center;
             color: #999;
+            text-align: center;
+        }
+
+        h2, .campo {
+            page-break-inside: avoid;
         }
     </style>
 </head>
 <body>
 
-    <h1>Formulario contestado por el usuario: {{ $usuario }}</h1>
-    <p><strong>Fecha de respuesta:</strong> {{ \Carbon\Carbon::parse($fecha)->format('d/m/Y H:i') }}</p>
+    <footer>
+        Documento generado automáticamente. Plataforma educativa - {{ date('Y') }}.
+    </footer>
+
+    <main>
+        <h1>Formulario contestado por el usuario: {{ $usuario }}</h1>
+        <p><strong>Fecha de respuesta:</strong> {{ \Carbon\Carbon::parse($fecha)->format('d/m/Y H:i') }}</p>
 
-    @foreach ($respuesta as $titulo => $campos)
-        <h2>{{ $titulo }}</h2>
+        @foreach ($respuesta as $titulo => $campos)
+            <h2>{{ $titulo }}</h2>
 
-        @foreach ($campos as $clave => $valor)
-            <div class="campo">
-                <span>{{ $clave }}:</span> {{ $valor }}
-            </div>
+            @foreach ($campos as $clave => $valor)
+                <div class="campo">
+                    <span>{{ $clave }}:</span> {{ $valor }}
+                </div>
+            @endforeach
         @endforeach
-    @endforeach
-
-    <div class="footer">
-        Documento generado automáticamente. Plataforma educativa - {{ date('Y') }}.
-    </div>
+    </main>
 
 </body>
 </html>

+ 76 - 0
Front/src/app/modules/Administrador/pages/admin-form/admin-form.component.css

@@ -24,6 +24,82 @@
   padding: 20px;
   height: calc(100vh - 120px);
 }
+/* CSS */
+.modal {
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: 999;
+  width: 100vw;
+  height: 100vh;
+  background: rgba(0,0,0,0.5);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.modal-content {
+  background: #fff;
+  padding: 20px 30px;
+  border-radius: 10px;
+  width: 300px;
+  max-width: 90%;
+  text-align: center;
+  box-shadow: 0 5px 15px rgba(0,0,0,0.3);
+}
+
+.modal-content input {
+  width: 100%;
+  padding: 10px;
+  margin-top: 10px;
+  border-radius: 6px;
+  border: 1px solid #ccc;
+}
+
+.modal-actions {
+  margin-top: 15px;
+  display: flex;
+  justify-content: space-between;
+}
+
+.modal-actions button {
+  padding: 6px 12px;
+  border: none;
+  background-color: #007bff;
+  color: white;
+  border-radius: 6px;
+  cursor: pointer;
+}
+
+.modal-actions button:last-child {
+  background-color: #6c757d;
+}
+
+.error {
+  color: red;
+  font-size: 0.85em;
+  margin-top: 5px;
+}
+
+
+.buttons {
+  display: flex;
+  justify-content: space-between;
+}
+
+button {
+  padding: 6px 12px;
+  border: none;
+  border-radius: 6px;
+  background-color: #007bff;
+  color: white;
+  cursor: pointer;
+}
+
+button:hover {
+  background-color: #0056b3;
+}
+
 
 /* Paneles */
 .container-formConfig,

+ 26 - 9
Front/src/app/modules/Administrador/pages/admin-form/admin-form.component.html

@@ -3,6 +3,22 @@
     <p class="content" [style.color]="textColor">Creación de formularios</p>
   </div>
 </div>
+<!-- HTML -->
+<!-- Modal para ingresar el identificador -->
+<div class="modal" *ngIf="showModalIdentificador">
+  <div class="modal-content">
+    <h3>Identificador del Campo</h3>
+    <input [formControl]="nombreIdentificadorControl" placeholder="Ej. nombre_alumno">
+    <div *ngIf="nombreIdentificadorControl.invalid && nombreIdentificadorControl.touched" class="error">
+      Ingresa un identificador válido (letras, números y guiones bajos).
+    </div>
+    <div class="modal-actions">
+      <button (click)="confirmarIdentificador()">Aceptar</button>
+      <button (click)="showModalIdentificador = false">Cancelar</button>
+    </div>
+  </div>
+</div>
+
 
 <div class="container-main" [formGroup]="form">
 
@@ -26,14 +42,14 @@
       (tabDimensionsChange)="onTabDimensionsChange($event)">
     </app-configuration-panel>
     <!-- Selector de tipos de campo -->
-    <div *ngIf="showElementSelector && selectedCell" class="selector">
-      <p>Selecciona un tipo de campo para agregar en posición {{ selectedCell.row + 1 }}, {{ selectedCell.col + 1 }} - {{ currentTab?.name }}</p>
-      <div class="element-buttons">
-        <button *ngFor="let el of availableElements" (click)="addElementToCell(el)">
-          {{ el.label }}
-        </button>
-      </div>
-    </div>
+  <div *ngIf="showElementSelector && selectedCell" class="selector">
+  <p>Selecciona un tipo de campo para agregar en posición {{ selectedCell.row + 1 }}, {{ selectedCell.col + 1 }} - {{ currentTab?.name }}</p>
+  <div class="element-buttons">
+    <button *ngFor="let el of availableElements" (click)="addElementToCell(el)" [style.background-color]="color">
+      <p [style.color]="textColor">{{ el.label }}</p>
+    </button>
+  </div>
+</div>
   </div>
 
   <!-- Contenedor principal con panel izquierdo y formulario -->
@@ -63,7 +79,8 @@
 
             <button *ngIf="tabs.length > 1"
                     class="tab-close-btn"
-                    (click)="removeTab(); $event.stopPropagation()">
+                    (click)="removeTab(); $event.stopPropagation()"
+                 >
               &times;
             </button>
           </div>

+ 80 - 26
Front/src/app/modules/Administrador/pages/admin-form/admin-form.component.ts

@@ -3,7 +3,7 @@ import { Component, OnInit } from '@angular/core';
 import { EnviarInfoService } from '../../services/enviar-info.service';
 import { FormService } from '../../services/FormService.service';
 import { ActivatedRoute, Router } from '@angular/router';
-import { FormArray } from '@angular/forms';
+import { FormArray, Validators } from '@angular/forms';
 import { FormBuilder, FormGroup, FormControl } from '@angular/forms';
 
 //aqui es para agregar popiedades a las celdas que se generan el el build grid
@@ -176,6 +176,15 @@ export class AdminFormComponent implements OnInit {
   ];
   formData: any;
   form: any;
+  // Dentro del AdminFormComponent (fuera de métodos)
+
+showModalIdentificador = false;
+nombreIdentificadorControl = new FormControl('', [
+  Validators.required,
+  Validators.pattern('^[a-zA-Z_][a-zA-Z0-9_]*$')
+]);
+pendingTemplate: FormElement | null = null;
+
 
 constructor(
   private _enviarInfo: EnviarInfoService,
@@ -562,30 +571,20 @@ getSafeControlName(cell: any, rowIndex: number, colIndex: number): string {
     this.editingElement = null;
   }
 
-
-addElementToCell(template: FormElement) {
-  if (!this.selectedCell || this.selectedCell.element) {
-    alert('Esta celda ya tiene un campo. Elimínalo primero.');
-    return;
-  }
-
-  // Solicita un "nombre clave" legible para el input, ejemplo: "nombre_alumno"
-  let nombreClave = prompt('Ingresa el identificador único para este campo (ej. nombre_alumno):');
-  if (!nombreClave) {
-    alert('Debes ingresar un identificador válido.');
+confirmarIdentificador() {
+  if (this.nombreIdentificadorControl.invalid || !this.pendingTemplate) {
+    this.nombreIdentificadorControl.markAsTouched();
     return;
   }
 
-  // Limpia espacios y pasa a minúsculas para usar como key
-  nombreClave = nombreClave.trim().toLowerCase().replace(/\s+/g, '_');
-
-  const element = { ...template };
+  const nombreClave = this.nombreIdentificadorControl.value!.trim().toLowerCase().replace(/\s+/g, '_');
+  const element = { ...this.pendingTemplate };
 
   element.id = `${this.currentTab?.id}_${nombreClave}`;
-  element.name = nombreClave;          // <--- Aquí asignamos el key legible
-  element.label = this.capitalizeWords(nombreClave.replace(/_/g, ' ')); // etiqueta legible: "Nombre Alumno"
+  element.name = nombreClave;
+  element.label = this.capitalizeWords(nombreClave.replace(/_/g, ' '));
 
-  // Aplica validaciones según tipo, igual que antes
+  // Validaciones según tipo
   switch (element.type) {
     case 'email':
       Object.assign(element, {
@@ -598,19 +597,74 @@ addElementToCell(template: FormElement) {
       Object.assign(element, { required: true, min: 1, max: 100 });
       break;
     case 'text':
-    element.required = true;
-  element.min = element.min ?? 1;
-  element.max = element.max ?? 20;
-  if (!element.pattern) {
-    element.pattern = '^\\b(\\w+\\b\\s*){1,20}$';
-  }
+      element.required = true;
+      element.min = element.min ?? 1;
+      element.max = element.max ?? 20;
+      if (!element.pattern) {
+        element.pattern = '^\\b(\\w+\\b\\s*){1,20}$';
+      }
       break;
   }
 
-  this.selectedCell.element = element;
+  this.selectedCell!.element = element;
   this.editingElement = element;
   this.showElementSelector = false;
   this.updateCurrentTabGrid();
+  this.showModalIdentificador = false;
+  this.pendingTemplate = null;
+}
+
+addElementToCell(template: FormElement) {
+  if (!this.selectedCell || this.selectedCell.element) {
+    alert('Esta celda ya tiene un campo. Elimínalo primero.');
+    return;
+  }
+  this.pendingTemplate = template;
+  this.nombreIdentificadorControl.reset();
+  this.showModalIdentificador = true; // abre modal
+
+  // // Solicita un "nombre clave" legible para el input, ejemplo: "nombre_alumno"
+  // let nombreClave = prompt('Ingresa el identificador único para este campo (ej. nombre_alumno):');
+  // if (!nombreClave) {
+  //   alert('Debes ingresar un identificador válido.');
+  //   return;
+  // }
+
+  // // Limpia espacios y pasa a minúsculas para usar como key
+  // nombreClave = nombreClave.trim().toLowerCase().replace(/\s+/g, '_');
+
+  // const element = { ...template };
+
+  // element.id = `${this.currentTab?.id}_${nombreClave}`;
+  // element.name = nombreClave;          // <--- Aquí asignamos el key legible
+  // element.label = this.capitalizeWords(nombreClave.replace(/_/g, ' ')); // etiqueta legible: "Nombre Alumno"
+
+  // Aplica validaciones según tipo, igual que antes
+  // switch (element.type) {
+  //   case 'email':
+  //     Object.assign(element, {
+  //       required: true,
+  //       pattern: '^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$',
+  //       placeholder: 'ejemplo@correo.com'
+  //     });
+  //     break;
+  //   case 'number':
+  //     Object.assign(element, { required: true, min: 1, max: 100 });
+  //     break;
+  //   case 'text':
+  //   element.required = true;
+  // element.min = element.min ?? 1;
+  // element.max = element.max ?? 20;
+  // if (!element.pattern) {
+  //   element.pattern = '^\\b(\\w+\\b\\s*){1,20}$';
+  // }
+  //     break;
+  // }
+
+  // this.selectedCell.element = element;
+  // this.editingElement = element;
+  this.showElementSelector = false;
+  this.updateCurrentTabGrid();
 }
 getControlName(tab: Tab | null, cell: any): string {
   const row = cell.row ?? 0;

+ 1 - 1
Front/src/app/modules/Administrador/pages/admin-form/configuration-panel/configuration-panel.component.css

@@ -87,7 +87,7 @@
 
 /* Botón de ayuda "?" */
 .help-btn {
-  background: #007bff;
+  background: #f19696;
   border: none;
   border-radius: 50%;
   width: 22px;

+ 5 - 5
Front/src/app/modules/Administrador/pages/admin-form/configuration-panel/configuration-panel.component.html

@@ -4,8 +4,8 @@
 <div class="config-section">
   <div class="input-with-help">
     <p class="text">Título del formulario</p>
-    <button class="help-btn" (click)="showHelp('formTitle')">
-      <i class="help-icon">?</i>
+    <button  class="help-btn" (click)="showHelp('formTitle')">
+      <i class="help-icon" >?</i>
     </button>
   </div>
   <div class="help-tooltip" *ngIf="showTooltip === 'formTitle'">
@@ -77,15 +77,15 @@
   </div>
 
   <div class="tab-actions">
-    <button mat-button class="example-tab-button" (click)="addTab()">Agregar nueva sección</button>
-    <button mat-button class="example-tab-button" [disabled]="tabs.length === 1" (click)="removeTab(tabs.length - 1)">Eliminar última sección</button>
+    <button mat-button class="example-tab-button" (click)="addTab() " style="background-color: #34A208;"><p [style.color]="textColor">Agregar nueva sección</p></button>
+    <button mat-button class="example-tab-button" [disabled]="tabs.length === 1" (click)="removeTab(tabs.length - 1)" style="background-color: red;"><p [style.color]="textColor">Eliminar última sección</p></button>
   </div>
 </div>
 
 <!-- Generar Configuración del Formulario -->
 <div class="config-section">
   <div class="input-with-help">
-    <button class="btn-generate" (click)="generateConfiguration()">Generar Configuración del Formulario</button>
+    <button class="btn-generate" (click)="generateConfiguration()" [style.background-color]="color"><p [style.color]="textColor">Generar Configuración del Formulario</p></button>
     <button class="help-btn" (click)="showHelp('generateJson')">
       <i class="help-icon">?</i>
     </button>

+ 14 - 2
Front/src/app/modules/Administrador/pages/admin-form/configuration-panel/configuration-panel.component.ts

@@ -1,4 +1,5 @@
-import { Component, Input, Output, EventEmitter } from '@angular/core';
+import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
+import { EnviarInfoService } from '../../../services/enviar-info.service';
 
 interface Tab {
   id: string;
@@ -14,7 +15,10 @@ interface Tab {
   templateUrl: './configuration-panel.component.html',
   styleUrls: ['./configuration-panel.component.css']
 })
-export class ConfigurationPanelComponent {
+export class ConfigurationPanelComponent  implements OnInit {
+   color: string = '';
+  textColor: string = '';
+
   @Input() formTitle = '';
   @Input() rows = 3;
   @Input() columns = 3;
@@ -32,10 +36,18 @@ export class ConfigurationPanelComponent {
   @Output() gridConfigChange = new EventEmitter<void>();
   @Output() tabDimensionsChange = new EventEmitter<{ tab: Tab, rows: number, columns: number }>();
 
+constructor(
+  private _enviarInfo: EnviarInfoService,
+) {}
+   ngOnInit(): void {
+     this._enviarInfo.currentTextColor.subscribe(color => this.textColor = color);
+    this._enviarInfo.currentColor.subscribe(color => this.color = color);
+  }
   showHelp(field: string) {
     this.showTooltipChange.emit(this.showTooltip === field ? '' : field);
   }
 
+
  onRowsChange(value: number) {
   const validValue = this.validateMin(value);
   this.rowsChange.emit(validValue);

+ 4 - 0
Front/src/app/modules/Administrador/pages/admin-form/form-selector/form-selector.component.css

@@ -6,3 +6,7 @@
 .table-container{
   width: 97%;
 }
+.principal{
+  margin-left: 15px !important;
+  background-color: aqua;
+}

+ 4 - 1
Front/src/app/modules/Administrador/pages/admin-form/form-selector/form-selector.component.html

@@ -3,6 +3,7 @@
     <p class="content" [style.color]="'white'">Publicar formularios</p>
   </div>
 </div>
+<div clas="principal">
 
 <div class="container-col fadeIn">
   <div class="flex-row container-search">
@@ -61,7 +62,7 @@
 <button *ngIf="form.is_published" mat-button color="warn"
         (click)="despublicarFormulario(form.id)"
         [disabled]="isLoading">
-  <mat-icon>cancel</mat-icon> Despublicar
+  <mat-icon>cancel</mat-icon> bajar publicación
 </button>
 
   </td>
@@ -93,3 +94,5 @@
   </div>
 
 
+</div>
+</div>

+ 4 - 2
Front/src/app/modules/Padres/pages/formularios/formularios.component.html

@@ -83,8 +83,10 @@
     </mat-tab-group>
 
     <div class="button-container" style="margin-top: 16px;">
-      <button type="submit" [disabled]="form.invalid" class="submit-button mat-raised-button mat-primary">
-        Enviar
+      <button type="submit" [disabled]="form.invalid" class="submit-button mat-raised-button mat-primary"
+       [style.background-color]="color" >
+
+       <p  [style.color]="textColor" >Enviar</p>
       </button>
     </div>