Browse Source

Task/improve type safety in account balances component (#6352)

* fix(lib): add type annotations for date adapter

* fix(lib): handle form value possibly null

* fix(lint): use arrow fn for validators

* fix(lib): accounts table typings

* fix(lib): remove unsubscribeSubject due to lack of observable

* fix(lib): remove validators variable

* feat(lib): implement inject functions

* feat(lib): make locale an input signal

* feat(lib): make showActions an input signal

* feat(lib): make accountId an input signal

* feat(lib): make accountCurrency an input signal

* feat(lib): make accountBalances an input signal

* feat(lib): make sort a viewChild signal

* feat(lib): implement isNil
pull/6258/head^2
Kenrick Tandrian 1 week ago
committed by GitHub
parent
commit
6c6f20c3fd
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 10
      libs/ui/src/lib/account-balances/account-balances.component.html
  2. 68
      libs/ui/src/lib/account-balances/account-balances.component.ts
  3. 2
      libs/ui/src/lib/accounts-table/accounts-table.component.ts

10
libs/ui/src/lib/account-balances/account-balances.component.html

@ -12,7 +12,7 @@
<ng-container i18n>Date</ng-container> <ng-container i18n>Date</ng-container>
</th> </th>
<td *matCellDef="let element" class="px-2" mat-cell> <td *matCellDef="let element" class="px-2" mat-cell>
<gf-value [isDate]="true" [locale]="locale" [value]="element?.date" /> <gf-value [isDate]="true" [locale]="locale()" [value]="element?.date" />
</td> </td>
<td *matFooterCellDef class="px-2" mat-footer-cell> <td *matFooterCellDef class="px-2" mat-footer-cell>
<mat-form-field appearance="outline" class="py-1 without-hint"> <mat-form-field appearance="outline" class="py-1 without-hint">
@ -37,7 +37,7 @@
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
<gf-value <gf-value
[isCurrency]="true" [isCurrency]="true"
[locale]="locale" [locale]="locale()"
[unit]="element?.account?.currency" [unit]="element?.account?.currency"
[value]="element?.value" [value]="element?.value"
/> />
@ -48,7 +48,7 @@
<mat-form-field appearance="outline" class="without-hint"> <mat-form-field appearance="outline" class="without-hint">
<input formControlName="balance" matInput type="number" /> <input formControlName="balance" matInput type="number" />
<div class="ml-2" matTextSuffix> <div class="ml-2" matTextSuffix>
{{ accountCurrency }} {{ accountCurrency() }}
</div> </div>
</mat-form-field> </mat-form-field>
</div> </div>
@ -58,7 +58,7 @@
<ng-container matColumnDef="actions" stickyEnd> <ng-container matColumnDef="actions" stickyEnd>
<th *matHeaderCellDef class="px-1 text-center" mat-header-cell></th> <th *matHeaderCellDef class="px-1 text-center" mat-header-cell></th>
<td *matCellDef="let element" class="px-1 text-center" mat-cell> <td *matCellDef="let element" class="px-1 text-center" mat-cell>
@if (showActions) { @if (showActions()) {
<button <button
class="mx-1 no-min-width px-2" class="mx-1 no-min-width px-2"
mat-button mat-button
@ -100,7 +100,7 @@
<tr <tr
*matFooterRowDef="displayedColumns" *matFooterRowDef="displayedColumns"
mat-footer-row mat-footer-row
[hidden]="!showActions" [hidden]="!showActions()"
></tr> ></tr>
</table> </table>
</form> </form>

68
libs/ui/src/lib/account-balances/account-balances.component.ts

@ -10,12 +10,12 @@ import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
EventEmitter, EventEmitter,
Input,
OnChanges, OnChanges,
OnDestroy,
OnInit, OnInit,
Output, Output,
ViewChild inject,
input,
viewChild
} from '@angular/core'; } from '@angular/core';
import { import {
FormGroup, FormGroup,
@ -39,8 +39,7 @@ import {
ellipsisHorizontal, ellipsisHorizontal,
trashOutline trashOutline
} from 'ionicons/icons'; } from 'ionicons/icons';
import { get } from 'lodash'; import { get, isNil } from 'lodash';
import { Subject } from 'rxjs';
import { GfValueComponent } from '../value'; import { GfValueComponent } from '../value';
@ -63,50 +62,44 @@ import { GfValueComponent } from '../value';
styleUrls: ['./account-balances.component.scss'], styleUrls: ['./account-balances.component.scss'],
templateUrl: './account-balances.component.html' templateUrl: './account-balances.component.html'
}) })
export class GfAccountBalancesComponent export class GfAccountBalancesComponent implements OnChanges, OnInit {
implements OnChanges, OnDestroy, OnInit
{
@Input() accountBalances: AccountBalancesResponse['balances'];
@Input() accountCurrency: string;
@Input() accountId: string;
@Input() locale = getLocale();
@Input() showActions = true;
@Output() accountBalanceCreated = new EventEmitter<CreateAccountBalanceDto>(); @Output() accountBalanceCreated = new EventEmitter<CreateAccountBalanceDto>();
@Output() accountBalanceDeleted = new EventEmitter<string>(); @Output() accountBalanceDeleted = new EventEmitter<string>();
@ViewChild(MatSort) sort: MatSort; public readonly accountBalances =
input.required<AccountBalancesResponse['balances']>();
public readonly accountCurrency = input.required<string>();
public readonly accountId = input.required<string>();
public readonly displayedColumns: string[] = ['date', 'value', 'actions'];
public readonly locale = input(getLocale());
public readonly showActions = input(true);
public readonly sort = viewChild(MatSort);
public accountBalanceForm = new FormGroup({ public accountBalanceForm = new FormGroup({
balance: new FormControl(0, Validators.required), balance: new FormControl(0, (control) => Validators.required(control)),
date: new FormControl(new Date(), Validators.required) date: new FormControl(new Date(), (control) => Validators.required(control))
}); });
public dataSource = new MatTableDataSource< public dataSource = new MatTableDataSource<
AccountBalancesResponse['balances'][0] AccountBalancesResponse['balances'][0]
>(); >();
public displayedColumns: string[] = ['date', 'value', 'actions']; private dateAdapter = inject<DateAdapter<Date, string>>(DateAdapter);
public Validators = Validators; private notificationService = inject(NotificationService);
private unsubscribeSubject = new Subject<void>();
public constructor( public constructor() {
private dateAdapter: DateAdapter<any>,
private notificationService: NotificationService
) {
addIcons({ calendarClearOutline, ellipsisHorizontal, trashOutline }); addIcons({ calendarClearOutline, ellipsisHorizontal, trashOutline });
} }
public ngOnInit() { public ngOnInit() {
this.dateAdapter.setLocale(this.locale); this.dateAdapter.setLocale(this.locale());
} }
public ngOnChanges() { public ngOnChanges() {
if (this.accountBalances) { if (this.accountBalances()) {
this.dataSource = new MatTableDataSource(this.accountBalances); this.dataSource = new MatTableDataSource(this.accountBalances());
this.dataSource.sort = this.sort; this.dataSource.sort = this.sort();
this.dataSource.sortingDataAccessor = get; this.dataSource.sortingDataAccessor = get;
} }
} }
@ -122,10 +115,16 @@ export class GfAccountBalancesComponent
} }
public async onSubmitAccountBalance() { public async onSubmitAccountBalance() {
const { balance, date } = this.accountBalanceForm.value;
if (isNil(balance) || !date) {
return;
}
const accountBalance: CreateAccountBalanceDto = { const accountBalance: CreateAccountBalanceDto = {
accountId: this.accountId, balance,
balance: this.accountBalanceForm.get('balance').value, accountId: this.accountId(),
date: format(this.accountBalanceForm.get('date').value, DATE_FORMAT) date: format(date, DATE_FORMAT)
}; };
try { try {
@ -141,9 +140,4 @@ export class GfAccountBalancesComponent
this.accountBalanceCreated.emit(accountBalance); this.accountBalanceCreated.emit(accountBalance);
} }
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
} }

2
libs/ui/src/lib/accounts-table/accounts-table.component.ts

@ -53,7 +53,7 @@ import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
templateUrl: './accounts-table.component.html' templateUrl: './accounts-table.component.html'
}) })
export class GfAccountsTableComponent { export class GfAccountsTableComponent {
public readonly accounts = input.required<Account[] | undefined>(); public readonly accounts = input.required<Account[]>();
public readonly activitiesCount = input<number>(); public readonly activitiesCount = input<number>();
public readonly baseCurrency = input<string>(); public readonly baseCurrency = input<string>();
public readonly hasPermissionToOpenDetails = input(true); public readonly hasPermissionToOpenDetails = input(true);

Loading…
Cancel
Save