diff --git a/frontend/Exence/src/app/private/transactions-and-categories/create-transaction-dialog/create-transaction-dialog.component.html b/frontend/Exence/src/app/private/transactions-and-categories/create-transaction-dialog/create-transaction-dialog.component.html index 1c9875b..09267ed 100644 --- a/frontend/Exence/src/app/private/transactions-and-categories/create-transaction-dialog/create-transaction-dialog.component.html +++ b/frontend/Exence/src/app/private/transactions-and-categories/create-transaction-dialog/create-transaction-dialog.component.html @@ -50,16 +50,24 @@

New transaction

- @let categoryControl = form.controls.category; + @let categoryControl = form.controls.category.controls; Category - - @for (category of categories; track category.id) { + + + Search + + + + + + + @for (category of filteredCategories(); track category.id) { {{ `${category.name} - ${category.emoji}` }} } - + diff --git a/frontend/Exence/src/app/private/transactions-and-categories/create-transaction-dialog/create-transaction-dialog.component.ts b/frontend/Exence/src/app/private/transactions-and-categories/create-transaction-dialog/create-transaction-dialog.component.ts index 5a9818c..0b7e56a 100644 --- a/frontend/Exence/src/app/private/transactions-and-categories/create-transaction-dialog/create-transaction-dialog.component.ts +++ b/frontend/Exence/src/app/private/transactions-and-categories/create-transaction-dialog/create-transaction-dialog.component.ts @@ -1,4 +1,5 @@ -import { Component, inject, OnInit } from '@angular/core'; +import { Component, computed, inject, OnInit, signal } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; import { NonNullableFormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; import { MatCardModule } from '@angular/material/card'; import { MatCheckboxModule } from '@angular/material/checkbox'; @@ -6,9 +7,11 @@ import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; +import { startWith } from 'rxjs'; import { Category } from '../../../data-model/modules/category/Category'; import { Transaction } from '../../../data-model/modules/transaction/Transaction'; import { TransactionType } from '../../../data-model/modules/transaction/TransactionType'; +import { AutoTrimDirective } from '../../../shared/auto-trim.directive'; import { ButtonComponent } from '../../../shared/button/button.component'; import { DialogWithBaseComponent } from '../../../shared/dialog/dialog.service'; import { InputClearButtonComponent } from '../../../shared/input-clear-button/input-clear-button.component'; @@ -16,7 +19,6 @@ import { SnackbarService } from '../../../shared/snackbar/snackbar.service'; import { ValidatorComponent } from '../../../shared/validator/validator.component'; import { CategoryService } from '../../category.service'; import { TransactionService } from '../transaction.service'; -import { AutoTrimDirective } from "src/app/shared/auto-trim.directive"; export interface CreateTransactionDialogData { type?: TransactionType; @@ -28,17 +30,18 @@ export interface CreateTransactionDialogData { templateUrl: './create-transaction-dialog.component.html', styleUrl: './create-transaction-dialog.component.scss', imports: [ - ReactiveFormsModule, - MatFormFieldModule, - MatInputModule, - MatCardModule, - MatSelectModule, MatDatepickerModule, - MatCheckboxModule, - InputClearButtonComponent, - ButtonComponent, - ValidatorComponent, - AutoTrimDirective -], + ReactiveFormsModule, + MatFormFieldModule, + MatInputModule, + MatCardModule, + MatSelectModule, + MatDatepickerModule, + MatCheckboxModule, + InputClearButtonComponent, + ButtonComponent, + ValidatorComponent, + AutoTrimDirective, + ], }) export class CreateTransactionDialogComponent extends DialogWithBaseComponent implements OnInit { private readonly transactionService = inject(TransactionService); @@ -48,9 +51,7 @@ export class CreateTransactionDialogComponent extends DialogWithBaseComponent('', [Validators.required, Validators.maxLength(255)]), @@ -59,11 +60,26 @@ export class CreateTransactionDialogComponent extends DialogWithBaseComponent(null, [Validators.required, Validators.min(1)]), type: this.fb.control(TransactionType.EXPENSE, [Validators.required]), recurring: this.fb.control(false), - category: this.fb.control(null, [Validators.required]), + category: this.fb.group({ + category: this.fb.control(null, [Validators.required]), + searchText: this.fb.control('', [Validators.maxLength(25)]), + }), + }); + + private categories = signal([]); + private searchText = toSignal(this.form.controls.category.controls.searchText.valueChanges.pipe(startWith('')), { initialValue: '' }); + + filteredCategories = computed(() => { + const categories = this.categories(); + const search = this.searchText(); + if (!search) return categories; + return categories.filter(category => + category.name.toLowerCase().includes(search.toLowerCase()) + ); }); async ngOnInit(): Promise { - this.categories = await this.categoryService.list(); + this.categories.set(await this.categoryService.list()); if (this.data?.type) { this.form.controls.type.setValue(this.data.type); } @@ -90,7 +106,7 @@ export class CreateTransactionDialogComponent extends DialogWithBaseComponent