Merged PR 1973: feat(customer-search): use navigation state for reward customer selection

feat(customer-search): use navigation state for reward customer selection

Replace tab metadata context flag with NavigationStateService for tracking
reward flow customer selection. Store return URL in preserved navigation
context instead of tab metadata 'context' field.

Benefits:
- Clean separation: tab metadata no longer polluted with flow state
- Automatic cleanup when tabs close (no manual cleanup needed)
- Survives intermediate navigations (e.g., address edit)
- Tab-scoped automatically via TabService integration

Changes:
- Remove `isRewardTab()` linkedSignal and tab metadata 'context' check
- Add NavigationStateService with 'select-customer' scope
- Store returnUrl in preserved context before navigation
- Restore context and navigate back on customer selection
- Update reward-start-card to preserve context on button click
- Remove reward-catalog context initialization (no longer needed)

Technical Details:
- Context stored in tab.metadata['navigation-contexts']['select-customer']
- Uses async methods: preserveContext(), restoreAndClearContext()
- Signal-based hasReturnUrl() for template reactivity
- Maintains existing button flow (checks hasReturnUrl signal)

Ref: #5368
This commit is contained in:
Nino Righi
2025-10-20 11:56:35 +00:00
committed by Lorenz Hilpert
parent b96d889da5
commit f549c59bc8
6 changed files with 55 additions and 539 deletions

View File

@@ -17,7 +17,6 @@ import { RewardHeaderComponent } from './reward-header/reward-header.component';
import { RewardListComponent } from './reward-list/reward-list.component';
import { injectRestoreScrollPosition } from '@isa/utils/scroll-position';
import { RewardActionComponent } from './reward-action/reward-action.component';
import { TabService } from '@isa/core/tabs';
import { SelectedRewardShoppingCartResource } from '@isa/checkout/data-access';
import { SelectedCustomerBonusCardsResource } from '@isa/crm/data-access';
@@ -54,28 +53,14 @@ function querySettingsFactory() {
},
})
export class RewardCatalogComponent {
#tabService = inject(TabService);
restoreScrollPosition = injectRestoreScrollPosition();
searchTrigger = signal<SearchTrigger | 'reload' | 'initial'>('initial');
#filterService = inject(FilterService);
constructor() {
this.initRewardContext();
}
search(trigger: SearchTrigger): void {
this.searchTrigger.set(trigger); // Ist entweder 'scan', 'input', 'filter' oder 'orderBy'
this.#filterService.commit();
}
// Wichtig damit Kundensuche weiß, dass wir im Reward Kontext sind - Über Header CTA oder Kaufoptionen gelangt man zur Kundensuche
initRewardContext() {
const tabId = this.#tabService.activatedTabId();
if (tabId) {
this.#tabService.patchTabMetadata(tabId, { context: 'reward' });
}
}
}

View File

@@ -7,15 +7,15 @@
</p>
</div>
<a
<button
class="reward-start-card__select-cta"
data-which="select-customer"
data-what="select-customer"
uiButton
color="tertiary"
size="large"
[routerLink]="route().path"
[queryParams]="route().queryParams"
type="button"
(click)="onSelectCustomer()"
>
Kund*in auswählen
</a>
</button>

View File

@@ -1,16 +1,41 @@
import { ChangeDetectionStrategy, Component, computed } from '@angular/core';
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { ButtonComponent } from '@isa/ui/buttons';
import { injectTabId } from '@isa/core/tabs';
import { RouterLink } from '@angular/router';
import { Router } from '@angular/router';
import { getRouteToCustomer } from '../../helpers';
import { NavigationStateService } from '@isa/core/navigation';
@Component({
selector: 'reward-start-card',
templateUrl: './reward-start-card.component.html',
styleUrl: './reward-start-card.component.css',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ButtonComponent, RouterLink],
imports: [ButtonComponent],
})
export class RewardStartCardComponent {
readonly #navigationState = inject(NavigationStateService);
readonly #router = inject(Router);
tabId = injectTabId();
route = computed(() => getRouteToCustomer(this.tabId()));
/**
* Called when "Kund*in auswählen" button is clicked.
* Preserves the current URL as returnUrl before navigating to customer search.
*/
async onSelectCustomer() {
const customerRoute = getRouteToCustomer(this.tabId());
// Preserve context: Store current reward page URL to return to after customer selection
await this.#navigationState.preserveContext(
{
returnUrl: this.#router.url,
},
'select-customer',
);
// Navigate to customer search
await this.#router.navigate(customerRoute.path, {
queryParams: customerRoute.queryParams,
});
}
}