Paging Kundensuche

This commit is contained in:
Lorenz Hilpert
2023-07-10 13:33:43 +02:00
parent 201ea2ee9c
commit f015169011
7 changed files with 89 additions and 7 deletions

View File

@@ -1,4 +1,9 @@
<cdk-virtual-scroll-viewport itemSize="98" class="h-[calc(100vh-18.875rem)]" *ngIf="!compact">
<cdk-virtual-scroll-viewport
itemSize="98"
class="h-[calc(100vh-18.875rem)]"
*ngIf="!compact"
(scrolledIndexChange)="scrolledIndexChange($event)"
>
<a
*cdkVirtualFor="let customer of customers; trackBy: trackByFn"
[routerLink]="customerSearchNavigation.detailsRoute({ processId: processId, customerId: customer.id })?.path"
@@ -11,7 +16,12 @@
</a>
</cdk-virtual-scroll-viewport>
<cdk-virtual-scroll-viewport itemSize="98" class="h-[calc(100vh-20.75rem)]" *ngIf="compact">
<cdk-virtual-scroll-viewport
itemSize="98"
class="h-[calc(100vh-20.75rem)]"
*ngIf="compact"
(scrolledIndexChange)="scrolledIndexChange($event)"
>
<a
*cdkVirtualFor="let customer of customers; trackBy: trackByFn"
[routerLink]="customerSearchNavigation.detailsRoute({ processId: processId, customerId: customer.id })?.path"

View File

@@ -1,7 +1,8 @@
import { Component, ChangeDetectionStrategy, Input, EventEmitter, Output } from '@angular/core';
import { Component, ChangeDetectionStrategy, Input, EventEmitter, Output, ViewChild } from '@angular/core';
import { CustomerInfoDTO } from '@swagger/crm';
import { BooleanInput, NumberInput, coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
import { CustomerSearchNavigation } from '../../navigations';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
@Component({
selector: 'page-customer-result-list',
@@ -28,6 +29,9 @@ export class CustomerResultListComponent {
@Output()
selectedChange = new EventEmitter<CustomerInfoDTO>();
@Output()
endReached = new EventEmitter<void>();
private _processId: NumberInput;
@Input()
get processId() {
@@ -39,5 +43,19 @@ export class CustomerResultListComponent {
trackByFn = (_: number, item: CustomerInfoDTO) => item?.id;
@ViewChild(CdkVirtualScrollViewport, { static: false })
viewport: CdkVirtualScrollViewport;
@Input()
set scrollIndex(index: number) {
this.viewport?.scrollToIndex(index);
}
constructor(public customerSearchNavigation: CustomerSearchNavigation) {}
scrolledIndexChange(index: number) {
if (index && this.customers.length <= this.viewport?.getRenderedRange()?.end) {
this.endReached.emit();
}
}
}

View File

@@ -19,4 +19,5 @@
<span class="mr-5 self-end text-sm"> {{ hits$ | async }} Treffer </span>
</div>
<page-customer-result-list [processId]="processId$ | async" [customers]="customers$ | async"> </page-customer-result-list>
<page-customer-result-list [processId]="processId$ | async" [customers]="customers$ | async" (endReached)="paginate()">
</page-customer-result-list>

View File

@@ -67,4 +67,9 @@ export class CustomerResultsMainViewComponent implements OnInit, OnDestroy {
this._store.setFilter(filter);
this._store.search();
}
paginate() {
console.log('paginate');
this._store.paginate();
}
}

View File

@@ -19,4 +19,5 @@
<span class="mr-5 self-end text-sm mt-4"> {{ hits$ | async }} Treffer </span>
</div>
<page-customer-result-list [processId]="processId$ | async" compact="true" [customers]="customers$ | async"> </page-customer-result-list>
<page-customer-result-list [processId]="processId$ | async" compact="true" [customers]="customers$ | async" (endReached)="paginate()">
</page-customer-result-list>

View File

@@ -67,4 +67,8 @@ export class CustomerResultsSideViewComponent implements OnInit, OnDestroy {
this._store.setFilter(filter);
this._store.search();
}
paginate() {
this._store.paginate();
}
}

View File

@@ -3,7 +3,7 @@ import { CustomerSearchState } from './customer-search.state';
import * as S from './selectors';
import { Injectable, OnDestroy } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { distinctUntilChanged, filter, switchMap, takeUntil, tap, withLatestFrom, delayWhen } from 'rxjs/operators';
import { distinctUntilChanged, filter, switchMap, takeUntil, tap, withLatestFrom, delayWhen, delay } from 'rxjs/operators';
import { CrmCustomerService } from '@domain/crm';
import { Result } from '@domain/defs';
import { CustomerDTO, ListResponseArgsOfCustomerInfoDTO, QuerySettingsDTO } from '@swagger/crm';
@@ -197,9 +197,13 @@ export class CustomerSearchStore extends ComponentStore<CustomerSearchState> imp
this.patchState({ fetchingCustomerList: true, customerList: [], customerListCount: 0 });
this.restoreSearchResult();
}),
delay(1),
switchMap(([_, filter, processId]) =>
this._customerService
.getCustomersWithQueryToken(filter.getQueryToken())
.getCustomersWithQueryToken({
...filter.getQueryToken(),
take: this.customerList?.length || 20,
})
.pipe(
takeUntil(this._cancelSearch),
tapResponse(this.handleSearchResponse(filter, processId), this.handleSearchError, this.handleSearchComplete)
@@ -226,6 +230,45 @@ export class CustomerSearchStore extends ComponentStore<CustomerSearchState> imp
this._cancelSearch.next();
}
paginate = this.effect(($: Observable<void>) =>
$.pipe(
withLatestFrom(this.filter$, this.processId$, this.customerList$, this.fetchingCustomerList$),
filter(
([_, __, ___, customerList, fetchingCustomerList]) =>
!fetchingCustomerList && customerList.length && customerList.length < this.customerListCount
),
delayWhen(() => this.fetchingCustomerList$.pipe(filter((fetching) => !fetching))),
tap(() => {
this.patchState({ fetchingCustomerList: true });
}),
switchMap(([_, filter, processId, customerList]) =>
this._customerService
.getCustomersWithQueryToken({
...filter.getQueryToken(),
skip: customerList.length,
})
.pipe(
takeUntil(this._cancelSearch),
tapResponse(this.handlePaginateResponse(filter, processId), this.handlePaginateError, this.handlePaginateComplete)
)
)
)
);
handlePaginateResponse = (filter: Filter, processId: number) => (result: ListResponseArgsOfCustomerInfoDTO) => {
this.patchState({ customerList: [...this.customerList, ...result.result], customerListCount: result.hits });
this._customerListResponse.next([result, filter, processId]);
this.cacheSearchResult();
};
handlePaginateError = (err: any) => {
console.error(err);
};
handlePaginateComplete = () => {
this.patchState({ fetchingCustomerList: false });
};
reset(queryParams: Record<string, string> = {}) {
this.patchState({ customerList: [], customerListCount: 0, queryParams });