import { Component, OnInit, OnDestroy } from '@angular/core'; import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; import { CommonModule } from '@angular/common'; import { Router, RouterModule } from '@angular/router'; import { ExtractionService } from '../../services/extraction.service'; import { SessionService, User } from '../../services/session.service'; import { ExtractionResponse, ClaimSubmission } from '../../services/extraction'; import { LucideAngularModule, ShieldCheck, AlertCircle, CheckCircle, ArrowLeft, Eye, EyeOff, Wand2 } from 'lucide-angular'; import { Subscription } from 'rxjs'; @Component({ selector: 'app-claim-form', standalone: true, imports: [CommonModule, ReactiveFormsModule, LucideAngularModule, RouterModule], templateUrl: './claim-form.component.html', styleUrls: ['./claim-form.component.css'] }) export class ClaimFormComponent implements OnInit, OnDestroy { claimForm: FormGroup; currentUser: User | null = null; previewUrl: string | null = null; selectedFile: File | null = null; extractionResponse: ExtractionResponse | null = null; isLoading = false; isSubmitting = false; isDragging = false; showRawJson = false; private amountSpentSub: Subscription | null = null; readonly ShieldCheck = ShieldCheck; readonly AlertCircle = AlertCircle; readonly CheckCircle = CheckCircle; readonly ArrowLeft = ArrowLeft; readonly Eye = Eye; readonly EyeOff = EyeOff; readonly Wand2 = Wand2; errorMessage: string | null = null; constructor( private fb: FormBuilder, private extractionService: ExtractionService, private sessionService: SessionService, private router: Router ) { this.claimForm = this.fb.group({ provider_name: ['', Validators.required], visit_date: ['', Validators.required], amount_spent: ['', [Validators.required, Validators.min(0.01)]], amount_claimed: [{ value: 0, disabled: true }], currency: ['MYR'] }); } ngOnInit(): void { this.currentUser = this.sessionService.getCurrentUser(); if (!this.currentUser) { this.router.navigate(['/']); return; } this.amountSpentSub = this.claimForm.get('amount_spent')?.valueChanges.subscribe(() => { this.calculateClaimable(); }) || null; } ngOnDestroy(): void { if (this.amountSpentSub) { this.amountSpentSub.unsubscribe(); } } calculateClaimable(): void { if (!this.currentUser) return; const spent = Number(this.claimForm.get('amount_spent')?.value) || 0; const remaining = this.currentUser.medical_allowance; const claimable = Math.min(spent, remaining); this.claimForm.patchValue({ amount_claimed: claimable }, { emitEvent: false }); } onDragOver(event: DragEvent): void { event.preventDefault(); event.stopPropagation(); this.isDragging = true; } onDragLeave(event: DragEvent): void { event.preventDefault(); event.stopPropagation(); this.isDragging = false; } onDrop(event: DragEvent): void { event.preventDefault(); event.stopPropagation(); this.isDragging = false; const files = event.dataTransfer?.files; if (files && files.length > 0) { this.handleFileSelection(files[0]); } } onFileSelected(event: any): void { const file: File = event.target.files[0]; if (file) { this.handleFileSelection(file); } } private handleFileSelection(file: File): void { if (!this.currentUser) return; this.selectedFile = file; this.previewUrl = URL.createObjectURL(file); this.extractionResponse = null; // reset if existing this.errorMessage = null; } autoFillWithAI(): void { if (!this.currentUser || !this.selectedFile) return; this.isLoading = true; this.errorMessage = null; this.extractionService.extractData(this.selectedFile, this.currentUser.name, this.currentUser.department).subscribe({ next: (response) => { this.extractionResponse = response; this.claimForm.patchValue({ provider_name: response.provider_name, visit_date: response.visit_date, amount_spent: response.total_amount, currency: response.currency || 'MYR' }); // The valueChanges subscription will trigger calculateClaimable automatically this.isLoading = false; }, error: (err: Error) => { console.error('Extraction failed', err); this.errorMessage = err.message; this.isLoading = false; } }); } onSubmit(): void { if (this.claimForm.invalid || !this.currentUser) return; this.isSubmitting = true; const formData = this.claimForm.getRawValue(); const submissionData: ClaimSubmission = { provider_name: formData.provider_name, visit_date: formData.visit_date, amount_spent: Number(formData.amount_spent), currency: formData.currency, extraction_data: this.extractionResponse }; this.extractionService.submitClaim(submissionData, this.currentUser.id).subscribe({ next: () => { this.isSubmitting = false; this.router.navigate(['/']); }, error: (err) => { console.error('Submission failed', err); this.errorMessage = 'Failed to submit claim. Please try again.'; this.isSubmitting = false; } }); } get rawJson(): string { return JSON.stringify(this.extractionResponse, null, 2); } }