> For the complete documentation index, see [llms.txt](https://elguerre.gitbook.io/de0an/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://elguerre.gitbook.io/de0an/capitulo-11-backstage-y-un-futuro-prometedor/funcionalidad-core-con-ia.md).

# Funcionalidad Core con IA

El capítulo 8 fue el más denso del libro. Allí construimos el corazón de Task\[in]: las pantallas de Proyectos, Tareas, Pomodoros y Checklist. Cada entidad con su listado, su detalle, su edición. Acciones, comportamientos, navegación entre pantallas... fue un capítulo que puso a prueba todo lo aprendido.

Hoy, construir esa misma funcionalidad con Angular y asistencia de IA es una experiencia radicalmente diferente.

## Formularios reactivos en Angular

Uno de los cambios más significativos respecto a UWP es el sistema de formularios. Donde antes teníamos bindings bidireccionales en XAML con propiedades en el ViewModel, Angular ofrece **Reactive Forms**: formularios tipados, validados y testeable de forma nativa:

```typescript
@Component({
  selector: "app-tarea-form",
  template: `
    <form [formGroup]="form" (ngSubmit)="guardar()">
      <mat-form-field>
        <mat-label>Título</mat-label>
        <input matInput formControlName="titulo" />
        @if (form.controls.titulo.hasError("required")) {
          <mat-error>El título es obligatorio</mat-error>
        }
      </mat-form-field>

      <mat-form-field>
        <mat-label>Prioridad</mat-label>
        <mat-select formControlName="prioridad">
          <mat-option value="alta">Alta</mat-option>
          <mat-option value="media">Media</mat-option>
          <mat-option value="baja">Baja</mat-option>
        </mat-select>
      </mat-form-field>

      <button mat-raised-button type="submit" [disabled]="form.invalid">
        Guardar
      </button>
    </form>
  `,
})
export class TareaFormComponent {
  private fb = inject(FormBuilder);

  form = this.fb.group({
    titulo: ["", Validators.required],
    descripcion: [""],
    prioridad: ["media", Validators.required],
    fechaLimite: [null as Date | null],
  });

  guardar() {
    if (this.form.valid) {
      const tarea = this.form.getRawValue();
      // Enviar al servicio...
    }
  }
}
```

Las validaciones, el estado del formulario (dirty, touched, valid) y la comunicación con el backend se gestionan de forma declarativa y predecible.

## Signals para el estado de la aplicación

En el capítulo 8, el estado de la aplicación (la lista de proyectos, las tareas del proyecto seleccionado, los pomodoros activos) se gestionaba a través de propiedades observables en los ViewModels. Con Angular Signals, esta gestión se simplifica:

```typescript
@Injectable({ providedIn: "root" })
export class TareasService {
  private http = inject(HttpClient);

  tareas = signal<Tarea[]>([]);
  tareaSeleccionada = signal<Tarea | null>(null);

  tareasActivas = computed(() => this.tareas().filter((t) => !t.completada));

  contadorPendientes = computed(() => this.tareasActivas().length);

  async cargar(proyectoId: number) {
    const resultado = await firstValueFrom(
      this.http.get<Tarea[]>(`/api/proyectos/${proyectoId}/tareas`),
    );
    this.tareas.set(resultado);
  }

  async completar(id: number) {
    await firstValueFrom(
      this.http.patch(`/api/tareas/${id}`, { completada: true }),
    );
    this.tareas.update((tareas) =>
      tareas.map((t) => (t.id === id ? { ...t, completada: true } : t)),
    );
  }
}
```

`signal`, `computed` y `effect` son las tres primitivas que reemplazan gran parte de la complejidad de RxJS para la gestión de estado. Más simple, más predecible, y sin riesgo de olvidar un `unsubscribe`.

## IA para el scaffolding de CRUD

Aquí es donde la IA brilla de forma especial. La generación de código CRUD (Create, Read, Update, Delete) es una de las tareas más repetitivas del desarrollo, y la IA la acelera enormemente:

```
> Genera un CRUD completo para la entidad Proyecto: servicio Angular
  con signals, componentes de lista y detalle con Material,
  y los endpoints Minimal API correspondientes en .NET.
```

La IA genera el servicio, los componentes, los endpoints, e incluso los DTOs y las validaciones básicas. Tú revisas, ajustas lo que sea necesario y añades la lógica de negocio específica.

## El Pomodoro: de temporizador UWP a timer web

El temporizador de Pomodoro del capítulo 8 usaba `DispatcherTimer` de UWP. En Angular, un temporizador se implementa con Signals y `setInterval` o, mejor aún, con RxJS:

```typescript
export class PomodoroTimerComponent {
  private readonly DURACION = 25 * 60; // 25 minutos en segundos

  segundosRestantes = signal(this.DURACION);
  activo = signal(false);

  minutos = computed(() => Math.floor(this.segundosRestantes() / 60));
  segundos = computed(() => this.segundosRestantes() % 60);

  private intervalId: number | null = null;

  iniciar() {
    this.activo.set(true);
    this.intervalId = window.setInterval(() => {
      this.segundosRestantes.update((s) => {
        if (s <= 0) {
          this.pausar();
          this.notificar();
          return 0;
        }
        return s - 1;
      });
    }, 1000);
  }

  pausar() {
    this.activo.set(false);
    if (this.intervalId) {
      clearInterval(this.intervalId);
      this.intervalId = null;
    }
  }

  reiniciar() {
    this.pausar();
    this.segundosRestantes.set(this.DURACION);
  }

  private notificar() {
    if ("Notification" in window && Notification.permission === "granted") {
      new Notification("Pomodoro completado", {
        body: "Es momento de tomar un descanso.",
      });
    }
  }
}
```

La notificación al completar el Pomodoro usa la Web Notifications API, el equivalente web de las notificaciones Toast que implementamos en UWP.

## La lección que permanece

La funcionalidad core de una aplicación es donde se demuestra la calidad del software. Da igual cuántas pantallas bonitas tengas si la creación de una tarea falla, si el temporizador no es preciso o si los datos se pierden. La IA puede generar el esqueleto del código, pero la lógica de negocio — las reglas que hacen que tu aplicación sea *tu aplicación* — requiere tu atención y tu criterio. Como dijimos en el capítulo 8: *"La sencillez y agilidad entre el usuario y la aplicación han de ser lo más natural posible"*.
