|
@@ -3,9 +3,9 @@ import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angula
|
|
|
import { CommonModule } from '@angular/common';
|
|
import { CommonModule } from '@angular/common';
|
|
|
import { Router, RouterModule } from '@angular/router';
|
|
import { Router, RouterModule } from '@angular/router';
|
|
|
import { ExtractionService } from '../../services/extraction.service';
|
|
import { ExtractionService } from '../../services/extraction.service';
|
|
|
|
|
+import { SessionService, User } from '../../services/session.service';
|
|
|
import { ExtractionResponse } from '../../services/extraction';
|
|
import { ExtractionResponse } from '../../services/extraction';
|
|
|
-import { LucideAngularModule, ShieldCheck, AlertCircle, CheckCircle, ArrowLeft } from 'lucide-angular';
|
|
|
|
|
-import { SessionService } from '../../services/session.service';
|
|
|
|
|
|
|
+import { LucideAngularModule, ShieldCheck, AlertCircle, CheckCircle, ArrowLeft, Eye, EyeOff } from 'lucide-angular';
|
|
|
|
|
|
|
|
@Component({
|
|
@Component({
|
|
|
selector: 'app-claim-form',
|
|
selector: 'app-claim-form',
|
|
@@ -16,15 +16,20 @@ import { SessionService } from '../../services/session.service';
|
|
|
})
|
|
})
|
|
|
export class ClaimFormComponent implements OnInit {
|
|
export class ClaimFormComponent implements OnInit {
|
|
|
claimForm: FormGroup;
|
|
claimForm: FormGroup;
|
|
|
|
|
+ currentUser: User | null = null;
|
|
|
previewUrl: string | null = null;
|
|
previewUrl: string | null = null;
|
|
|
extractionResponse: ExtractionResponse | null = null;
|
|
extractionResponse: ExtractionResponse | null = null;
|
|
|
isLoading = false;
|
|
isLoading = false;
|
|
|
isSubmitting = false;
|
|
isSubmitting = false;
|
|
|
isDragging = false;
|
|
isDragging = false;
|
|
|
|
|
+ showRawJson = false;
|
|
|
|
|
+
|
|
|
readonly ShieldCheck = ShieldCheck;
|
|
readonly ShieldCheck = ShieldCheck;
|
|
|
readonly AlertCircle = AlertCircle;
|
|
readonly AlertCircle = AlertCircle;
|
|
|
readonly CheckCircle = CheckCircle;
|
|
readonly CheckCircle = CheckCircle;
|
|
|
readonly ArrowLeft = ArrowLeft;
|
|
readonly ArrowLeft = ArrowLeft;
|
|
|
|
|
+ readonly Eye = Eye;
|
|
|
|
|
+ readonly EyeOff = EyeOff;
|
|
|
errorMessage: string | null = null;
|
|
errorMessage: string | null = null;
|
|
|
|
|
|
|
|
constructor(
|
|
constructor(
|
|
@@ -36,18 +41,29 @@ export class ClaimFormComponent implements OnInit {
|
|
|
this.claimForm = this.fb.group({
|
|
this.claimForm = this.fb.group({
|
|
|
provider_name: ['', Validators.required],
|
|
provider_name: ['', Validators.required],
|
|
|
visit_date: ['', Validators.required],
|
|
visit_date: ['', Validators.required],
|
|
|
- total_amount: [0, [Validators.required, Validators.min(0.01)]],
|
|
|
|
|
|
|
+ amount_spent: [{ value: 0, disabled: true }, [Validators.required, Validators.min(0.01)]],
|
|
|
|
|
+ amount_claimed: [{ value: 0, disabled: false }, [Validators.required, Validators.min(0)]],
|
|
|
currency: ['MYR']
|
|
currency: ['MYR']
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ngOnInit(): void {
|
|
ngOnInit(): void {
|
|
|
- const user = this.sessionService.getCurrentUser();
|
|
|
|
|
- if (!user) {
|
|
|
|
|
|
|
+ this.currentUser = this.sessionService.getCurrentUser();
|
|
|
|
|
+ if (!this.currentUser) {
|
|
|
this.router.navigate(['/']);
|
|
this.router.navigate(['/']);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ calculateClaimable(): void {
|
|
|
|
|
+ if (!this.currentUser || !this.extractionResponse) return;
|
|
|
|
|
+
|
|
|
|
|
+ const spent = 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 });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
onDragOver(event: DragEvent): void {
|
|
onDragOver(event: DragEvent): void {
|
|
|
event.preventDefault();
|
|
event.preventDefault();
|
|
|
event.stopPropagation();
|
|
event.stopPropagation();
|
|
@@ -64,7 +80,7 @@ export class ClaimFormComponent implements OnInit {
|
|
|
event.preventDefault();
|
|
event.preventDefault();
|
|
|
event.stopPropagation();
|
|
event.stopPropagation();
|
|
|
this.isDragging = false;
|
|
this.isDragging = false;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const files = event.dataTransfer?.files;
|
|
const files = event.dataTransfer?.files;
|
|
|
if (files && files.length > 0) {
|
|
if (files && files.length > 0) {
|
|
|
this.processFile(files[0]);
|
|
this.processFile(files[0]);
|
|
@@ -79,21 +95,22 @@ export class ClaimFormComponent implements OnInit {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private processFile(file: File): void {
|
|
private processFile(file: File): void {
|
|
|
|
|
+ if (!this.currentUser) return;
|
|
|
|
|
+
|
|
|
this.previewUrl = URL.createObjectURL(file);
|
|
this.previewUrl = URL.createObjectURL(file);
|
|
|
this.isLoading = true;
|
|
this.isLoading = true;
|
|
|
this.errorMessage = null;
|
|
this.errorMessage = null;
|
|
|
-
|
|
|
|
|
- const user = this.sessionService.getCurrentUser();
|
|
|
|
|
-
|
|
|
|
|
- this.extractionService.extractData(file, user?.name, user?.department).subscribe({
|
|
|
|
|
|
|
+
|
|
|
|
|
+ this.extractionService.extractData(file, this.currentUser.name, this.currentUser.department).subscribe({
|
|
|
next: (response) => {
|
|
next: (response) => {
|
|
|
this.extractionResponse = response;
|
|
this.extractionResponse = response;
|
|
|
this.claimForm.patchValue({
|
|
this.claimForm.patchValue({
|
|
|
provider_name: response.provider_name,
|
|
provider_name: response.provider_name,
|
|
|
visit_date: response.visit_date,
|
|
visit_date: response.visit_date,
|
|
|
- total_amount: response.total_amount,
|
|
|
|
|
|
|
+ amount_spent: response.total_amount,
|
|
|
currency: response.currency || 'MYR'
|
|
currency: response.currency || 'MYR'
|
|
|
});
|
|
});
|
|
|
|
|
+ this.calculateClaimable();
|
|
|
this.isLoading = false;
|
|
this.isLoading = false;
|
|
|
},
|
|
},
|
|
|
error: (err: Error) => {
|
|
error: (err: Error) => {
|
|
@@ -105,21 +122,20 @@ export class ClaimFormComponent implements OnInit {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
onSubmit(): void {
|
|
onSubmit(): void {
|
|
|
- if (this.claimForm.invalid) return;
|
|
|
|
|
-
|
|
|
|
|
- const user = this.sessionService.getCurrentUser();
|
|
|
|
|
- if (!user) return;
|
|
|
|
|
|
|
+ if (this.claimForm.invalid || !this.currentUser) return;
|
|
|
|
|
|
|
|
this.isSubmitting = true;
|
|
this.isSubmitting = true;
|
|
|
- const formData = this.claimForm.value;
|
|
|
|
|
-
|
|
|
|
|
- // Merge user-verified data with AI response metadata if needed
|
|
|
|
|
|
|
+ const formData = this.claimForm.getRawValue(); // To get disabled fields
|
|
|
|
|
+
|
|
|
const submissionData: ExtractionResponse = {
|
|
const submissionData: ExtractionResponse = {
|
|
|
...this.extractionResponse!,
|
|
...this.extractionResponse!,
|
|
|
- ...formData
|
|
|
|
|
|
|
+ provider_name: formData.provider_name,
|
|
|
|
|
+ visit_date: formData.visit_date,
|
|
|
|
|
+ total_amount: formData.amount_spent,
|
|
|
|
|
+ currency: formData.currency
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- this.extractionService.submitClaim(submissionData, user.name, user.department).subscribe({
|
|
|
|
|
|
|
+ this.extractionService.submitClaim(submissionData, this.currentUser.id).subscribe({
|
|
|
next: () => {
|
|
next: () => {
|
|
|
this.isSubmitting = false;
|
|
this.isSubmitting = false;
|
|
|
this.router.navigate(['/dashboard']);
|
|
this.router.navigate(['/dashboard']);
|
|
@@ -132,7 +148,7 @@ export class ClaimFormComponent implements OnInit {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- get confidenceScore(): number {
|
|
|
|
|
- return this.extractionResponse?.confidence_score ?? 0;
|
|
|
|
|
|
|
+ get rawJson(): string {
|
|
|
|
|
+ return JSON.stringify(this.extractionResponse, null, 2);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|