Shared Split Screen Checkout Implementation

This commit is contained in:
Nino
2023-09-12 15:07:10 +02:00
parent a1e7ee2997
commit d9e67ec9be
13 changed files with 111 additions and 132 deletions

View File

@@ -22,7 +22,7 @@ export class CanActivateCartGuard {
name: `Vorgang ${processes.length + 1}`,
});
}
await this._checkoutNavigationService.navigateToCheckoutReview({ processId: lastActivatedProcessId });
await this._checkoutNavigationService.getCheckoutReviewPath(lastActivatedProcessId).path;
return false;
}
}

View File

@@ -407,7 +407,7 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
}
async navigateToShoppingCart() {
await this._checkoutNavigationService.navigateToCheckoutReview({ processId: this.applicationService.activatedProcessId });
await this._checkoutNavigationService.getCheckoutReviewPath(this.applicationService.activatedProcessId).navigate();
}
async navigateToCustomerSearch() {

View File

@@ -32,7 +32,7 @@ export class AddedToCartModalComponent {
}
async toCart() {
await this._checkoutNavigationService.navigateToCheckoutReview({ processId: this._applicationService.activatedProcessId });
await this._checkoutNavigationService.getCheckoutReviewPath(this._applicationService.activatedProcessId).navigate();
this.ref.close();
}
}

View File

@@ -200,7 +200,7 @@ export class CheckoutDummyComponent implements OnInit, OnDestroy {
queryParams: { customertype: filter.customertype },
});
} else {
await this._checkoutNavigationService.navigateToCheckoutReview({ processId: this._applicationService.activatedProcessId });
await this._checkoutNavigationService.getCheckoutReviewPath(this._applicationService.activatedProcessId).navigate();
}
this._ref?.close();
});
@@ -217,7 +217,7 @@ export class CheckoutDummyComponent implements OnInit, OnDestroy {
queryParams: { customertype: filter.customertype },
});
} else {
await this._checkoutNavigationService.navigateToCheckoutReview({ processId: this._applicationService.activatedProcessId });
await this._checkoutNavigationService.getCheckoutReviewPath(this._applicationService.activatedProcessId).navigate();
}
this._ref?.close();
});

View File

@@ -16,8 +16,8 @@ import { DomainCheckoutService } from '@domain/checkout';
import { AvailabilityDTO, DestinationDTO, ShoppingCartItemDTO } from '@swagger/checkout';
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
import { PrintModalData, PrintModalComponent } from '@modal/printer';
import { catchError, debounceTime, delay, first, map, shareReplay, switchMap, take, takeUntil, tap } from 'rxjs/operators';
import { Subject, NEVER, combineLatest, BehaviorSubject, interval, of, merge, Subscription } from 'rxjs';
import { delay, first, map, switchMap, takeUntil } from 'rxjs/operators';
import { Subject, NEVER, combineLatest, BehaviorSubject, Subscription } from 'rxjs';
import { DomainCatalogService } from '@domain/catalog';
import { BreadcrumbService } from '@core/breadcrumb';
import { DomainPrinterService } from '@domain/printer';
@@ -259,7 +259,7 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
await this.breadcrumb.addOrUpdateBreadcrumbIfNotExists({
key: this.applicationService.activatedProcessId,
name: 'Warenkorb',
path: this._navigationService.getCheckoutReviewPath(this.applicationService.activatedProcessId),
path: this._navigationService.getCheckoutReviewPath(this.applicationService.activatedProcessId).path,
tags: ['checkout', 'cart'],
section: 'customer',
});
@@ -525,7 +525,7 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
const orderIds = orders.map((order) => order.id).join(',');
this._store.orderCompleted.next();
await this.patchProcess(processId);
await this._navigationService.navigateToCheckoutSummary({ processId, orderIds });
await this._navigationService.getCheckoutSummaryPath({ processId, orderIds }).navigate();
} catch (error) {
const response = error?.error;
let message: string = response?.message ?? '';
@@ -547,7 +547,7 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy, AfterViewInit
if (error.status === 409) {
this._store.orderCompleted.next();
await this.patchProcess(processId);
await this._navigationService.navigateToCheckoutSummary({ processId });
await this._navigationService.getCheckoutSummaryPath({ processId }).navigate();
}
} finally {
this.showOrderButtonSpinner = false;

View File

@@ -173,7 +173,7 @@ export class CheckoutSummaryComponent implements OnInit, OnDestroy {
path: this._navigation.getCheckoutSummaryPath({
processId: this.applicationService.activatedProcessId,
orderIds: this._route.snapshot.params.orderIds,
}),
}).path,
tags: ['checkout', 'cart'],
section: 'customer',
});

View File

