Saltar al contenido principal
Esta guía detalla cómo integrar SofIA SDK en aplicaciones Angular, incluyendo la configuración necesaria para el uso de Web Components y la implementación de callbacks.

Configuración inicial

1. Instalación del paquete

npm install @omniloy/sofia-sdk

2. Configuración del módulo

Angular requiere configuración específica para soportar Web Components:
// app.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

// Importar SofIA SDK
import '@omniloy/sofia-sdk';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA] // Requerido para Web Components
})
export class AppModule { }

3. Configuración en Standalone Components (Angular 14+)

Para aplicaciones que usan Standalone Components:
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import '@omniloy/sofia-sdk';

bootstrapApplication(AppComponent, {
  providers: []
});
// app.component.ts
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  templateUrl: './app.component.html',
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppComponent {
  // Implementación del componente
}

Implementación del componente

Template HTML

<!-- app.component.html -->
<sofia-sdk
  baseurl="https://api.omniloy.com"
  wssurl="wss://wss.omniloy.com"
  apikey="PROD_KEY"
  [attr.userid]="userId"
  [attr.patientid]="patientId"
  [attr.toolsargs]="toolsArgsJson"
  [attr.isopen]="isOpen ? 'true' : 'false'"
  (handle-report)="onReport($event.detail)"
  (set-is-open)="onSetIsOpen($event.detail)">
</sofia-sdk>

Componente TypeScript

// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  userId = 'angular-user-123';
  patientId = 'patient-456';
  isOpen = false;
  
  // Esquema JSON para configuración clínica
  toolsArgsJson = JSON.stringify({
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "Consulta médica",
    "type": "object",
    "properties": {
      "diagnostico": {
        "type": "string",
        "description": "Diagnóstico principal"
      },
      "tratamiento": {
        "type": "string",
        "description": "Plan de tratamiento"
      }
    },
    "required": ["diagnostico"]
  });

  // Callback cuando se genera un reporte
  onReport(report: any) {
    console.log('Reporte recibido:', report);
    // Aquí puedes procesar el reporte generado
    // Por ejemplo, enviarlo a tu backend o EHR
  }

  // Callback cuando se cambia el estado de apertura
  onSetIsOpen(isOpen: boolean) {
    this.isOpen = isOpen;
    console.log('Estado de apertura:', isOpen);
  }

  // Método para abrir/cerrar programáticamente
  toggleSofIA() {
    this.isOpen = !this.isOpen;
  }
}

Configuración avanzada

Interfaces TypeScript

Para mejor tipado, puede definir interfaces para los datos:
// interfaces/sofia.interface.ts
export interface SofiaReport {
  diagnostico: string;
  tratamiento?: string;
  timestamp: string;
  userId: string;
  patientId: string;
}

export interface PatientData {
  nombre: string;
  edad: number;
  sexo: 'M' | 'F';
  historial?: string;
}

Servicio Angular

Puede encapsular la lógica de SofIA en un servicio:
// services/sofia.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { SofiaReport } from '../interfaces/sofia.interface';

@Injectable({
  providedIn: 'root'
})
export class SofiaService {
  private reportSubject = new BehaviorSubject<SofiaReport | null>(null);
  private isOpenSubject = new BehaviorSubject<boolean>(false);

  // Observables públicos
  report$: Observable<SofiaReport | null> = this.reportSubject.asObservable();
  isOpen$: Observable<boolean> = this.isOpenSubject.asObservable();

  // Métodos para manejar reportes
  handleReport(report: SofiaReport) {
    this.reportSubject.next(report);
    // Aquí puedes añadir lógica adicional como guardar en localStorage
    // o enviar al servidor
  }

  // Métodos para manejar estado
  setIsOpen(isOpen: boolean) {
    this.isOpenSubject.next(isOpen);
  }

