import { CdkScrollableModule } from '@angular/cdk/scrolling'; import { CurrencyPipe } from '@angular/common'; import { Component, computed, inject, linkedSignal } from '@angular/core'; import { form, FormField, FormRoot } from '@angular/forms/signals'; import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { Account } from '../core/account'; import { AccountService } from '../core/account.service'; import { Journal } from '../core/journal'; import { AccountingPipe } from '../shared/accounting.pipe'; import { MathService } from '../shared/math.service'; export interface JournalDialogFormData { debit: number; account: Account | string | null; amount: string; } @Component({ selector: 'app-journal-dialog', templateUrl: './journal-dialog.component.html', styleUrls: ['./journal-dialog.component.css'], imports: [ MatDialogModule, CdkScrollableModule, FormField, FormRoot, MatFormFieldModule, MatSelectModule, MatOptionModule, MatInputModule, MatAutocompleteModule, MatButtonModule, CurrencyPipe, AccountingPipe, ], }) export class JournalDialogComponent { private math = inject(MathService); private accountSer = inject(AccountService); readonly dialogRef = inject>(MatDialogRef); data = inject<{ journal: Journal; date: string; }>(MAT_DIALOG_DATA); formModel = linkedSignal< { journal: Journal; date: string; }, JournalDialogFormData >({ source: () => this.data, computation: (data: { journal: Journal; date: string }) => ({ debit: data.journal.debit, account: data.journal.account, amount: `${data.journal.amount}`, }), }); form = form(this.formModel); accountSearch = computed(() => { const v = this.form.account().value(); return typeof v === 'string' ? v : null; }); accountsResource = this.accountSer.autocomplete(this.accountSearch); accounts = computed(() => this.accountsResource.value() ?? []); balanceDate = computed(() => this.data.date); accountId = computed((): string | null => { const account = this.form.account().value(); return typeof account === 'string' ? null : (account?.id ?? null); }); accBalResource = this.accountSer.balance(this.accountId, this.balanceDate); accBal = computed(() => this.accBalResource.value() ?? null); displayFn(account?: Account): string { return account ? account.name : ''; } accept(): void { const formValue = this.form().value(); const account = typeof formValue.account === 'string' ? null : formValue.account; if (!account || !account.id) { return; } const amount = this.math.journalAmount(formValue.amount ?? '', Number(formValue.debit) || 1); this.data.journal.debit = amount.debit; this.data.journal.account = account; this.data.journal.amount = amount.amount; this.dialogRef.close(this.data.journal); } }