import { CdkScrollableModule } from '@angular/cdk/scrolling'; import { CurrencyPipe } from '@angular/common'; import { Component, inject, signal, computed } from '@angular/core'; import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatTableModule } from '@angular/material/table'; import { map, tap } from 'rxjs/operators'; import { ReceivePaymentItem } from '../../core/receive-payment-item'; import { SettleOption } from '../../core/settle-option'; import { SettleOptionService } from '../../settle-option/settle-option.service'; import { VoucherType } from '../bills/voucher-type'; export interface ReceivePaymentFormData { amounts: { name: string; amount: number; }[]; son: string; } @Component({ selector: 'app-receive-payment', templateUrl: './receive-payment.component.html', styleUrls: ['./receive-payment.component.css'], imports: [ CdkScrollableModule, CurrencyPipe, MatButtonModule, MatDialogModule, MatFormFieldModule, MatInputModule, MatTableModule, FormField, ], }) export class ReceivePaymentComponent { private ser = inject(SettleOptionService); dialogRef = inject>(MatDialogRef); data = inject<{ type: VoucherType; amount: number; }>(MAT_DIALOG_DATA); choices = signal([]); choicesWithAmount = computed(() => { const amounts = this.formModel().amounts; return this.choices().map((c, i) => ({ ...c, amount: amounts[i]?.amount ?? 0 })); }); type: VoucherType; amount: number; balance = computed(() => { return this.amount - this.formModel().amounts.reduce((a, c) => a + (c.amount ?? 0), 0); }); reason = ''; displayReason = signal(undefined); displayTable = signal(undefined); formModel = signal({ amounts: [], son: '', }); form = form(this.formModel); dataSource = this.choicesWithAmount; displayedColumns = ['name', 'amount']; constructor() { const data = this.data; this.type = data.type; this.amount = data.amount; this.displayReason.set(false); this.displayTable.set(false); this.ser .listForType(data.type) .pipe( tap((x: SettleOption[]) => this.displayReason.set(x.reduce((o, n) => o || n.hasReason, this.displayReason()))), tap((x: SettleOption[]) => this.displayTable.set(x.length > 1)), map((x: SettleOption[]) => x.map((y) => ({ ...y, amount: !this.displayTable() ? this.amount : 0 }) as ReceivePaymentItem), ), ) .subscribe((x) => { this.choices.set(x); this.formModel.update((f) => ({ ...f, amounts: x.map((y) => ({ name: y.name, amount: y.amount === 0 ? 0 : this.amount, })), })); }); } select(reason: string) { this.reason = reason.trim(); return true; } accept(): void { this.dialogRef.close({ choices: this.choicesWithAmount(), reason: this.reason }); } maxAmount(row: ReceivePaymentItem, index: number) { this.formModel.update((f) => { const newAmounts = [...f.amounts]; if (newAmounts[index]) { newAmounts[index] = { ...newAmounts[index], amount: row.amount + this.balance() }; } return { ...f, amounts: newAmounts }; }); } }