Skip to content

Commit 3fb0cc3

Browse files
committed
feat: extract order summary into a dedicated component
1 parent 226c62c commit 3fb0cc3

File tree

7 files changed

+98
-45
lines changed

7 files changed

+98
-45
lines changed

src/app/cart/cart.component.html

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
<div class="container">
1+
<div
2+
*ngIf="{
3+
products: products$ | async,
4+
totalPrice: totalPrice$ | async,
5+
cartEmpty: cartEmpty$ | async
6+
} as state"
7+
class="container"
8+
>
29
<div class="row">
310
<div class="col mx-auto py-3 py-md-5">
411
<mat-card>
@@ -7,17 +14,22 @@ <h1 class="text-center pt-4" mat-card-title>Checkout</h1>
714
<mat-card-content>
815
<mat-vertical-stepper #stepper [linear]="true">
916
<!-- Review your cart STEP -->
10-
<mat-step label="Review your cart" [completed]="cartEmpty$ | async">
11-
<ng-container *ngIf="cartEmpty$ | async; else emptyCartTemplate">
12-
<ng-container
13-
*ngIf="(loading$ | async) === false"
14-
[ngTemplateOutlet]="orderSummaryTemplate"
15-
[ngTemplateOutletContext]="{ showControls: true }"
16-
></ng-container>
17+
<mat-step label="Review your cart" [completed]="state.cartEmpty">
18+
<ng-container *ngIf="state.cartEmpty; else emptyCartTemplate">
19+
<app-order-summary
20+
*ngIf="state.products; else loaderTemplate"
21+
(add)="add($event)"
22+
(remove)="remove($event)"
23+
[products]="state.products"
24+
[totalPrice]="state.totalPrice!"
25+
[showControls]="true"
26+
></app-order-summary>
1727

18-
<div *ngIf="loading$ | async" class="py-5">
19-
<mat-spinner [diameter]="40" class="mx-auto"></mat-spinner>
20-
</div>
28+
<ng-template #loaderTemplate>
29+
<div class="py-5">
30+
<mat-spinner [diameter]="40" class="mx-auto"></mat-spinner>
31+
</div>
32+
</ng-template>
2133

2234
<div class="text-right">
2335
<button
@@ -58,10 +70,12 @@ <h2>Shipping address</h2>
5870

5971
<!-- Review your order STEP -->
6072
<mat-step label="Review your order">
61-
<ng-container
62-
[ngTemplateOutlet]="orderSummaryTemplate"
63-
[ngTemplateOutletContext]="{ showControls: false }"
64-
></ng-container>
73+
<app-order-summary
74+
*ngIf="state.products"
75+
[products]="state.products"
76+
[totalPrice]="state.totalPrice!"
77+
[showControls]="false"
78+
></app-order-summary>
6579

6680
<div class="row">
6781
<div class="col col-md-6">
@@ -91,32 +105,6 @@ <h2>Comment</h2>
91105
</div>
92106
</div>
93107

94-
<ng-template #orderSummaryTemplate let-showControls="showControls">
95-
<h2>Order summary</h2>
96-
97-
<ng-container>
98-
<app-product-item-checkout
99-
*ngFor="let product of products$ | async"
100-
(add)="add(product.id)"
101-
(remove)="remove(product.id)"
102-
[product]="product"
103-
[hideControls]="!showControls"
104-
></app-product-item-checkout>
105-
</ng-container>
106-
107-
<div class="row">
108-
<h3 class="col flex-grow-1">Shipping</h3>
109-
<span class="col flex-grow-0">Free</span>
110-
</div>
111-
112-
<div class="row">
113-
<h3 class="col flex-grow-1">Total</h3>
114-
<b class="col flex-grow-0" style="font-size: 18px">{{
115-
totalPrice$ | async | number: "1.2-2" | currency
116-
}}</b>
117-
</div>
118-
</ng-template>
119-
120108
<ng-template #emptyCartTemplate>
121109
<div class="lead">
122110
The cart is empty. Didn't you like anything in our shop?

