import { Component, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { GridModule } from '@progress/kendo-angular-grid'; import { ButtonsModule } from '@progress/kendo-angular-buttons'; import { ExpenseApiService } from '../../services/expense-api.service'; import { ExpenseFormDialogComponent, ExpenseFormResult } from '../../components/expense-form-dialog/expense-form-dialog.component'; import { ExpenseListItemDto } from '../../models/expense.model'; import { switchMap, of } from 'rxjs'; import { PageHeaderActionsDirective } from '../../../../shared/directives/page-header-actions.directive'; @Component({ selector: 'app-my-reimbursements-page', standalone: true, imports: [CommonModule, GridModule, ButtonsModule, ExpenseFormDialogComponent, PageHeaderActionsDirective], templateUrl: './my-reimbursements-page.component.html', styleUrls: ['./my-reimbursements-page.component.scss'], }) export class MyReimbursementsPageComponent implements OnInit { rows: ExpenseListItemDto[] = []; loading = false; dialogOpen = false; editRow: ExpenseListItemDto | null = null; constructor(private api: ExpenseApiService) {} ngOnInit(): void { this.load(); } load(): void { this.loading = true; this.api.getMine().subscribe({ next: r => { this.rows = r.items; this.loading = false; }, error: () => { this.loading = false; }, }); } openNew(): void { this.editRow = null; this.dialogOpen = true; } openEdit(row: ExpenseListItemDto): void { this.editRow = row; this.dialogOpen = true; } closeDialog(): void { this.dialogOpen = false; this.editRow = null; } onSave(result: ExpenseFormResult): void { if (this.editRow) { const id = this.editRow.id; this.api.update(id, result.request).pipe( switchMap(() => result.receipt ? this.api.uploadReceipt(id, result.receipt) : of(void 0)), ).subscribe(() => { this.closeDialog(); this.load(); }); } else { this.api.create(result.request).pipe( switchMap(created => result.receipt ? this.api.uploadReceipt(created.id, result.receipt).pipe(switchMap(() => of(created))) : of(created)), ).subscribe(() => { this.closeDialog(); this.load(); }); } } submit(row: ExpenseListItemDto): void { this.api.submit(row.id).subscribe(() => this.load()); } remove(row: ExpenseListItemDto): void { if (!confirm('Delete this reimbursement?')) return; this.api.delete(row.id).subscribe(() => this.load()); } openReceipt(id: number): void { this.api.downloadReceipt(id).subscribe(blob => { const url = URL.createObjectURL(blob); window.open(url, '_blank'); setTimeout(() => URL.revokeObjectURL(url), 60_000); }); } /** Editing (and reuploading the photo) is allowed while a reimbursement is still Draft or awaiting review. */ canEdit(row: ExpenseListItemDto): boolean { return row.status === 'Draft' || row.status === 'PendingApproval'; } /** Submit and Delete only apply before the reimbursement has been submitted. */ isDraft(row: ExpenseListItemDto): boolean { return row.status === 'Draft'; } statusClass(status: string): string { return ({ Draft: 'badge-draft', PendingApproval: 'badge-pending', Approved: 'badge-approved', Paid: 'badge-paid', Rejected: 'badge-rejected' } as Record)[status] ?? ''; } }