From e654a4d95e00062e45b93ea569794cbff343a707 Mon Sep 17 00:00:00 2001 From: Lorenz Hilpert Date: Fri, 14 Nov 2025 13:09:58 +0000 Subject: [PATCH] =?UTF-8?q?Merged=20PR=202028:=20Commit=2086563a73:=20?= =?UTF-8?q?=E2=9C=A8=20feat(crm):=20add=20customer=20card=20transactions?= =?UTF-8?q?=20history=20feature?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 86563a73: ✨ feat(crm): add customer card transactions history feature Implements #5316 - Service Portal History displaying last 5 loyalty card transactions **New feature library:** - Created @isa/crm/feature/customer-card-transactions with CDK table component - Shows transactions for first activated customer loyalty card - Displays: Date, Transaction type (reason), Amount (EUR), Receipt number, Points **Data layer:** - Added CustomerCardTransactionsResource with reactive resource pattern - Extended CrmSearchService with fetchLoyaltyBookings() method - Uses LoyaltyCardService.LoyaltyCardListBookings() API endpoint **UI/UX:** - CDK table with ISA design system colors - Header: 48px height, rounded corners (26px), neutral-400 background - Visual indicators: Green up arrow (EARN), Red down arrow (BURN) - German locale formatting (dd.MM.yyyy HH:mm.ss) - Full-width table layout with proper spacing (24px between rows) - Empty state when no transactions available **Icons:** - Added isaActionPolygonUp and isaActionPolygonDown to @isa/icons **Integration:** - Integrated into kundenkarte-main-view component - Automatically loads transactions for first active card Related work items: #5316 --- .../kundenkarte-main-view.component.html | 4 + .../kundenkarte-main-view.component.ts | 44 ++++++++- .../customer-card-transactions.resource.ts | 93 ++++++++++++++++++ .../data-access/src/lib/resources/index.ts | 1 + .../src/lib/services/crm-search.service.ts | 34 ++++++- .../customer-card-transactions/README.md | 7 ++ .../eslint.config.cjs | 34 +++++++ .../customer-card-transactions/project.json | 20 ++++ .../customer-card-transactions/src/index.ts | 1 + ...e-customer-card-transactions.component.css | 52 ++++++++++ ...-customer-card-transactions.component.html | 95 +++++++++++++++++++ ...stomer-card-transactions.component.spec.ts | 23 +++++ ...re-customer-card-transactions.component.ts | 83 ++++++++++++++++ .../src/test-setup.ts | 13 +++ .../customer-card-transactions/tsconfig.json | 30 ++++++ .../tsconfig.lib.json | 27 ++++++ .../tsconfig.spec.json | 29 ++++++ .../vite.config.mts | 35 +++++++ libs/icons/src/lib/icons.ts | 6 ++ tsconfig.base.json | 3 + 20 files changed, 631 insertions(+), 3 deletions(-) create mode 100644 libs/crm/data-access/src/lib/resources/customer-card-transactions.resource.ts create mode 100644 libs/crm/feature/customer-card-transactions/README.md create mode 100644 libs/crm/feature/customer-card-transactions/eslint.config.cjs create mode 100644 libs/crm/feature/customer-card-transactions/project.json create mode 100644 libs/crm/feature/customer-card-transactions/src/index.ts create mode 100644 libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.css create mode 100644 libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.html create mode 100644 libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.spec.ts create mode 100644 libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.ts create mode 100644 libs/crm/feature/customer-card-transactions/src/test-setup.ts create mode 100644 libs/crm/feature/customer-card-transactions/tsconfig.json create mode 100644 libs/crm/feature/customer-card-transactions/tsconfig.lib.json create mode 100644 libs/crm/feature/customer-card-transactions/tsconfig.spec.json create mode 100644 libs/crm/feature/customer-card-transactions/vite.config.mts diff --git a/apps/isa-app/src/page/customer/customer-search/kundenkarte-main-view/kundenkarte-main-view.component.html b/apps/isa-app/src/page/customer/customer-search/kundenkarte-main-view/kundenkarte-main-view.component.html index 1d9b19668..6ffa38ca4 100644 --- a/apps/isa-app/src/page/customer/customer-search/kundenkarte-main-view/kundenkarte-main-view.component.html +++ b/apps/isa-app/src/page/customer/customer-search/kundenkarte-main-view/kundenkarte-main-view.component.html @@ -10,3 +10,7 @@ [tabId]="processId$ | async" class="mt-4" /> + diff --git a/apps/isa-app/src/page/customer/customer-search/kundenkarte-main-view/kundenkarte-main-view.component.ts b/apps/isa-app/src/page/customer/customer-search/kundenkarte-main-view/kundenkarte-main-view.component.ts index c6c65d22e..dae6cc60d 100644 --- a/apps/isa-app/src/page/customer/customer-search/kundenkarte-main-view/kundenkarte-main-view.component.ts +++ b/apps/isa-app/src/page/customer/customer-search/kundenkarte-main-view/kundenkarte-main-view.component.ts @@ -1,10 +1,19 @@ -import { Component, ChangeDetectionStrategy, inject } from '@angular/core'; +import { + Component, + ChangeDetectionStrategy, + inject, + computed, + effect, +} from '@angular/core'; import { CustomerSearchStore } from '../store'; import { ActivatedRoute } from '@angular/router'; import { map } from 'rxjs/operators'; import { AsyncPipe } from '@angular/common'; import { CustomerMenuComponent } from '../../components/customer-menu'; import { CustomerLoyaltyCardsComponent } from '@isa/crm/feature/customer-loyalty-cards'; +import { CrmFeatureCustomerCardTransactionsComponent } from '@isa/crm/feature/customer-card-transactions'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { CustomerBonusCardsResource } from '@isa/crm/data-access'; @Component({ selector: 'page-customer-kundenkarte-main-view', @@ -12,15 +21,46 @@ import { CustomerLoyaltyCardsComponent } from '@isa/crm/feature/customer-loyalty styleUrls: ['kundenkarte-main-view.component.css'], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'page-customer-kundenkarte-main-view' }, - imports: [CustomerMenuComponent, AsyncPipe, CustomerLoyaltyCardsComponent], + imports: [ + CustomerMenuComponent, + AsyncPipe, + CustomerLoyaltyCardsComponent, + CrmFeatureCustomerCardTransactionsComponent, + ], + providers: [CustomerBonusCardsResource], }) export class KundenkarteMainViewComponent { private _store = inject(CustomerSearchStore); private _activatedRoute = inject(ActivatedRoute); + private _bonusCardsResource = inject(CustomerBonusCardsResource); customerId$ = this._activatedRoute.params.pipe( map((params) => params.customerId), ); processId$ = this._store.processId$; + + /** + * Convert customerId observable to signal for reactive usage + */ + readonly customerId = toSignal(this.customerId$); + + /** + * Get the first active card code + */ + readonly firstActiveCardCode = computed(() => { + const cards = this._bonusCardsResource.resource.value(); + const firstActiveCard = cards?.find((card) => card.isActive); + return firstActiveCard?.code; + }); + + constructor() { + // Load bonus cards when customerId changes + effect(() => { + const customerId = this.customerId(); + if (customerId) { + this._bonusCardsResource.params({ customerId: Number(customerId) }); + } + }); + } } diff --git a/libs/crm/data-access/src/lib/resources/customer-card-transactions.resource.ts b/libs/crm/data-access/src/lib/resources/customer-card-transactions.resource.ts new file mode 100644 index 000000000..aee66dfb0 --- /dev/null +++ b/libs/crm/data-access/src/lib/resources/customer-card-transactions.resource.ts @@ -0,0 +1,93 @@ +import { Injectable, inject, resource, signal, computed } from '@angular/core'; +import { logger } from '@isa/core/logging'; +import { CrmSearchService } from '@isa/crm/data-access'; +import { LoyaltyBookingInfoDTO } from '@generated/swagger/crm-api'; + +/** + * Resource for loading customer loyalty card transactions. + * + * Provides reactive loading of the last 5 transactions for a given card code. + * Card code can be changed dynamically via `params()` method. + * + * **Note:** This resource should be provided at the component level, + * not in root. Provide it in the `providers` array of the component + * that needs scoped access to transactions. + * + * @example + * ```typescript + * @Component({ + * providers: [CustomerCardTransactionsResource], + * }) + * export class MyFeatureComponent { + * #transactionsResource = inject(CustomerCardTransactionsResource); + * + * transactions = this.#transactionsResource.resource.value; + * isLoading = this.#transactionsResource.resource.isLoading; + * + * loadTransactions(cardCode: string) { + * this.#transactionsResource.params({ cardCode }); + * } + * } + * ``` + */ +@Injectable() +export class CustomerCardTransactionsResource { + readonly #crmSearchService = inject(CrmSearchService); + readonly #logger = logger(() => ({ + context: 'CustomerCardTransactionsResource', + })); + + readonly #cardCode = signal(undefined); + + /** + * Resource that loads transactions based on current parameters. + * + * Exposes: + * - `value()` - Array of transactions or undefined + * - `isLoading()` - Loading state + * - `error()` - Error state + * - `status()` - Current status ('idle' | 'loading' | 'resolved' | 'error') + */ + readonly resource = resource({ + params: computed(() => ({ cardCode: this.#cardCode() })), + loader: async ({ + params, + abortSignal, + }): Promise => { + const { cardCode } = params; + + if (!cardCode) { + this.#logger.debug('No cardCode provided, skipping load'); + return undefined; + } + + this.#logger.debug('Loading loyalty card transactions', () => ({ + cardCode, + })); + + const transactions = await this.#crmSearchService.fetchLoyaltyBookings( + cardCode, + abortSignal, + ); + + this.#logger.debug('Transactions loaded', () => ({ + cardCode, + count: transactions.length, + })); + + return transactions; + }, + defaultValue: undefined, + }); + + /** + * Update resource parameters to trigger a reload. + * + * @param params - Parameters for loading transactions + * @param params.cardCode - Card code to load transactions for (undefined clears data) + */ + params(params: { cardCode?: string }): void { + this.#logger.debug('Updating params', () => params); + this.#cardCode.set(params.cardCode); + } +} diff --git a/libs/crm/data-access/src/lib/resources/index.ts b/libs/crm/data-access/src/lib/resources/index.ts index a74710f64..cd5e8b7af 100644 --- a/libs/crm/data-access/src/lib/resources/index.ts +++ b/libs/crm/data-access/src/lib/resources/index.ts @@ -1,5 +1,6 @@ export * from './country.resource'; export * from './customer-bonus-cards.resource'; +export * from './customer-card-transactions.resource'; export * from './customer-payer-address.resource'; export * from './primary-customer-card.resource'; export * from './customer-shipping-address.resource'; diff --git a/libs/crm/data-access/src/lib/services/crm-search.service.ts b/libs/crm/data-access/src/lib/services/crm-search.service.ts index e393d70ad..302ce37cb 100644 --- a/libs/crm/data-access/src/lib/services/crm-search.service.ts +++ b/libs/crm/data-access/src/lib/services/crm-search.service.ts @@ -1,5 +1,9 @@ import { inject, Injectable } from '@angular/core'; -import { CustomerService } from '@generated/swagger/crm-api'; +import { + CustomerService, + LoyaltyCardService, + LoyaltyBookingInfoDTO, +} from '@generated/swagger/crm-api'; import { Customer, FetchCustomerCardsInput, @@ -19,6 +23,7 @@ import { logger } from '@isa/core/logging'; @Injectable({ providedIn: 'root' }) export class CrmSearchService { #customerService = inject(CustomerService); + #loyaltyCardService = inject(LoyaltyCardService); #logger = logger(() => ({ service: 'CrmSearchService', })); @@ -72,4 +77,31 @@ export class CrmSearchService { return [] as unknown as ResponseArgs; } } + + async fetchLoyaltyBookings( + cardCode: string, + abortSignal?: AbortSignal, + ): Promise { + this.#logger.info('Fetching loyalty bookings from API'); + + let req$ = this.#loyaltyCardService + .LoyaltyCardListBookings({ cardCode }) + .pipe(catchResponseArgsErrorPipe()); + + if (abortSignal) { + req$ = req$.pipe(takeUntilAborted(abortSignal)); + } + + try { + const res = await firstValueFrom(req$); + this.#logger.debug('Successfully fetched loyalty bookings'); + + const transactions = res?.result?.data || []; + + return transactions; + } catch (error) { + this.#logger.error('Error fetching loyalty bookings', error); + return []; + } + } } diff --git a/libs/crm/feature/customer-card-transactions/README.md b/libs/crm/feature/customer-card-transactions/README.md new file mode 100644 index 000000000..833ebda32 --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/README.md @@ -0,0 +1,7 @@ +# crm-feature-customer-card-transactions + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test crm-feature-customer-card-transactions` to execute the unit tests. diff --git a/libs/crm/feature/customer-card-transactions/eslint.config.cjs b/libs/crm/feature/customer-card-transactions/eslint.config.cjs new file mode 100644 index 000000000..a6b77027c --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/eslint.config.cjs @@ -0,0 +1,34 @@ +const nx = require('@nx/eslint-plugin'); +const baseConfig = require('../../../../eslint.config.js'); + +module.exports = [ + ...baseConfig, + ...nx.configs['flat/angular'], + ...nx.configs['flat/angular-template'], + { + files: ['**/*.ts'], + rules: { + '@angular-eslint/directive-selector': [ + 'error', + { + type: 'attribute', + prefix: 'crm', + style: 'camelCase', + }, + ], + '@angular-eslint/component-selector': [ + 'error', + { + type: 'element', + prefix: 'crm', + style: 'kebab-case', + }, + ], + }, + }, + { + files: ['**/*.html'], + // Override or add rules here + rules: {}, + }, +]; diff --git a/libs/crm/feature/customer-card-transactions/project.json b/libs/crm/feature/customer-card-transactions/project.json new file mode 100644 index 000000000..827aa61a0 --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/project.json @@ -0,0 +1,20 @@ +{ + "name": "crm-feature-customer-card-transactions", + "$schema": "../../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/crm/feature/customer-card-transactions/src", + "prefix": "crm", + "projectType": "library", + "tags": [], + "targets": { + "test": { + "executor": "@nx/vite:test", + "outputs": ["{options.reportsDirectory}"], + "options": { + "reportsDirectory": "../../../../coverage/libs/crm/feature/customer-card-transactions" + } + }, + "lint": { + "executor": "@nx/eslint:lint" + } + } +} diff --git a/libs/crm/feature/customer-card-transactions/src/index.ts b/libs/crm/feature/customer-card-transactions/src/index.ts new file mode 100644 index 000000000..77bbcd353 --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/src/index.ts @@ -0,0 +1 @@ +export { CrmFeatureCustomerCardTransactionsComponent } from './lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component'; diff --git a/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.css b/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.css new file mode 100644 index 000000000..f150986a0 --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.css @@ -0,0 +1,52 @@ +/* Table */ +.cdk-table { + width: 100%; + border-spacing: 0 1.5rem; +} + +/* Header Row */ +.cdk-header-row { + background-color: #CED4DA; + height: 48px; + display: table-row; +} + +/* Header Cells */ +.cdk-header-cell { + font-size: 12px; + font-weight: 700; + color: #212529; + padding: 16px 8px; + background-color: #CED4DA; +} + +.cdk-header-cell:first-child { + border-top-left-radius: 26px; + border-bottom-left-radius: 26px; + padding-left: 24px; +} + +.cdk-header-cell:last-child { + border-top-right-radius: 26px; + border-bottom-right-radius: 26px; + padding-right: 24px; +} + +/* Data Rows */ +.cdk-row { + display: table-row; +} + +/* Data Cells */ +.cdk-cell { + color: #212529; + padding: 12px 8px; +} + +.cdk-cell:first-child { + padding-left: 24px; +} + +.cdk-cell:last-child { + padding-right: 24px; +} diff --git a/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.html b/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.html new file mode 100644 index 000000000..1750bed30 --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.html @@ -0,0 +1,95 @@ +
+

