mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merged PR 2028: Commit 86563a73: ✨ feat(crm): add customer card transactions history feature
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
This commit is contained in:
committed by
Nino Righi
parent
5057d56532
commit
e654a4d95e
@@ -10,3 +10,7 @@
|
||||
[tabId]="processId$ | async"
|
||||
class="mt-4"
|
||||
/>
|
||||
<crm-customer-card-transactions
|
||||
[cardCode]="firstActiveCardCode()"
|
||||
class="mt-8"
|
||||
/>
|
||||
|
||||
@@ -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) });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<string | undefined>(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<LoyaltyBookingInfoDTO[] | undefined> => {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
@@ -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<BonusCardInfo[]>;
|
||||
}
|
||||
}
|
||||
|
||||
async fetchLoyaltyBookings(
|
||||
cardCode: string,
|
||||
abortSignal?: AbortSignal,
|
||||
): Promise<LoyaltyBookingInfoDTO[]> {
|
||||
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 [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
7
libs/crm/feature/customer-card-transactions/README.md
Normal file
7
libs/crm/feature/customer-card-transactions/README.md
Normal file
@@ -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.
|
||||
@@ -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: {},
|
||||
},
|
||||
];
|
||||
20
libs/crm/feature/customer-card-transactions/project.json
Normal file
20
libs/crm/feature/customer-card-transactions/project.json
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
1
libs/crm/feature/customer-card-transactions/src/index.ts
Normal file
1
libs/crm/feature/customer-card-transactions/src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { CrmFeatureCustomerCardTransactionsComponent } from './lib/crm-feature-customer-card-transactions/crm-feature-customer-card-transactions.component';
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<div class="flex flex-col gap-[24px] px-4">
|
||||
<h2 class="isa-text-body-1-bold text-isa-neutral-900">
|
||||
Letzte 5 Transaktionen des Kunden
|
||||
</h2>
|
||||
|
||||
@if (isLoading()) {
|
||||
<div class="text-isa-neutral-500 text-sm">Lade Transaktionen...</div>
|
||||
} @else if (error()) {
|
||||
<div class="text-isa-accent-red text-sm">
|
||||
Fehler beim Laden der Transaktionen
|
||||
</div>
|
||||
} @else if (!transactions()?.length) {
|
||||
<ui-empty-state
|
||||
title="Keine Transaktionen"
|
||||
description="Für diese Kundenkarte wurden noch keine Transaktionen erfasst"
|
||||
appearance="no-results"
|
||||
/>
|
||||
} @else {
|
||||
<table cdk-table [dataSource]="dataSource()" [trackBy]="trackByDate">
|
||||
<!-- Date -->
|
||||
<ng-container cdkColumnDef="date">
|
||||
<th cdk-header-cell *cdkHeaderCellDef>
|
||||
Datum
|
||||
</th>
|
||||
<td cdk-cell *cdkCellDef="let t" class="text-xs">
|
||||
{{ t.date | date: 'dd.MM.yyyy' }} <span class="text-isa-neutral-500">{{ t.date | date: 'HH:mm.ss' }}</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Type -->
|
||||
<ng-container cdkColumnDef="reason">
|
||||
<th cdk-header-cell *cdkHeaderCellDef>
|
||||
Buchungsart
|
||||
</th>
|
||||
<td cdk-cell *cdkCellDef="let t" class="text-xs">
|
||||
{{ t.reason || '-' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Amount -->
|
||||
<ng-container cdkColumnDef="amount">
|
||||
<th cdk-header-cell *cdkHeaderCellDef class="text-right">
|
||||
Umsatz
|
||||
</th>
|
||||
<td cdk-cell *cdkCellDef="let t" class="text-xs text-right">
|
||||
@if (t.type === 'BURN') {-}{{ t.amount || 0 | number: '1.2-2' : 'de-DE' }} EUR
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Reference -->
|
||||
<ng-container cdkColumnDef="reference">
|
||||
<th cdk-header-cell *cdkHeaderCellDef class="text-right">
|
||||
Bon-Nummer
|
||||
</th>
|
||||
<td cdk-cell *cdkCellDef="let t" class="text-xs text-right">
|
||||
{{ t.reference || '-' }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Points -->
|
||||
<ng-container cdkColumnDef="points">
|
||||
<th cdk-header-cell *cdkHeaderCellDef class="text-right">
|
||||
Lesepunkte
|
||||
</th>
|
||||
<td cdk-cell *cdkCellDef="let t" class="text-xs text-right">
|
||||
@if (t.type === 'EARN') {
|
||||
<span class="text-isa-accent-green inline-flex items-center gap-1">
|
||||
{{ t.points }}
|
||||
<ng-icon name="isaActionPolygonUp" size="0.75rem" />
|
||||
</span>
|
||||
} @else if (t.type === 'BURN') {
|
||||
<span class="text-isa-accent-red inline-flex items-center gap-1">
|
||||
-{{ t.points }}
|
||||
<ng-icon name="isaActionPolygonDown" size="0.75rem" />
|
||||
</span>
|
||||
} @else {
|
||||
{{ t.points }}
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Header Row -->
|
||||
<tr
|
||||
cdk-header-row
|
||||
*cdkHeaderRowDef="displayedColumns"
|
||||
></tr>
|
||||
|
||||
<!-- Data Rows -->
|
||||
<tr
|
||||
cdk-row
|
||||
*cdkRowDef="let row; columns: displayedColumns"
|
||||
></tr>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
@@ -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<CrmFeatureCustomerCardTransactionsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [CrmFeatureCustomerCardTransactionsComponent],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(
|
||||
CrmFeatureCustomerCardTransactionsComponent,
|
||||
);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -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<string | undefined>(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<keyof LoyaltyBookingInfoDTO> = [
|
||||
'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 });
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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(),
|
||||
);
|
||||
30
libs/crm/feature/customer-card-transactions/tsconfig.json
Normal file
30
libs/crm/feature/customer-card-transactions/tsconfig.json
Normal file
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -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"]
|
||||
}
|
||||
35
libs/crm/feature/customer-card-transactions/vite.config.mts
Normal file
35
libs/crm/feature/customer-card-transactions/vite.config.mts
Normal file
@@ -0,0 +1,35 @@
|
||||
/// <reference types='vitest' />
|
||||
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'],
|
||||
},
|
||||
},
|
||||
}));
|
||||
@@ -12,6 +12,12 @@ export const isaActionChevronRight =
|
||||
export const isaActionChevronLeft =
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" clip-rule="evenodd" d="M15.7071 5.29289C16.0976 5.68342 16.0976 6.31658 15.7071 6.70711L10.4142 12L15.7071 17.2929C16.0976 17.6834 16.0976 18.3166 15.7071 18.7071C15.3166 19.0976 14.6834 19.0976 14.2929 18.7071L8.29289 12.7071C7.90237 12.3166 7.90237 11.6834 8.29289 11.2929L14.2929 5.29289C14.6834 4.90237 15.3166 4.90237 15.7071 5.29289Z" fill="currentColor"/> </svg>';
|
||||
|
||||
export const isaActionPolygonDown =
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" width="11" height="7" viewBox="0 0 11 7" fill="currentColor"><path d="M6.20628 6.61478C5.80916 7.05483 5.11859 7.05482 4.72148 6.61475L0.259338 1.66997C-0.321102 1.02675 0.135351 2.08819e-05 1.00175 2.09576e-05L9.92633 2.17379e-05C10.7927 2.18136e-05 11.2492 1.02678 10.6687 1.66999L6.20628 6.61478Z" fill="currentColor"/></svg>';
|
||||
|
||||
export const isaActionPolygonUp =
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" width="11" height="7" viewBox="0 0 11 7" fill="currentColor"><path d="M4.72148 0.385223C5.11859 -0.0548283 5.80916 -0.0548171 6.20628 0.385247L10.6687 5.33003C11.2492 5.97325 10.7927 7 9.92633 7L1.00175 7C0.135351 7 -0.321102 5.97322 0.259338 5.33001L4.72148 0.385223Z" fill="currentColor"/></svg>';
|
||||
|
||||
export const isaActionMinus =
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"> <path fill-rule="evenodd" clip-rule="evenodd" d="M4 12C4 11.4477 4.44772 11 5 11H19C19.5523 11 20 11.4477 20 12C20 12.5523 19.5523 13 19 13H5C4.44772 13 4 12.5523 4 12Z" fill="currentColor"/></svg>';
|
||||
|
||||
|
||||
@@ -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"
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user