// src/app/upload-image-modal.component.ts import { Component, Input, Output, EventEmitter, AfterViewInit, ViewChild, ElementRef, OnDestroy } from '@angular/core'; import { Box, DeckImage, DeckService, OcrResult } from '../deck.service'; import { CommonModule } from '@angular/common'; import { HttpClient } from '@angular/common/http'; import { Modal } from 'flowbite'; @Component({ selector: 'app-upload-image-modal', templateUrl: './upload-image-modal.component.html', standalone: true, imports: [CommonModule] }) export class UploadImageModalComponent implements AfterViewInit, OnDestroy { @Input() deckName: string = ''; @Output() imageUploaded = new EventEmitter<{ imageSrc: string | ArrayBuffer | null | undefined, deckImage:DeckImage }>(); @ViewChild('uploadImageModal') modalElement!: ElementRef; @ViewChild('imageFile') imageFileElement!: ElementRef; imageFile: File | null = null; processingStatus: string = ''; loading: boolean = false; modal: any; constructor(private deckService: DeckService, private http: HttpClient) { } ngAfterViewInit(): void { this.modal = new Modal(this.modalElement.nativeElement); } ngOnDestroy(): void { // Modal wird automatisch von Flowbite verwaltet } open(): void { this.resetState(); this.modal.show(); } closeModal(): void { this.modal.hide(); } resetState(): void { this.imageFile = null; this.processingStatus = ''; this.loading = false; } onFileChange(event: any): void { const file: File = event.target.files[0]; if (!file) return; this.imageFile = file; this.processingStatus = 'Verarbeitung läuft...'; this.loading = true; const reader = new FileReader(); reader.onload = async (e) => { const imageSrc = e.target?.result; // Bild als Base64-String ohne Präfix (data:image/...) const imageBase64 = (imageSrc as string).split(',')[1]; try { const response = await this.http.post('/api/ocr', { image: imageBase64 }).toPromise(); if (!response || !response.results) { this.processingStatus = 'Ungültige Antwort vom OCR-Service'; this.loading = false; return; } this.processingStatus = 'Verarbeitung abgeschlossen'; this.loading = false; // Emit Event mit Bilddaten und OCR-Ergebnissen const bildname=this.imageFile?.name??''; const bildid=response.results.length>0?response.results[0].name:null const boxes:Box[] = []; response.results.forEach((result: OcrResult) => { const box = result.box; const xs = box.map((point: number[]) => point[0]); const ys = box.map((point: number[]) => point[1]); const xMin = Math.min(...xs); const xMax = Math.max(...xs); const yMin = Math.min(...ys); const yMax = Math.max(...ys); boxes.push({x1:xMin,x2:xMax,y1:yMin,y2:yMax}) }); const deckImage:DeckImage={name:bildname,id:bildid,boxes} this.imageUploaded.emit({ imageSrc, deckImage }); this.resetFileInput(); // Schließe das Upload-Modal this.closeModal(); } catch (error) { console.error('Fehler beim OCR-Service:', error); this.processingStatus = 'Fehler beim OCR-Service'; this.loading = false; } }; reader.readAsDataURL(file); } /** * Setzt das Datei-Input-Feld zurück, sodass dieselbe Datei erneut ausgewählt werden kann. */ resetFileInput(): void { if (this.imageFileElement && this.imageFileElement.nativeElement) { this.imageFileElement.nativeElement.value = ''; } } }