Files
ISA-Frontend/apps/isa-app/src/page/remission/remission-list/remission-list.component.ts
2025-03-03 13:28:03 +01:00

301 lines
9.2 KiB
TypeScript

import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import {
Component,
ChangeDetectionStrategy,
OnInit,
OnDestroy,
ViewChild,
ViewChildren,
QueryList,
TrackByFunction,
inject,
} from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ApplicationService } from '@core/application';
import { BreadcrumbService } from '@core/breadcrumb';
import { Config } from '@core/config';
import { RemissionListItem } from '@domain/remission';
import { SupplierDTO } from '@generated/swagger/inventory-api';
import { Subject, combineLatest, BehaviorSubject } from 'rxjs';
import { debounceTime, first, map, shareReplay, takeUntil, withLatestFrom } from 'rxjs/operators';
import { RemissionListItemComponent } from './remission-list-item';
import { RemissionListComponentStore } from './remission-list.component-store';
import { RemissionComponentStore } from './remission.component-store';
import { ShellService } from '@shared/shell';
@Component({
selector: 'page-remission-list',
templateUrl: 'remission-list.component.html',
styleUrls: ['remission-list.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [RemissionComponentStore],
standalone: false,
})
export class RemissionListComponent implements OnInit, OnDestroy {
shellService = inject(ShellService);
@ViewChildren(RemissionListItemComponent) listItems: QueryList<RemissionListItemComponent>;
@ViewChild('scrollContainer', { static: true })
scrollContainer: CdkVirtualScrollViewport;
private _onDestroy$ = new Subject<void>();
get processId() {
return this._config.get('process.ids.remission');
}
get suppliers$() {
return this._remissionListStore.suppliers$;
}
get selectedSupplier$() {
return this._remissionListStore.selectedSupplier$;
}
get selectedSupplierId$() {
return this._remissionListStore.selectedSupplier$.pipe(map((s) => s?.id));
}
get sources$() {
return this._remissionListStore.sources$;
}
get selectedSource$() {
return this._remissionListStore.selectedSource$;
}
get items$() {
return this._remissionListStore.items$;
}
get requiredCapacities$() {
return this._remissionListStore.requiredCapacities$;
}
get hits$() {
return this._remissionListStore.hits$;
}
get fetching$() {
return this._remissionListStore.fetching$;
}
get return$() {
return this._remissionStore.return$;
}
get filter$() {
return this._remissionListStore.filter$;
}
showSelectDepartmenttext$ = combineLatest([this.filter$, this.selectedSource$]).pipe(
map(([filter, source]) => {
if (source !== 'Abteilungsremission') {
return false;
}
if (filter?.getQueryToken()?.filter?.abteilungen) {
return false;
}
return true;
}),
);
listEmpty$ = combineLatest([this.fetching$, this.hits$]).pipe(
map(([loading, hits]) => !loading && hits === 0),
shareReplay(),
);
get queryParams$() {
return this._activatedRoute.queryParams.pipe(
withLatestFrom(this._remissionListStore.filter$, this.selectedSupplierId$, this.selectedSource$),
map(([params, filter, supplier, source]) => {
let queryParams = params;
if (filter) {
queryParams = { ...filter.getQueryParams(), ...params, supplier, source };
}
return queryParams;
}),
);
}
get returnCount$() {
return this._remissionStore.returnCount$;
}
showStartRemissionAction$ = combineLatest([this.listEmpty$, this.return$]).pipe(map(([empty, r]) => !empty && !r));
filteredSuppliers$ = combineLatest([this._remissionStore.uncompleted$, this.suppliers$, this.selectedSupplier$]).pipe(
map(([uncompleted, suppliers, selectedSupplier]) => {
if (!uncompleted) {
return suppliers;
}
return suppliers.filter((supplier) => supplier?.id === selectedSupplier?.id);
}),
);
trackByItemId: TrackByFunction<RemissionListItem> = (_, item) => item.dto.id;
showScrollArrow$ = new BehaviorSubject<boolean>(false);
remittingItem$ = new BehaviorSubject<boolean>(false);
constructor(
private readonly _remissionListStore: RemissionListComponentStore,
private readonly _remissionStore: RemissionComponentStore,
private readonly _router: Router,
private readonly _activatedRoute: ActivatedRoute,
private readonly _breadcrumb: BreadcrumbService,
private readonly _applicationService: ApplicationService,
private readonly _config: Config,
) {}
ngOnInit() {
this._activatedRoute.queryParams
.pipe(takeUntil(this._onDestroy$), debounceTime(0))
.subscribe(async (queryParams) => {
const { supplier, source } = queryParams;
if (supplier) {
this._remissionListStore.setSelectedSupplierId(+supplier);
}
if (source) {
this._remissionListStore.setSelectedSource(source);
}
const data = await this._remissionListStore.getCachedData();
if (data.items?.length !== 0) {
this._remissionListStore.setItems(data.items);
this._remissionListStore.setHits(data.hits);
this.scrollTop(Number(queryParams?.scroll_position ?? 0));
}
await this.updateBreadcrumb(queryParams);
await this.removeBreadcrumbs();
});
this._remissionListStore.filter$
.pipe(takeUntil(this._onDestroy$), withLatestFrom(this._remissionListStore.selectedSource$))
.subscribe(([_, source]) => {
if (source === 'Abteilungsremission') {
this._remissionListStore.loadRequiredCapacities();
}
});
this._activatedRoute.params.pipe(takeUntil(this._onDestroy$)).subscribe((params) => {
const id = +params.returnId;
if (id) {
// Remission wurde gestartet
this._remissionStore.getReturn(id);
} else {
// Für die Anzahl der Warenbegleitscheine, wenn keine Remission gestartet wurde
this._remissionStore.getReturns(false);
}
});
this._remissionStore.getReturnCompleted.pipe(takeUntil(this._onDestroy$)).subscribe((returnDto) => {
if (returnDto) {
this._remissionListStore.setSelectedSupplierId(returnDto.supplier.id);
}
if (!returnDto || !!returnDto.completed) {
this._applicationService.patchProcessData(this._remissionListStore.processId, {
active: undefined,
});
this._router.navigate(['./'], { relativeTo: this._activatedRoute.parent });
}
});
}
async ngOnDestroy() {
this._onDestroy$.next();
this._onDestroy$.complete();
if (this._remissionStore.return) {
this._remissionListStore.cacheCurrentData();
const params = await this._activatedRoute.queryParams.pipe(first()).toPromise();
await this.updateBreadcrumb(params);
}
}
async updateBreadcrumb(queryParams: Record<string, string> = {}) {
const scroll_position = this.scrollContainer.measureScrollOffset('top');
const returnId = this._activatedRoute?.snapshot?.params?.returnId;
const packageNumber = this._activatedRoute?.snapshot?.params?.packageNumber;
const crumbs = await this._breadcrumb
.getBreadcrumbsByKeyAndTags$(this._remissionListStore.processId, ['remission'])
.pipe(first())
.toPromise();
const params = { ...queryParams, scroll_position };
for (const crumb of crumbs) {
this._breadcrumb.patchBreadcrumb(crumb.id, {
params,
path: `/filiale/remission/${returnId ? returnId + '/' : ''}${packageNumber ? packageNumber + '/' : ''}list`,
});
}
}
async scrolledIndexChange(index: number) {
const items = await this.items$.pipe(first()).toPromise();
const hits = await this.hits$.pipe(first()).toPromise();
if (index > 0) {
this.showScrollArrow$.next(true);
} else {
this.showScrollArrow$.next(false);
}
if (items.length >= hits) {
return;
}
if (this._activatedRoute.snapshot.fragment === 'shipping-document') {
return;
}
if (index >= items.length - 10 && items.length - 10 > 0 && !this._remissionListStore.fetching) {
this._remissionListStore.search({});
}
}
scrollTop(scrollPos: number) {
setTimeout(() => this.scrollContainer.scrollTo({ top: scrollPos, behavior: 'smooth' }), 0);
}
setSupplier(supplier: SupplierDTO) {
this._remissionListStore.setSupplier(supplier);
}
setSource(source: string) {
this._remissionListStore.setSource(source);
}
async removeBreadcrumbs() {
await this._breadcrumb.removeBreadcrumbsByKeyAndTags(this._remissionListStore.processId, [
'remission',
'shipping-documents',
]);
await this._breadcrumb.removeBreadcrumbsByKeyAndTags(this._remissionListStore.processId, [
'remission',
'add-product',
]);
await this._breadcrumb.removeBreadcrumbsByKeyAndTags(this._remissionListStore.processId, ['remission', 'create']);
await this._breadcrumb.removeBreadcrumbsByKeyAndTags(this._remissionListStore.processId, [
'remission',
'finish-shipping-document',
]);
await this._breadcrumb.removeBreadcrumbsByKeyAndTags(this._remissionListStore.processId, [
'remission',
'finish-remission',
]);
}
shippingDocumentDeleted() {
this._router.navigate(['/filiale', 'remission', 'list']);
}
}