+ Letzte 5 Transaktionen des Kunden +

+ + @if (isLoading()) { +
Lade Transaktionen...
+ } @else if (error()) { +
+ Fehler beim Laden der Transaktionen +
+ } @else if (!transactions()?.length) { + + } @else { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Datum + + {{ t.date | date: 'dd.MM.yyyy' }} {{ t.date | date: 'HH:mm.ss' }} + + Buchungsart + + {{ t.reason || '-' }} + + Umsatz + + @if (t.type === 'BURN') {-}{{ t.amount || 0 | number: '1.2-2' : 'de-DE' }} EUR + + Bon-Nummer + + {{ t.reference || '-' }} + + Lesepunkte + + @if (t.type === 'EARN') { + + {{ t.points }} + + + } @else if (t.type === 'BURN') { + + -{{ t.points }} + + + } @else { + {{ t.points }} + } +
+ } +
diff --git a/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.spec.ts b/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.spec.ts new file mode 100644 index 000000000..396a85cf9 --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { CrmFeatureCustomerCardTransactionsComponent } from './crm-feature-customer-card-transactions.component'; + +describe('CrmFeatureCustomerCardTransactionsComponent', () => { + let component: CrmFeatureCustomerCardTransactionsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [CrmFeatureCustomerCardTransactionsComponent], + }).compileComponents(); + + fixture = TestBed.createComponent( + CrmFeatureCustomerCardTransactionsComponent, + ); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.ts b/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.ts new file mode 100644 index 000000000..ae6af353a --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/src/lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component.ts @@ -0,0 +1,83 @@ +import { + Component, + ChangeDetectionStrategy, + inject, + input, + effect, + computed, +} from '@angular/core'; +import { DatePipe, DecimalPipe } from '@angular/common'; +import { CdkTableModule } from '@angular/cdk/table'; +import { NgIconComponent, provideIcons } from '@ng-icons/core'; +import { isaActionPolygonUp, isaActionPolygonDown } from '@isa/icons'; +import { logger } from '@isa/core/logging'; +import { EmptyStateComponent } from '@isa/ui/empty-state'; +import { CustomerCardTransactionsResource } from '@isa/crm/data-access'; +import { LoyaltyBookingInfoDTO } from '@generated/swagger/crm-api'; + +@Component({ + selector: 'crm-customer-card-transactions', + imports: [ + DatePipe, + DecimalPipe, + CdkTableModule, + NgIconComponent, + EmptyStateComponent, + ], + providers: [ + CustomerCardTransactionsResource, + provideIcons({ isaActionPolygonUp, isaActionPolygonDown }), + ], + templateUrl: './crm-feature-customer-card-transactions.component.html', + styleUrl: './crm-feature-customer-card-transactions.component.css', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class CrmFeatureCustomerCardTransactionsComponent { + readonly #logger = logger(() => ({ + component: 'CrmFeatureCustomerCardTransactionsComponent', + })); + readonly #transactionsResource = inject(CustomerCardTransactionsResource); + + /** + * Card code to load transactions for. + * Should be the code of the first activated card. + */ + readonly cardCode = input(undefined); + + /** + * Exposed resource signals for template + */ + readonly transactions = this.#transactionsResource.resource.value; + readonly isLoading = this.#transactionsResource.resource.isLoading; + readonly error = this.#transactionsResource.resource.error; + + /** + * Data source for CDK table - defaults to empty array when undefined + */ + readonly dataSource = computed(() => this.transactions()?.slice(0, 5) ?? []); + + /** + * Column definitions for the table + */ + readonly displayedColumns: Array = [ + 'date', + 'reason', + 'amount', + 'reference', + 'points', + ]; + + /** + * Track by function for performance + */ + readonly trackByDate = (_index: number, item: { date: Date }) => item.date; + + constructor() { + // React to cardCode input changes + effect(() => { + const code = this.cardCode(); + this.#logger.debug('Card code changed', () => ({ cardCode: code })); + this.#transactionsResource.params({ cardCode: code }); + }); + } +} diff --git a/libs/crm/feature/customer-card-transactions/src/test-setup.ts b/libs/crm/feature/customer-card-transactions/src/test-setup.ts new file mode 100644 index 000000000..cebf5ae72 --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/src/test-setup.ts @@ -0,0 +1,13 @@ +import '@angular/compiler'; +import '@analogjs/vitest-angular/setup-zone'; + +import { + BrowserTestingModule, + platformBrowserTesting, +} from '@angular/platform-browser/testing'; +import { getTestBed } from '@angular/core/testing'; + +getTestBed().initTestEnvironment( + BrowserTestingModule, + platformBrowserTesting(), +); diff --git a/libs/crm/feature/customer-card-transactions/tsconfig.json b/libs/crm/feature/customer-card-transactions/tsconfig.json new file mode 100644 index 000000000..06f8b89a6 --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/tsconfig.json @@ -0,0 +1,30 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "importHelpers": true, + "moduleResolution": "bundler", + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "module": "preserve" + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "typeCheckHostBindings": true, + "strictTemplates": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/libs/crm/feature/customer-card-transactions/tsconfig.lib.json b/libs/crm/feature/customer-card-transactions/tsconfig.lib.json new file mode 100644 index 000000000..9259117c2 --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/tsconfig.lib.json @@ -0,0 +1,27 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": [ + "src/**/*.spec.ts", + "src/test-setup.ts", + "jest.config.ts", + "src/**/*.test.ts", + "vite.config.ts", + "vite.config.mts", + "vitest.config.ts", + "vitest.config.mts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx" + ], + "include": ["src/**/*.ts"] +} diff --git a/libs/crm/feature/customer-card-transactions/tsconfig.spec.json b/libs/crm/feature/customer-card-transactions/tsconfig.spec.json new file mode 100644 index 000000000..b2f92f3ec --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/tsconfig.spec.json @@ -0,0 +1,29 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../../dist/out-tsc", + "types": [ + "vitest/globals", + "vitest/importMeta", + "vite/client", + "node", + "vitest" + ] + }, + "include": [ + "vite.config.ts", + "vite.config.mts", + "vitest.config.ts", + "vitest.config.mts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ], + "files": ["src/test-setup.ts"] +} diff --git a/libs/crm/feature/customer-card-transactions/vite.config.mts b/libs/crm/feature/customer-card-transactions/vite.config.mts new file mode 100644 index 000000000..cf3280ebe --- /dev/null +++ b/libs/crm/feature/customer-card-transactions/vite.config.mts @@ -0,0 +1,35 @@ +/// +import { defineConfig } from 'vite'; +import angular from '@analogjs/vite-plugin-angular'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; +import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin'; + +export default +// @ts-expect-error - Vitest reporter tuple types have complex inference issues +defineConfig(() => ({ + root: __dirname, + cacheDir: + '../../../../node_modules/.vite/libs/crm/feature/customer-card-transactions', + plugins: [angular(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])], + // Uncomment this if you are using workers. + // worker: { + // plugins: [ nxViteTsPaths() ], + // }, + test: { + watch: false, + globals: true, + environment: 'jsdom', + include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + setupFiles: ['src/test-setup.ts'], + reporters: [ + 'default', + ['junit', { outputFile: '../../../../testresults/junit-crm-feature-customer-card-transactions.xml' }], + ], + coverage: { + reportsDirectory: + '../../../../coverage/libs/crm/feature/customer-card-transactions', + provider: 'v8' as const, + reporter: ['text', 'cobertura'], + }, + }, +})); diff --git a/libs/icons/src/lib/icons.ts b/libs/icons/src/lib/icons.ts index 0f91e76bb..a6a914757 100644 --- a/libs/icons/src/lib/icons.ts +++ b/libs/icons/src/lib/icons.ts @@ -12,6 +12,12 @@ export const isaActionChevronRight = export const isaActionChevronLeft = ' '; +export const isaActionPolygonDown = + ''; + +export const isaActionPolygonUp = + ''; + export const isaActionMinus = ' '; diff --git a/tsconfig.base.json b/tsconfig.base.json index a68ceace0..92ad5779b 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -69,6 +69,9 @@ "@isa/core/storage": ["libs/core/storage/src/index.ts"], "@isa/core/tabs": ["libs/core/tabs/src/index.ts"], "@isa/crm/data-access": ["libs/crm/data-access/src/index.ts"], + "@isa/crm/feature/customer-card-transactions": [ + "libs/crm/feature/customer-card-transactions/src/index.ts" + ], "@isa/crm/feature/customer-loyalty-cards": [ "libs/crm/feature/customer-loyalty-cards/src/index.ts" ],