  // Método para generar toolsArgs dinámicamente
  generateToolsArgs(specialty: string): string {
    const baseSchema = {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "title": `Consulta de ${specialty}`,
      "type": "object"
    };

    // Personalizar según especialidad
    switch(specialty) {
      case 'cardiologia':
        return JSON.stringify({
          ...baseSchema,
          "properties": {
            "diagnostico": { "type": "string" },
            "ritmo_cardiaco": { "type": "number" },
            "presion_arterial": { "type": "string" }
          }
        });
      case 'dermatologia':
        return JSON.stringify({
          ...baseSchema,
          "properties": {
            "diagnostico": { "type": "string" },
            "tipo_lesion": { "type": "string" },
            "localizacion": { "type": "string" }
          }
        });
      default:
        return JSON.stringify({
          ...baseSchema,
          "properties": {
            "diagnostico": { "type": "string" },
            "tratamiento": { "type": "string" }
          }
        });
    }
  }
}

Uso del servicio en componente

// app.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { SofiaService } from './services/sofia.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent implements OnInit, OnDestroy {
  private destroy$ = new Subject<void>();
  
  userId = 'angular-user-123';
  patientId = 'patient-456';
  isOpen = false;
  toolsArgsJson = '';

  constructor(private sofiaService: SofiaService) {}

  ngOnInit() {
    // Suscribirse a cambios de estado
    this.sofiaService.isOpen$
      .pipe(takeUntil(this.destroy$))
      .subscribe(isOpen => {
        this.isOpen = isOpen;
      });

    // Suscribirse a reportes
    this.sofiaService.report$
      .pipe(takeUntil(this.destroy$))
      .subscribe(report => {
        if (report) {
          console.log('Nuevo reporte:', report);
          // Procesar reporte
        }
      });

    // Configurar toolsArgs inicial
    this.toolsArgsJson = this.sofiaService.generateToolsArgs('general');
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }

  onReport(report: any) {
    this.sofiaService.handleReport(report);
  }

  onSetIsOpen(isOpen: boolean) {
    this.sofiaService.setIsOpen(isOpen);
  }
}

Consideraciones importantes

Detección de cambios

Angular puede requerir detección manual de cambios en algunos casos:
import { ChangeDetectorRef } from '@angular/core';

constructor(private cdr: ChangeDetectorRef) {}

onReport(report: any) {
  // Procesar reporte
  this.cdr.detectChanges(); // Forzar detección si es necesario
}

Ciclo de vida de componentes

ngAfterViewInit() {
  // El Web Component está disponible después de la inicialización de la vista
  const sofiaElement = document.querySelector('sofia-sdk');
  if (sofiaElement) {
    // Configuración adicional si es necesaria
  }
}

Manejo de errores

onReport(report: any) {
  try {
    // Procesar reporte
    this.processReport(report);
  } catch (error) {
    console.error('Error procesando reporte:', error);
    // Manejar error apropiadamente
  }
}

Integración con Angular Material

Si usa Angular Material, puede integrar SofIA con sus componentes:
<mat-card>
  <mat-card-header>
    <mat-card-title>Consulta Médica</mat-card-title>
    <mat-card-subtitle>Paciente: {{patientId}}</mat-card-subtitle>
  </mat-card-header>
  
  <mat-card-content>
    <sofia-sdk
      [attr.apikey]="apiKey"
      [attr.userid]="userId"
      [attr.patientid]="patientId"
      [attr.toolsargs]="toolsArgsJson"
      [attr.isopen]="isOpen ? 'true' : 'false'"
      (handle-report)="onReport($event.detail)"
      (set-is-open)="onSetIsOpen($event.detail)">
    </sofia-sdk>
  </mat-card-content>
  
  <mat-card-actions>
    <button mat-button (click)="toggleSofIA()">
      {{isOpen ? 'Cerrar' : 'Abrir'}} SofIA
    </button>
  </mat-card-actions>
</mat-card>
Esta implementación proporciona una base sólida para integrar SofIA SDK en aplicaciones Angular modernas, con tipado fuerte y mejores prácticas de Angular.