src/app/cart/cart.component.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
33
import { STEPPER_GLOBAL_OPTIONS } from '@angular/cdk/stepper';
44
import { CheckoutService } from './checkout.service';
55
import { ProductCheckout } from '../products/product.interface';
6-
import { BehaviorSubject, Observable } from 'rxjs';
6+
import { Observable } from 'rxjs';
77
import { CartService } from './cart.service';
8-
import { map, shareReplay, tap } from 'rxjs/operators';
8+
import { map, shareReplay } from 'rxjs/operators';
99

1010
@Component({
1111
selector: 'app-cart',
@@ -19,7 +19,6 @@ import { map, shareReplay, tap } from 'rxjs/operators';
1919
],
2020
})
2121
export class CartComponent implements OnInit {
22-
loading$ = new BehaviorSubject(true);
2322
products$!: Observable<ProductCheckout[]>;
2423
totalPrice$!: Observable<number>;
2524
totalInCart$!: Observable<number>;
@@ -55,7 +54,6 @@ export class CartComponent implements OnInit {
5554
});
5655

5756
this.products$ = this.checkoutService.getProductsForCheckout().pipe(
58-
tap(() => this.loading$.next(false)),
5957
shareReplay({
6058
refCount: true,
6159
bufferSize: 1,

src/app/cart/cart.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ import { ProductItemCheckoutComponent } from './product-item-checkout/product-it
1212
import { CartCountControlsModule } from '../core/cart-count-controls/cart-count-controls.module';
1313
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
1414
import { CartShippingFormComponent } from './cart-shipping-form/cart-shipping-form.component';
15+
import { OrderSummaryComponent } from './order-summary/order-summary.component';
1516

1617
@NgModule({
1718
declarations: [
1819
CartComponent,
1920
ProductItemCheckoutComponent,
2021
CartShippingFormComponent,
22+
OrderSummaryComponent,
2123
],
2224
imports: [
2325
CommonModule,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<h2>Order summary</h2>
2+
3+
<ng-container>
4+
<app-product-item-checkout
5+
*ngFor="let product of products"
6+
(add)="add.emit(product.id)"
7+
(remove)="remove.emit(product.id)"
8+
[product]="product"
9+
[hideControls]="!showControls"
10+
></app-product-item-checkout>
11+
</ng-container>
12+
13+
<div class="row">
14+
<h3 class="col flex-grow-1">Shipping</h3>
15+
<span class="col flex-grow-0">Free</span>
16+
</div>
17+
18+
<div class="row">
19+
<h3 class="col flex-grow-1">Total</h3>
20+
<b class="col flex-grow-0" style="font-size: 18px">{{
21+
totalPrice | number: "1.2-2" | currency
22+
}}</b>
23+
</div>

src/app/cart/order-summary/order-summary.component.scss

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { OrderSummaryComponent } from './order-summary.component';
4+
5+
describe('OrderSummaryComponent', () => {
6+
let component: OrderSummaryComponent;
7+
let fixture: ComponentFixture<OrderSummaryComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
declarations: [OrderSummaryComponent],
12+
}).compileComponents();
13+
});
14+
15+
beforeEach(() => {
16+
fixture = TestBed.createComponent(OrderSummaryComponent);
17+
component = fixture.componentInstance;
18+
fixture.detectChanges();
19+
});
20+
21+
it('should create', () => {
22+
expect(component).toBeTruthy();
23+
});
24+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Component, EventEmitter, Input, Output } from '@angular/core';
2+
import { ProductCheckout } from '../../products/product.interface';
3+
4+
@Component({
5+
selector: 'app-order-summary',
6+
templateUrl: './order-summary.component.html',
7+
styleUrls: ['./order-summary.component.scss'],
8+
})
9+
export class OrderSummaryComponent {
10+
@Input() products!: ProductCheckout[];
11+
@Input() showControls!: boolean;
12+
@Input() totalPrice!: number;
13+
14+
/** Add productId */
15+
@Output() add = new EventEmitter<string>();
16+
/** Remove productId */
17+
@Output() remove = new EventEmitter<string>();
18+
}

0 commit comments

Comments
 (0)