import { Component, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { DragDropModule, CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop'; import { SplitterModule } from 'primeng/splitter'; import { ButtonModule } from 'primeng/button'; import { DialogModule } from 'primeng/dialog'; import { InputTextModule } from 'primeng/inputtext'; import { DropdownModule } from 'primeng/dropdown'; import { TableModule } from 'primeng/table'; import { ToastModule } from 'primeng/toast'; import { MessageService } from 'primeng/api'; import { TemplateService, DocumentLayout, TemplateField } from '../services/template.service'; @Component({ selector: 'app-templates', standalone: true, imports: [ CommonModule, FormsModule, DragDropModule, SplitterModule, ButtonModule, DialogModule, InputTextModule, DropdownModule, TableModule, ToastModule ], providers: [MessageService], templateUrl: './templates.component.html', styleUrls: ['./templates.component.scss'] }) export class TemplatesComponent implements OnInit { // Document State documentId: string | null = null; layoutNodes: DocumentLayout[] = []; // Template State templateName: string = ''; templateFields: TemplateField[] = []; mappings: { [fieldId: number]: DocumentLayout[] } = {}; // UI State displayAddField: boolean = false; newField: TemplateField = { field_label: '', field_type: 'TEXT', display_order: 0, required_flag: false }; fieldTypes = [ { label: 'TEXT', value: 'TEXT' }, { label: 'NUMBER', value: 'NUMBER' }, { label: 'DATE', value: 'DATE' }, { label: 'AMOUNT', value: 'AMOUNT' }, { label: 'ADDRESS', value: 'ADDRESS' }, { label: 'TABLE_COLUMN', value: 'TABLE_COLUMN' } ]; constructor( private templateService: TemplateService, private messageService: MessageService ) {} ngOnInit(): void {} onFileUpload(event: any) { const file = event.target.files[0]; if (file) { this.templateService.uploadDocument(file).subscribe({ next: (res) => { this.documentId = res.id || res.pk_document_id; this.messageService.add({ severity: 'success', summary: 'Uploaded', detail: 'Document uploaded successfully.' }); this.fetchLayout(); }, error: (err) => { this.messageService.add({ severity: 'error', summary: 'Error', detail: 'Upload failed.' }); } }); } } fetchLayout() { if (!this.documentId) return; this.templateService.getDocumentLayout(this.documentId).subscribe({ next: (layouts) => { if (layouts.length === 0) { // Document might still be processing in the background Celery worker // Poll again after 2 seconds setTimeout(() => this.fetchLayout(), 2000); return; } this.layoutNodes = layouts; // Trigger auto-recognition this.autoRecognize(); } }); } autoRecognize() { if (!this.documentId) return; this.templateService.recognizeTemplate(this.documentId).subscribe({ next: (res) => { if (res.templateMatched) { this.messageService.add({ severity: 'info', summary: 'Template Recognized', detail: `Confidence: ${res.confidence}%` }); // In a full implementation, we'd load the template fields and populate the mappings. } } }); } showAddFieldDialog() { this.newField = { field_label: '', field_type: 'TEXT', display_order: this.templateFields.length, required_flag: false }; this.displayAddField = true; } addField() { if (!this.newField.field_label) return; this.newField.pk_template_field_id = new Date().getTime(); // mock ID until saved this.templateFields.push({ ...this.newField }); this.mappings[this.newField.pk_template_field_id] = []; this.displayAddField = false; } saveTemplateAndMappings() { if (!this.templateName || this.templateName.trim() === '') { this.messageService.add({ severity: 'warn', summary: 'Warning', detail: 'Please provide a template name.' }); return; } if (this.templateFields.length === 0) { this.messageService.add({ severity: 'warn', summary: 'Warning', detail: 'Please add at least one template field.' }); return; } this.templateService.createTemplate({ template_name: this.templateName, fields: this.templateFields }).subscribe({ next: (res) => { // In a real scenario, we pass res.templateId and map the layoutNodes this.messageService.add({ severity: 'success', summary: 'Success', detail: 'Template & Mappings saved successfully.' }); } }); } // Drag and Drop Logic drop(event: CdkDragDrop, fieldId?: number) { if (event.previousContainer === event.container) { moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); } else { transferArrayItem( event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex, ); } } getConnectedDropLists() { // Return all field ID strings as drop lists return this.templateFields.map(f => 'field-' + f.pk_template_field_id); } }