mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merge branch 'release/4.5' into develop
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -80,3 +80,6 @@ CLAUDE.md
|
||||
*.pyc
|
||||
.vite
|
||||
reports/
|
||||
|
||||
# Local iPad dev setup (proxy)
|
||||
/local-dev/
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('CustomerCardPointsSummaryComponent', () => {
|
||||
});
|
||||
|
||||
describe('formattedPoints computed signal', () => {
|
||||
it('should display points from primary card', () => {
|
||||
it('should display points from first card', () => {
|
||||
fixture.componentRef.setInput('cards', mockCards);
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -77,7 +77,7 @@ describe('CustomerCardPointsSummaryComponent', () => {
|
||||
expect(component.formattedPoints()).toBe('123.456');
|
||||
});
|
||||
|
||||
it('should display 0 when no primary card exists', () => {
|
||||
it('should display points from first card regardless of isPrimary flag', () => {
|
||||
const cardsWithoutPrimary: BonusCardInfo[] = [
|
||||
{
|
||||
code: 'CARD-1',
|
||||
@@ -93,7 +93,7 @@ describe('CustomerCardPointsSummaryComponent', () => {
|
||||
fixture.componentRef.setInput('cards', cardsWithoutPrimary);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.formattedPoints()).toBe('0');
|
||||
expect(component.formattedPoints()).toBe('1.500');
|
||||
});
|
||||
|
||||
it('should display 0 when cards array is empty', () => {
|
||||
@@ -122,14 +122,14 @@ describe('CustomerCardPointsSummaryComponent', () => {
|
||||
expect(component.formattedPoints()).toBe('0');
|
||||
});
|
||||
|
||||
it('should only use primary card points, not sum of all cards', () => {
|
||||
it('should only use first card points, not sum of all cards', () => {
|
||||
const multipleCards: BonusCardInfo[] = [
|
||||
{
|
||||
code: 'CARD-1',
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
isActive: true,
|
||||
isPrimary: true,
|
||||
isPrimary: false,
|
||||
totalPoints: 1000,
|
||||
cardNumber: '1234-5678-9012-3456',
|
||||
} as BonusCardInfo,
|
||||
@@ -138,7 +138,7 @@ describe('CustomerCardPointsSummaryComponent', () => {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
isActive: true,
|
||||
isPrimary: false,
|
||||
isPrimary: true,
|
||||
totalPoints: 500,
|
||||
cardNumber: '9876-5432-1098-7654',
|
||||
} as BonusCardInfo,
|
||||
@@ -147,7 +147,7 @@ describe('CustomerCardPointsSummaryComponent', () => {
|
||||
fixture.componentRef.setInput('cards', multipleCards);
|
||||
fixture.detectChanges();
|
||||
|
||||
// Should be 1000, not 1500
|
||||
// Should be 1000 (first card), not 500 (primary) or 1500 (sum)
|
||||
expect(component.formattedPoints()).toBe('1.000');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -36,12 +36,11 @@ export class CustomerCardPointsSummaryComponent {
|
||||
readonly navigateToPraemienshop = output<void>();
|
||||
|
||||
/**
|
||||
* Total points from primary card, formatted with thousands separator.
|
||||
* Total points from first card, formatted with thousands separator.
|
||||
*/
|
||||
readonly formattedPoints = computed(() => {
|
||||
const cards = this.cards();
|
||||
const primaryCard = cards.find((c) => c.isPrimary);
|
||||
const points = primaryCard?.totalPoints ?? 0;
|
||||
const points = cards?.[0]?.totalPoints ?? 0;
|
||||
|
||||
// Format with German thousands separator (dot)
|
||||
return points.toLocaleString('de-DE');
|
||||
|
||||
@@ -84,8 +84,11 @@ export class CloseOnScrollDirective implements OnDestroy {
|
||||
}
|
||||
this.#isActive = true;
|
||||
|
||||
// Delay listener registration to next frame to skip any stale scroll events
|
||||
this.#pendingActivation = requestAnimationFrame(() => {
|
||||
// Delay listener registration to skip scroll events caused by:
|
||||
// 1. Stale scroll events from before activation
|
||||
// 2. iOS Safari's automatic "scroll into view" when focusing elements
|
||||
// Using setTimeout with 100ms to ensure iOS scroll-into-view completes
|
||||
this.#pendingActivation = window.setTimeout(() => {
|
||||
this.#scrollListener = (event: Event) => {
|
||||
const excludeElement = this.closeOnScrollExclude();
|
||||
if (excludeElement?.contains(event.target as HTMLElement)) {
|
||||
@@ -101,12 +104,12 @@ export class CloseOnScrollDirective implements OnDestroy {
|
||||
{ capture: true, passive: true },
|
||||
);
|
||||
this.#logger.debug('Activated scroll listener');
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
#deactivate(): void {
|
||||
if (this.#pendingActivation) {
|
||||
cancelAnimationFrame(this.#pendingActivation);
|
||||
clearTimeout(this.#pendingActivation);
|
||||
this.#pendingActivation = undefined;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user