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:
Lorenz Hilpert
2025-11-14 13:09:58 +00:00
committed by Nino Righi
parent 5057d56532
commit e654a4d95e
20 changed files with 631 additions and 3 deletions

View File

@@ -10,3 +10,7 @@
[tabId]="processId$ | async"
class="mt-4"
/>
<crm-customer-card-transactions
[cardCode]="firstActiveCardCode()"
class="mt-8"
/>

View File

@@ -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) });
}
});
}
}