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 19229a385..14e4a1e2e 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 @@ -9,28 +9,30 @@ [customerId]="customerId$ | async" [tabId]="processId$ | async" (navigateToPraemienshop)="onNavigateToPraemienshop()" + (cardUpdated)="reloadCardTransactionsAndCards()" class="mt-4" /> -@let cardCode = firstActiveCardCode(); +@let activeCardCode = firstActiveCardCode(); -@if (cardCode) { +@if (activeCardCode) { - } + + { + const cards = this.#bonusCardsResource.resource.value(); + const firstCard = cards?.[0]; + return firstCard?.code; + }); + /** * Get the first active card code */ diff --git a/libs/crm/feature/customer-bon-redemption/src/lib/crm-feature-customer-bon-redemption/components/bon-input-field/bon-input-field.component.html b/libs/crm/feature/customer-bon-redemption/src/lib/crm-feature-customer-bon-redemption/components/bon-input-field/bon-input-field.component.html index 009dcd46f..65ec2b7b9 100644 --- a/libs/crm/feature/customer-bon-redemption/src/lib/crm-feature-customer-bon-redemption/components/bon-input-field/bon-input-field.component.html +++ b/libs/crm/feature/customer-bon-redemption/src/lib/crm-feature-customer-bon-redemption/components/bon-input-field/bon-input-field.component.html @@ -10,7 +10,7 @@ [ngModel]="store.bonNumber()" (ngModelChange)="onBonNumberChange($event)" required - placeholder="Bon Nummer / Rechnungs-Nummer (HUG.de)*" + placeholder="Bon Nummer" data-what="bon-number-input" data-which="customer-loyalty" aria-label="Bon Nummer eingeben" diff --git a/libs/crm/feature/customer-loyalty-cards/src/lib/components/add-customer-card/add-customer-card.component.ts b/libs/crm/feature/customer-loyalty-cards/src/lib/components/add-customer-card/add-customer-card.component.ts index 0f82892f2..72b19ce04 100644 --- a/libs/crm/feature/customer-loyalty-cards/src/lib/components/add-customer-card/add-customer-card.component.ts +++ b/libs/crm/feature/customer-loyalty-cards/src/lib/components/add-customer-card/add-customer-card.component.ts @@ -2,8 +2,7 @@ import { ChangeDetectionStrategy, Component, inject, - input, - OnDestroy, + output, } from '@angular/core'; import { Validators } from '@angular/forms'; import { logger } from '@isa/core/logging'; @@ -22,8 +21,7 @@ import { firstValueFrom } from 'rxjs'; changeDetection: ChangeDetectionStrategy.OnPush, imports: [TextButtonComponent], }) -export class AddCustomerCardComponent implements OnDestroy { - #reloadTimeoutId?: ReturnType; +export class AddCustomerCardComponent { #logger = logger(() => ({ component: 'AddCustomerCardComponent', })); @@ -34,6 +32,12 @@ export class AddCustomerCardComponent implements OnDestroy { #textDialog = injectTextInputDialog(); #feedbackDialog = injectFeedbackDialog(); + /** + * Event emitted when a card has been successfully added. + * Parent should reload cards and transactions. + */ + readonly cardAdded = output(); + async addCardDialog() { this.#logger.debug('Opening add card dialog'); const dialogRef = this.#textDialog({ @@ -52,7 +56,6 @@ export class AddCustomerCardComponent implements OnDestroy { ], onConfirm: async (cardCode: string) => { await this.addCard(cardCode); - this.reloadCards(); }, }, width: '30rem', @@ -62,6 +65,7 @@ export class AddCustomerCardComponent implements OnDestroy { if (dialogResult?.inputValue) { this.feedback(); + this.cardAdded.emit(); } } @@ -90,16 +94,4 @@ export class AddCustomerCardComponent implements OnDestroy { }); this.#logger.info('Adding customer card complete', () => ({ cardCode })); } - - reloadCards() { - this.#reloadTimeoutId = setTimeout(() => { - this.#bonusCardsResource.resource.reload(); - }, 500); - } - - ngOnDestroy(): void { - if (this.#reloadTimeoutId) { - clearTimeout(this.#reloadTimeoutId); - } - } } diff --git a/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-card/customer-card.component.html b/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-card/customer-card.component.html index 47f65d600..41c847872 100644 --- a/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-card/customer-card.component.html +++ b/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-card/customer-card.component.html @@ -48,6 +48,7 @@ diff --git a/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-card/customer-card.component.ts b/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-card/customer-card.component.ts index bc6a45edd..910fba544 100644 --- a/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-card/customer-card.component.ts +++ b/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-card/customer-card.component.ts @@ -1,4 +1,9 @@ -import { ChangeDetectionStrategy, Component, input } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + input, + output, +} from '@angular/core'; import { BonusCardInfo } from '@isa/crm/data-access'; import { BarcodeComponent } from '@isa/shared/barcode'; import { LockCustomerCardComponent } from '../lock-customer-card/lock-customer-card.component'; @@ -35,6 +40,12 @@ export class CustomerCardComponent { */ readonly card = input.required(); + /** + * Event emitted when a card has been successfully locked or unlocked. + * Parent should reload cards and transactions. + */ + readonly cardLocked = output(); + /** * Barcode dimensions in rem, converted to pixels for JsBarcode. * Base: 1rem = 16px diff --git a/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-cards-carousel/customer-cards-carousel.component.html b/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-cards-carousel/customer-cards-carousel.component.html index 4686bfe7d..f9e5ba579 100644 --- a/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-cards-carousel/customer-cards-carousel.component.html +++ b/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-cards-carousel/customer-cards-carousel.component.html @@ -6,7 +6,7 @@ [padding]="'0.75rem 0.5rem'" > @for (card of sortedCards(); track card.code) { - + } diff --git a/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-cards-carousel/customer-cards-carousel.component.ts b/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-cards-carousel/customer-cards-carousel.component.ts index bb84a6bc2..33ba03407 100644 --- a/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-cards-carousel/customer-cards-carousel.component.ts +++ b/libs/crm/feature/customer-loyalty-cards/src/lib/components/customer-cards-carousel/customer-cards-carousel.component.ts @@ -33,6 +33,12 @@ export class CustomerCardsCarouselComponent { */ readonly cards = input.required(); + /** + * Event emitted when a card has been successfully locked or unlocked. + * Parent should reload cards and transactions. + */ + readonly cardLocked = output(); + /** * Cards sorted with blocked cards at the end. * Per Figma annotation: "gesperrte Karte immer nach hinten" diff --git a/libs/crm/feature/customer-loyalty-cards/src/lib/components/lock-customer-card/lock-customer-card.component.ts b/libs/crm/feature/customer-loyalty-cards/src/lib/components/lock-customer-card/lock-customer-card.component.ts index 94134616a..27e051299 100644 --- a/libs/crm/feature/customer-loyalty-cards/src/lib/components/lock-customer-card/lock-customer-card.component.ts +++ b/libs/crm/feature/customer-loyalty-cards/src/lib/components/lock-customer-card/lock-customer-card.component.ts @@ -3,7 +3,7 @@ import { Component, inject, input, - OnDestroy, + output, signal, } from '@angular/core'; import { logger } from '@isa/core/logging'; @@ -24,8 +24,7 @@ import { changeDetection: ChangeDetectionStrategy.OnPush, imports: [TextButtonComponent], }) -export class LockCustomerCardComponent implements OnDestroy { - #reloadTimeoutId?: ReturnType; +export class LockCustomerCardComponent { #logger = logger(() => ({ component: 'LockCustomerCardComponent', })); @@ -41,6 +40,12 @@ export class LockCustomerCardComponent implements OnDestroy { readonly #customerId = this.#bonusCardsResource.customerId; + /** + * Event emitted when a card has been successfully locked or unlocked. + * Parent should reload cards and transactions. + */ + readonly cardLocked = output(); + loading = signal(false); async lockCard() { @@ -55,7 +60,7 @@ export class LockCustomerCardComponent implements OnDestroy { message: 'Karte gesperrt', }, }); - this.reloadCards(); + this.cardLocked.emit(); } catch (error: unknown) { this.#logger.error('Error locking card', error as Error, () => ({ cardCode, @@ -90,7 +95,7 @@ export class LockCustomerCardComponent implements OnDestroy { message: 'Karte entsperrt', }, }); - this.reloadCards(); + this.cardLocked.emit(); } catch (error: unknown) { this.#logger.error('Error unlocking card', error as Error, () => ({ cardCode, @@ -104,16 +109,4 @@ export class LockCustomerCardComponent implements OnDestroy { this.loading.set(false); } } - - reloadCards() { - this.#reloadTimeoutId = setTimeout(() => { - this.#bonusCardsResource.resource.reload(); - }, 500); - } - - ngOnDestroy(): void { - if (this.#reloadTimeoutId) { - clearTimeout(this.#reloadTimeoutId); - } - } } diff --git a/libs/crm/feature/customer-loyalty-cards/src/lib/customer-loyalty-cards.component.html b/libs/crm/feature/customer-loyalty-cards/src/lib/customer-loyalty-cards.component.html index 6976add2e..6b1edf0c5 100644 --- a/libs/crm/feature/customer-loyalty-cards/src/lib/customer-loyalty-cards.component.html +++ b/libs/crm/feature/customer-loyalty-cards/src/lib/customer-loyalty-cards.component.html @@ -28,8 +28,12 @@ /> - + - + } diff --git a/libs/crm/feature/customer-loyalty-cards/src/lib/customer-loyalty-cards.component.ts b/libs/crm/feature/customer-loyalty-cards/src/lib/customer-loyalty-cards.component.ts index dca5770d3..14b72b2ed 100644 --- a/libs/crm/feature/customer-loyalty-cards/src/lib/customer-loyalty-cards.component.ts +++ b/libs/crm/feature/customer-loyalty-cards/src/lib/customer-loyalty-cards.component.ts @@ -62,6 +62,12 @@ export class CustomerLoyaltyCardsComponent { */ readonly navigateToPraemienshop = output(); + /** + * Event emitted when a card has been added, locked, or unlocked. + * Parent should reload cards and transactions. + */ + readonly cardUpdated = output(); + /** * All bonus cards for the selected customer. */ @@ -96,4 +102,13 @@ export class CustomerLoyaltyCardsComponent { this.#logger.info('Emit navigate to Prämienshop event'); this.navigateToPraemienshop.emit(); } + + /** + * Handle card update events from child components. + * Forwards the event to parent for reload coordination. + */ + onCardUpdated(): void { + this.#logger.debug('Card updated, forwarding event to parent'); + this.cardUpdated.emit(); + } }