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