import { Component, inject, afterNextRender, linkedSignal, input, computed } from '@angular/core'; import { form, FormField, FormRoot } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatOptionModule } from '@angular/material/core'; import { MatDialog } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Router } from '@angular/router'; import { Account } from '../../core/account'; import { AccountService } from '../../core/account.service'; import { CostCentreService } from '../../cost-centre/cost-centre.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { ErrorStateComponent } from '../../shared/error-state/error-state.component'; import { SkeletonLoaderComponent } from '../../shared/skeleton-loader/skeleton-loader.component'; import { AccountTypeService } from '../account-type.service'; export interface AccountDetailFormData { code: string; name: string; type: number; isActive: boolean; isReconcilable: boolean; costCentre: string; } @Component({ selector: 'app-account-detail', templateUrl: './account-detail.component.html', styleUrls: ['./account-detail.component.css'], imports: [ MatIconModule, MatFormFieldModule, MatInputModule, MatSelectModule, MatOptionModule, MatCheckboxModule, MatButtonModule, FormField, FormRoot, SkeletonLoaderComponent, ErrorStateComponent, ], }) export class AccountDetailComponent { private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(AccountService); private accountTypeService = inject(AccountTypeService); private costCentreService = inject(CostCentreService); id = input(null, { transform: (v: string | null | undefined) => v ?? null }); itemResource = this.ser.get(this.id); item = computed(() => this.itemResource.value() ?? new Account()); accountModel = linkedSignal({ source: this.item, computation: (itemVal): AccountDetailFormData => { return { code: (itemVal.code || '(Auto)').toString(), name: itemVal.name || '', type: itemVal.type ?? 0, isActive: itemVal.isActive ?? true, isReconcilable: itemVal.isReconcilable ?? false, costCentre: itemVal.costCentre?.id ?? '', }; }, }); accountForm = form(this.accountModel); accountTypesResource = this.accountTypeService.list(); costCentresResource = this.costCentreService.list(); accountTypes = computed(() => this.accountTypesResource.value() || []); costCentres = computed(() => this.costCentresResource.value() || []); constructor() { afterNextRender(() => { this.accountForm.name().focusBoundControl(); }); } save() { this.ser.saveOrUpdate(this.getItem()).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/accounts'); }, error: (error) => { this.snackBar.open(error as string, 'Danger'); }, }); } delete() { this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/accounts'); }, error: (error) => { this.snackBar.open(error as string, 'Danger'); }, }); } confirmDelete(): void { const dialogRef = this.dialog.open(ConfirmDialogComponent, { width: '250px', data: { title: 'Delete Account?', content: 'Are you sure? This cannot be undone.' }, }); dialogRef.afterClosed().subscribe((result: boolean) => { if (result) { this.delete(); } }); } getItem(): Account { const formModel = this.accountModel(); const item = this.item(); item.name = formModel.name ?? ''; item.type = formModel.type ?? 0; item.isActive = formModel.isActive ?? true; item.isReconcilable = formModel.isReconcilable ?? false; item.costCentre.id = formModel.costCentre ?? ''; return item; } }