import { Component, ElementRef, Inject, ViewChild } from '@angular/core'; import { FormArray, FormControl, FormGroup } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { distinctUntilChanged, 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'; import { ReceivePaymentDatasource } from './receive-payment-datasource'; @Component({ selector: 'app-receive-payment', templateUrl: './receive-payment.component.html', styleUrls: ['./receive-payment.component.css'], }) export class ReceivePaymentComponent { @ViewChild('son', { static: true }) son?: ElementRef; choices: ReceivePaymentItem[] = []; type: VoucherType; amount: number; balance: number; reason = ''; displayReason: boolean; displayTable: boolean; form: FormGroup<{ amounts: FormArray< FormGroup<{ name: FormControl; amount: FormControl; }> >; son: FormControl; }>; dataSource: ReceivePaymentDatasource; displayedColumns = ['name', 'amount']; constructor( public dialogRef: MatDialogRef, private ser: SettleOptionService, @Inject(MAT_DIALOG_DATA) public data: { type: VoucherType; amount: number }, ) { this.form = new FormGroup({ amounts: new FormArray< FormGroup<{ name: FormControl; amount: FormControl; }> >([]), son: new FormControl('', { nonNullable: true }), }); this.type = data.type; this.amount = data.amount; this.balance = data.amount; this.displayReason = false; this.displayTable = false; this.ser .listForType(data.type) .pipe( tap((x: SettleOption[]) => (this.displayReason = x.reduce((o, n) => o || n.hasReason, this.displayReason))), tap((x: SettleOption[]) => (this.displayTable = x.length > 1)), map((x: SettleOption[]) => x.map((y) => ({ ...y, amount: !this.displayTable ? this.amount : 0 } as ReceivePaymentItem)), ), ) .subscribe((x) => { this.choices = x; this.form.controls.amounts.clear(); this.choices.forEach((y: ReceivePaymentItem) => this.form.controls.amounts.push( new FormGroup({ name: new FormControl(y.name, { nonNullable: true }), amount: new FormControl(y.amount === 0 ? 0 : this.amount, { nonNullable: true, }), }), ), ); this.dataSource = new ReceivePaymentDatasource(this.choices); this.listenToAmountChange(); this.balance = this.amount - this.choices.reduce((a, c) => a + c.amount, 0); }); this.dataSource = new ReceivePaymentDatasource(this.choices); this.listenToAmountChange(); } listenToAmountChange() { const array = this.form.controls.amounts; this.choices.forEach((z, i) => array.controls[i].valueChanges.pipe(distinctUntilChanged()).subscribe((x) => { (this.choices.find((s) => s.name === x.name) as ReceivePaymentItem).amount = x.amount ?? 0; this.balance = this.amount - this.choices.reduce((a, c) => a + c.amount, 0); }), ); } select(reason: string) { this.reason = reason.trim(); return true; } accept(): void { this.dialogRef.close({ choices: this.choices, reason: this.reason }); } maxAmount(row: ReceivePaymentItem, index: number) { const array = this.form.controls.amounts; const ctrl = array.controls[index].controls.amount; ctrl.setValue(row.amount + this.balance); } }