Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { MatProgressBarModule } from '@angular/material/progress-bar';
import { CategoryGet } from '../../../data-model/modules/category/CategoryGet';
import { CategorySummaryResponse } from '../../../data-model/modules/category/CategorySummaryResponse';
import { CategoryType } from '../../../data-model/modules/category/CategoryType';
import { RecurringTransactionCreate } from '../../../data-model/modules/transaction/RecurringTransactionCreate';
import { TransactionCreate } from '../../../data-model/modules/transaction/TransactionCreate';
import { AnimatedSkeletonLoaderComponent } from '../../../shared/animated-skeleton-loader/animated-skeleton-loader.component';
import { BaseComponent } from '../../../shared/base-component/base.component';
Expand All @@ -21,7 +22,9 @@ import { CreateCategoryDialogComponent } from '../../transactions-and-categories
import {
CreateTransactionDialogComponent,
CreateTransactionDialogData,
CreateTransactionDialogResult,
} from '../../transactions-and-categories/create-transaction-dialog/create-transaction-dialog.component';
import { RecurringStore } from '../../transactions-and-categories/recurring.store';
import { TransactionStore } from '../../transactions-and-categories/transaction.store';

@Component({
Expand All @@ -44,6 +47,7 @@ export class CategoriesComponent extends BaseComponent {
private readonly dialog = inject(DialogService);
private readonly categoryStore = inject(CategoryStore);
private readonly transactionStore = inject(TransactionStore);
private readonly recurringStore = inject(RecurringStore);
readonly display = inject(DisplaySizeService);

isLoading = input.required<boolean>();
Expand All @@ -69,10 +73,14 @@ export class CategoriesComponent extends BaseComponent {
async openCreateTransactionDialog(): Promise<void> {
const result = await this.dialog.openNonModal<
CreateTransactionDialogData | undefined,
TransactionCreate | null
CreateTransactionDialogResult | null
>(CreateTransactionDialogComponent, undefined);
if (!result) return;
this.transactionStore.createTransaction(result);
if (result.isRecurring) {
this.recurringStore.createRecurringTransaction(result.result as RecurringTransactionCreate);
} else {
this.transactionStore.createTransaction(result.result as TransactionCreate);
}
}

calcPercentage(amount: number): number {
Expand Down
10 changes: 7 additions & 3 deletions frontend/Exence/src/app/private/dashboard/dashboard.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { CategoryStore } from '../transactions-and-categories/category.store';
import {
CreateTransactionDialogComponent,
CreateTransactionDialogData,
CreateTransactionDialogResult,
} from '../transactions-and-categories/create-transaction-dialog/create-transaction-dialog.component';
import { RecurringStore } from '../transactions-and-categories/recurring.store';
import { TransactionListComponent } from '../transactions-and-categories/transaction-list/transaction-list.component';
Expand Down Expand Up @@ -87,10 +88,13 @@ export class DashboardComponent extends BaseComponent {
async openCreateTransactionDialog(transactionType: TransactionType): Promise<void> {
const result = await this.dialog.openNonModal<
CreateTransactionDialogData | undefined,
TransactionCreate | RecurringTransactionCreate | null
CreateTransactionDialogResult | null
>(CreateTransactionDialogComponent, { type: transactionType });
if (!result) return;
if ('date' in result) this.transactionStore.createTransaction(result as TransactionCreate);
else this.recurringStore.createRecurringTransaction(result as RecurringTransactionCreate);
if (result.isRecurring) {
this.recurringStore.createRecurringTransaction(result.result as RecurringTransactionCreate);
} else {
this.transactionStore.createTransaction(result.result as TransactionCreate);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ export interface CreateTransactionDialogData {
isRecurring?: boolean;
}

export interface CreateTransactionDialogResult {
result: TransactionCreate | RecurringTransactionCreate;
isRecurring: boolean;
}

@Component({
selector: 'ex-create-transaction-dialog',
templateUrl: './create-transaction-dialog.component.html',
Expand Down Expand Up @@ -87,7 +92,7 @@ export interface CreateTransactionDialogData {
})
export class CreateTransactionDialogComponent extends DialogWithBaseComponent<
CreateTransactionDialogData | undefined,
TransactionCreate | RecurringTransactionCreate | null
CreateTransactionDialogResult | null
> {
private readonly fb = inject(NonNullableFormBuilder);
private readonly categoryService = inject(CategoryService);
Expand Down Expand Up @@ -302,7 +307,7 @@ export class CreateTransactionDialogComponent extends DialogWithBaseComponent<
exchangeRate: formValue.exchangeRate!,
} satisfies TransactionCreate;
}
this.dialogRef.submit(request);
this.dialogRef.submit({ result: request, isRecurring: this.isRecurring() });
}

localizeCurrency(currency: SupportedCurrency): string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { PagedResponse } from '../../../data-model/modules/common/PagedResponse'
import { ColumnDef, DataTableComponent, TableAction } from '../../../shared/data-table/data-table.component';
import { ExCellDirective } from '../../../shared/data-table/ex-cell.directive';
import { RecurringStore } from '../recurring.store';
import { TransactionStore } from '../transaction.store';
import { CategoryStore } from '../category.store';
import { DialogService } from '../../../shared/dialog/dialog.service';
import { SvgIcons } from '../../../shared/svg-icons/svg-icons';
Expand All @@ -17,6 +18,7 @@ import { CurrencyPipe } from '../../../shared/pipes/currency.pipe';
import {
CreateTransactionDialogComponent,
CreateTransactionDialogData,
CreateTransactionDialogResult,
} from '../create-transaction-dialog/create-transaction-dialog.component';
import { DisplaySizeService } from '../../../shared/display-size.service';
import { MatLabel } from '@angular/material/form-field';
Expand Down Expand Up @@ -48,6 +50,7 @@ import { DayOfWeek } from '../../../data-model/modules/transaction/DayOfWeek';
})
export class RecurringListComponent {
private readonly recurringStore = inject(RecurringStore);
private readonly transactionStore = inject(TransactionStore);
private readonly categoryStore = inject(CategoryStore);
private readonly dialog = inject(DialogService);
private readonly display = inject(DisplaySizeService);
Expand Down Expand Up @@ -134,12 +137,16 @@ export class RecurringListComponent {
async openCreate(): Promise<void> {
const result = await this.dialog.openNonModal<
CreateTransactionDialogData,
TransactionCreate | RecurringTransactionCreate | null
CreateTransactionDialogResult | null
>(
CreateTransactionDialogComponent,
this.type() ? { type: this.type()!, isRecurring: true } : { isRecurring: true },
);
if (!result) return;
this.recurringStore.createRecurringTransaction(result as RecurringTransactionCreate);
if (result.isRecurring) {
this.recurringStore.createRecurringTransaction(result.result as RecurringTransactionCreate);
} else {
this.transactionStore.createTransaction(result.result as TransactionCreate);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { booleanAttribute, Component, computed, inject, input } from '@angular/c
import { MatIconModule } from '@angular/material/icon';
import { MatTooltipModule } from '@angular/material/tooltip';
import { PagedResponse } from '../../../data-model/modules/common/PagedResponse';
import { RecurringTransactionCreate } from '../../../data-model/modules/transaction/RecurringTransactionCreate';
import { TransactionCreate } from '../../../data-model/modules/transaction/TransactionCreate';
import { TransactionGet } from '../../../data-model/modules/transaction/TransactionGet';
import { TransactionModel } from '../../../data-model/modules/transaction/TransactionModel';
Expand All @@ -19,11 +20,13 @@ import { CategoryStore } from '../category.store';
import {
CreateTransactionDialogComponent,
CreateTransactionDialogData,
CreateTransactionDialogResult,
} from '../create-transaction-dialog/create-transaction-dialog.component';
import {
EditTransactionDialogComponent,
EditTransactionDialogData,
} from '../edit-transaction-dialog/edit-transaction-dialog.component';
import { RecurringStore } from '../recurring.store';
import { TransactionStore } from '../transaction.store';
import { TransactionListDetailsComponent } from './transaction-list-details/transaction-list-details.component';
import { TranslocoService } from '@jsverse/transloco';
Expand All @@ -50,6 +53,7 @@ import { format } from 'date-fns';
})
export class TransactionListComponent {
private readonly transactionStore = inject(TransactionStore);
private readonly recurringStore = inject(RecurringStore);
private readonly categoryStore = inject(CategoryStore);
private readonly dialog = inject(DialogService);
private readonly currencyService = inject(CurrencyService);
Expand Down Expand Up @@ -135,10 +139,14 @@ export class TransactionListComponent {
async openCreate(): Promise<void> {
const result = await this.dialog.openNonModal<
CreateTransactionDialogData | undefined,
TransactionCreate | null
CreateTransactionDialogResult | null
>(CreateTransactionDialogComponent, this.type() ? { type: this.type()! } : undefined);
if (!result) return;
this.transactionStore.createTransaction(result as TransactionCreate);
if (result.isRecurring) {
this.recurringStore.createRecurringTransaction(result.result as RecurringTransactionCreate);
} else {
this.transactionStore.createTransaction(result.result as TransactionCreate);
}
}

private async dupliateTransaction(row: TransactionModel): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,9 @@ describe('CreateTransactionDialogComponent', () => {
fillRequiredFields();
component.form.controls.recurring.controls.isRecurring.setValue(false);
component.create();
expect(dialogSubmitSpy).toHaveBeenCalledWith(
const submitted = dialogSubmitSpy.calls.mostRecent().args[0];
expect(submitted.isRecurring).toBe(false);
expect(submitted.result).toEqual(
jasmine.objectContaining({
title: 'Test Transaction',
amount: 100,
Expand All @@ -385,9 +387,8 @@ describe('CreateTransactionDialogComponent', () => {
date: jasmine.any(String),
}),
);
const submitted = dialogSubmitSpy.calls.mostRecent().args[0];
expect(submitted.frequency).toBeUndefined();
expect(submitted.startDate).toBeUndefined();
expect(submitted.result.frequency).toBeUndefined();
expect(submitted.result.startDate).toBeUndefined();
});

it('should call dialogRef.submit with RecurringTransactionCreate when recurring', () => {
Expand All @@ -396,17 +397,18 @@ describe('CreateTransactionDialogComponent', () => {
component.form.controls.recurring.controls.configs.controls.frequency.setValue(RecurrenceFrequency.WEEKLY);
component.form.controls.recurring.controls.configs.controls.endCondition.setValue(EndCondition.NEVER);
component.create();
expect(dialogSubmitSpy).toHaveBeenCalledWith(
const submitted = dialogSubmitSpy.calls.mostRecent().args[0];
expect(submitted.isRecurring).toBe(true);
expect(submitted.result).toEqual(
jasmine.objectContaining({
frequency: RecurrenceFrequency.WEEKLY,
interval: jasmine.any(Number),
startDate: jasmine.any(String),
endCondition: EndCondition.NEVER,
}),
);
const submitted = dialogSubmitSpy.calls.mostRecent().args[0];
expect(submitted.date).toBeUndefined();
expect(submitted.exchangeRate).toBeUndefined();
expect(submitted.result.date).toBeUndefined();
expect(submitted.result.exchangeRate).toBeUndefined();
});

it('should include dayOfWeek when frequency is WEEKLY', () => {
Expand All @@ -415,7 +417,7 @@ describe('CreateTransactionDialogComponent', () => {
component.form.controls.recurring.controls.configs.controls.frequency.setValue(RecurrenceFrequency.WEEKLY);
component.create();
const submitted = dialogSubmitSpy.calls.mostRecent().args[0];
expect(submitted.dayOfWeek).toBeDefined();
expect(submitted.result.dayOfWeek).toBeDefined();
});

it('should NOT include dayOfWeek when frequency is MONTHLY', () => {
Expand All @@ -424,7 +426,7 @@ describe('CreateTransactionDialogComponent', () => {
component.form.controls.recurring.controls.configs.controls.frequency.setValue(RecurrenceFrequency.MONTHLY);
component.create();
const submitted = dialogSubmitSpy.calls.mostRecent().args[0];
expect(submitted.dayOfWeek).toBeUndefined();
expect(submitted.result.dayOfWeek).toBeUndefined();
});

it('should include dayOfMonth when frequency is MONTHLY', () => {
Expand All @@ -433,7 +435,7 @@ describe('CreateTransactionDialogComponent', () => {
component.form.controls.recurring.controls.configs.controls.frequency.setValue(RecurrenceFrequency.MONTHLY);
component.create();
const submitted = dialogSubmitSpy.calls.mostRecent().args[0];
expect(submitted.dayOfMonth).toBeDefined();
expect(submitted.result.dayOfMonth).toBeDefined();
});

it('should include endDate when endCondition is UNTIL_DATE', () => {
Expand All @@ -445,7 +447,7 @@ describe('CreateTransactionDialogComponent', () => {
component.form.controls.recurring.controls.configs.controls.endDate.setValue(futureDate);
component.create();
const submitted = dialogSubmitSpy.calls.mostRecent().args[0];
expect(submitted.endDate).toEqual(jasmine.any(String));
expect(submitted.result.endDate).toEqual(jasmine.any(String));
});

it('should include maxOccurrences when endCondition is AFTER_OCCURRENCES', () => {
Expand All @@ -457,7 +459,7 @@ describe('CreateTransactionDialogComponent', () => {
component.form.controls.recurring.controls.configs.controls.maxOccurrences.setValue(5);
component.create();
const submitted = dialogSubmitSpy.calls.mostRecent().args[0];
expect(submitted.maxOccurrences).toBe(5);
expect(submitted.result.maxOccurrences).toBe(5);
});
});

Expand Down
Loading