@@ -5,38 +5,28 @@ import { CheckoutSummaryComponent } from './checkout-summary/checkout-summary.co
import { PageCheckoutComponent } from './page-checkout.component';
import { CheckoutReviewDetailsComponent } from './checkout-review/details/checkout-review-details.component';
const auxiliaryRoutes = [
{
path: 'details',
component: CheckoutReviewDetailsComponent,
outlet: 'left',
},
{
path: 'review',
component: CheckoutReviewComponent,
outlet: 'right',
},
{
path: 'summary',
component: CheckoutSummaryComponent,
outlet: 'main',
},
{
path: 'summary/:orderIds',
component: CheckoutSummaryComponent,
outlet: 'main',
},
];
const routes: Routes = [
{
path: '',
component: PageCheckoutComponent,
children: [
{ path: 'summary', component: CheckoutSummaryComponent },
{ path: 'summary/:orderIds', component: CheckoutSummaryComponent },
{ path: 'review', component: CheckoutReviewComponent },
...auxiliaryRoutes,
{
path: 'details',
component: CheckoutReviewDetailsComponent,
outlet: 'side',
},
{
path: 'review',
component: CheckoutReviewComponent,
},
{
path: 'summary',
component: CheckoutSummaryComponent,
},
{
path: 'summary/:orderIds',
component: CheckoutSummaryComponent,
},
{ path: '', pathMatch: 'full', redirectTo: 'review' },
],
},

View File

@@ -1,23 +1,3 @@
<shared-breadcrumb class="mb-5 desktop-small:mb-9" [key]="breadcrumbKey$ | async" [tags]="['checkout']"></shared-breadcrumb>
<ng-container *ngIf="routerEvents$ | async">
<ng-container *ngIf="!(isDesktop$ | async); else desktop">
<router-outlet></router-outlet>
</ng-container>
<ng-template #desktop>
<ng-container *ngIf="showMainOutlet$ | async">
<router-outlet name="main"></router-outlet>
</ng-container>
<div class="grid grid-cols-split-screen gap-split-screen">
<div *ngIf="!(showMainOutlet$ | async)" class="block">
<router-outlet name="left"></router-outlet>
</div>
<div *ngIf="!(showMainOutlet$ | async)">
<router-outlet name="right"></router-outlet>
</div>
</div>
</ng-template>
</ng-container>
<shared-splitscreen></shared-splitscreen>

View File

@@ -1,8 +1,6 @@
import { Component, ChangeDetectionStrategy, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ApplicationService } from '@core/application';
import { EnvironmentService } from '@core/environment';
import { map, shareReplay } from 'rxjs/operators';
import { map } from 'rxjs/operators';
@Component({
selector: 'page-checkout',
@@ -13,28 +11,7 @@ import { map, shareReplay } from 'rxjs/operators';
export class PageCheckoutComponent implements OnInit {
readonly breadcrumbKey$ = this.applicationService.activatedProcessId$.pipe(map((processId) => String(processId)));
get isDesktop$() {
return this._environmentService.matchDesktopLarge$;
}
routerEvents$ = this._router.events.pipe(shareReplay());
showMainOutlet$ = this.routerEvents$.pipe(
map((_) => {
const primary = this._activatedRoute?.children?.find(
(child) => child?.outlet === 'primary' && child?.routeConfig?.path === 'summary'
);
const main = this._activatedRoute?.children?.find((child) => child?.outlet === 'main' && child?.routeConfig?.path === 'summary');
return !!primary && !!main;
})
);
constructor(
private applicationService: ApplicationService,
private _environmentService: EnvironmentService,
private _router: Router,
private _activatedRoute: ActivatedRoute
) {}
constructor(private applicationService: ApplicationService) {}
ngOnInit() {}
}

View File

@@ -6,9 +6,18 @@ import { CheckoutReviewModule } from './checkout-review/checkout-review.module';
import { CheckoutSummaryModule } from './checkout-summary/checkout-summary.module';
import { PageCheckoutRoutingModule } from './page-checkout-routing.module';
import { PageCheckoutComponent } from './page-checkout.component';
import { SharedSplitscreenComponent } from '@shared/components/splitscreen';
@NgModule({
imports: [CommonModule, CheckoutSummaryModule, PageCheckoutRoutingModule, CheckoutReviewModule, CheckoutDummyModule, BreadcrumbModule],
imports: [
CommonModule,
CheckoutSummaryModule,
PageCheckoutRoutingModule,
CheckoutReviewModule,
SharedSplitscreenComponent,
CheckoutDummyModule,
BreadcrumbModule,
],
declarations: [PageCheckoutComponent],
exports: [],
})

View File

@@ -266,7 +266,7 @@ export class CustomerDetailsViewMainComponent extends ComponentStore<CustomerDet
if (this.shoppingCartHasItems) {
// Navigation zum Warenkorb
const path = this._checkoutNavigation.getCheckoutReviewPath(this.processId);
const path = this._checkoutNavigation.getCheckoutReviewPath(this.processId).path;
this._router.navigate(path);
} else {
// Navigation zur Artikelsuche

View File

@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { NavigationService } from './navigation.service';
import { Router } from '@angular/router';
import { NavigationExtras, Router } from '@angular/router';
@Injectable({ providedIn: 'root' })
export class CheckoutNavigationService extends NavigationService {
@@ -8,54 +8,77 @@ export class CheckoutNavigationService extends NavigationService {
super(_router);
}
getCheckoutReviewPath(processId: number): any[] {
return ['/kunde', processId, 'cart', { outlets: { primary: 'review', main: null, left: 'details', right: 'review' } }];
getCheckoutReviewPath(processId?: number): { path: any[]; extras?: NavigationExtras; navigate: () => Promise<boolean> } {
const path = ['/kunde', processId, 'cart', { outlets: { primary: ['review'], side: ['details'] } }].filter((x) => !!x);
return { path, navigate: this._createNavigationFn(path) };
}
getCheckoutSummaryPath({ processId, orderIds }: { processId: number; orderIds?: string }): any[] {
if (!!orderIds) {
return [
'/kunde',
processId,
'cart',
{ outlets: { primary: ['summary', orderIds], main: ['summary', orderIds], left: null, right: null } },
];
} else {
return ['/kunde', processId, 'cart', { outlets: { primary: 'summary', main: 'summary', left: null, right: null } }];
}
}
async navigateToCheckoutReview({
processId,
queryParams,
queryParamsHandling,
}: {
processId: number;
queryParams?: Record<string, string>;
queryParamsHandling?: 'merge' | 'preserve' | '';
}) {
await this._navigateTo({
routerLink: this.getCheckoutReviewPath(processId),
queryParams,
queryParamsHandling,
});
}
async navigateToCheckoutSummary({
getCheckoutSummaryPath({
processId,
orderIds,
queryParams,
queryParamsHandling,
extras,
}: {
processId: number;
processId?: number;
orderIds?: string;
queryParams?: Record<string, string>;
queryParamsHandling?: 'merge' | 'preserve' | '';
}) {
await this._navigateTo({
routerLink: this.getCheckoutSummaryPath({ processId, orderIds }),
queryParams,
queryParamsHandling,
});
extras?: NavigationExtras;
}): { path: any[]; extras?: NavigationExtras; navigate: () => Promise<boolean> } {
const path = ['/kunde', processId, 'cart', { outlets: { primary: ['summary', orderIds].filter((x) => !!x), side: null } }].filter(
(x) => !!x
);
return {
path,
navigate: this._createNavigationFn(path, extras),
};
}
// getCheckoutReviewPath(processId: number): any[] {
// return ['/kunde', processId, 'cart', { outlets: { primary: 'review', main: null, left: 'details', right: 'review' } }];
// }
// getCheckoutSummaryPath({ processId, orderIds }: { processId: number; orderIds?: string }): any[] {
// if (!!orderIds) {
// return [
// '/kunde',
// processId,
// 'cart',
// { outlets: { primary: ['summary', orderIds], main: ['summary', orderIds], left: null, right: null } },
// ];
// } else {
// return ['/kunde', processId, 'cart', { outlets: { primary: 'summary', main: 'summary', left: null, right: null } }];
// }
// }
// async navigateToCheckoutReview({
// processId,
// queryParams,
// queryParamsHandling,
// }: {
// processId: number;
// queryParams?: Record<string, string>;
// queryParamsHandling?: 'merge' | 'preserve' | '';
// }) {
// await this._navigateTo({
// routerLink: this.getCheckoutReviewPath(processId),
// queryParams,
// queryParamsHandling,
// });
// }
// async navigateToCheckoutSummary({
// processId,
// orderIds,
// queryParams,
// queryParamsHandling,
// }: {
// processId: number;
// orderIds?: string;
// queryParams?: Record<string, string>;
// queryParamsHandling?: 'merge' | 'preserve' | '';
// }) {
// await this._navigateTo({
// routerLink: this.getCheckoutSummaryPath({ processId, orderIds }),
// queryParams,
// queryParamsHandling,
// });
// }
}

View File

@@ -16,7 +16,7 @@ import { Breadcrumb, BreadcrumbService } from '@core/breadcrumb';
import { DomainCheckoutService } from '@domain/checkout';
import { CheckoutNavigationService } from '@shared/services';
import { BehaviorSubject, NEVER, Observable, combineLatest, isObservable } from 'rxjs';
import { filter, first, map, switchMap, tap } from 'rxjs/operators';
import { first, map, switchMap, tap } from 'rxjs/operators';
@Component({
selector: 'shell-process-bar-item',
@@ -78,7 +78,7 @@ export class ShellProcessBarItemComponent implements OnInit, OnDestroy, OnChange
}
getCheckoutPath(processId: number) {
return this._checkoutNavigationService.getCheckoutReviewPath(processId);
return this._checkoutNavigationService.getCheckoutReviewPath(processId).path;
}
initLatestBreadcrumb$() {