Skip to content

Commit

Permalink
Merge branch 'main' into CFWEB-121---Interoperate-@Defer-and-migrate-…
Browse files Browse the repository at this point in the history
…control-structures

# Conflicts:
#	src/app/catalog/product/components/product-detail/product-detail.component.html
#	src/app/catalog/product/product.module.ts
#	src/app/shared/components/product/product.component.ts
  • Loading branch information
Kancso0 committed Oct 29, 2024
2 parents 518c9f6 + 3b07183 commit 399b035
Show file tree
Hide file tree
Showing 28 changed files with 628 additions and 79 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
- name: Install Dependencies
if: steps.cache-nodemodules.outputs.cache-hit != 'true'
run: |
npm i
npm ci
# install playwright
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
"rxjs": "7.8.1",
"stylelint-config-scss": "1.0.0-security",
"tslib": "2.6.2",
"zone.js": "0.14.4"
"zone.js": "0.14.4",
"@ngrx/signals": "^18.0.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "18.1.3",
Expand Down
2 changes: 1 addition & 1 deletion src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
~ SPDX-FileCopyrightText: (c) 2022 Carl Zeiss AG
~ SPDX-License-Identifier: MIT
-->

<app-shopping-cart></app-shopping-cart>
<router-outlet></router-outlet>
4 changes: 3 additions & 1 deletion src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@

import { TestBed, waitForAsync } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { provideMockStore } from '@ngrx/store/testing';

describe('AppComponent', () => {
beforeEach(() =>
TestBed.configureTestingModule({
imports: [AppComponent],
})
providers: [provideMockStore({ initialState: {} })],
}),
);

it('should create the app', waitForAsync(() => {
Expand Down
3 changes: 2 additions & 1 deletion src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { ShoppingCartComponent } from '@app/shared/components/shopping-cart/shopping-cart.component';

@Component({
selector: 'app-root',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [RouterOutlet],
imports: [RouterOutlet, ShoppingCartComponent],
templateUrl: './app.component.html',
})
export class AppComponent {}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
~ SPDX-License-Identifier: MIT
-->

<header *ngIf="product$ | async as product">
<app-theme-switcher></app-theme-switcher>
<h1>{{ product.title }}</h1>
</header>

<div class="container">
<div class="row">
@if (product$ | async; as product) {
Expand All @@ -13,19 +18,21 @@
<h2>{{ product.title }}</h2>

<h3>Price</h3>
<p>{{ product.price }}</p>
<p>{{ product.price }}</p>

<div>
<h3>Number of items</h3>
<button class="confirmation-button" (click)="decreaseProductNumber()">-</button>
<button class="counter-button" (click)="decreaseProductNumber()">-</button>
{{ productNumber() }}
<button class="confirmation-button" (click)="increseProductNumber()">+</button>
<button class="counter-button" (click)="increseProductNumber()">+</button>
</div>

<h3>Ingredients</h3>
<p>{{ product.description }}</p>

<button class="confirmation-button" (click)="showConfirmation()">Buy Online</button>
<div class="button-container">
<button (click)="addToCart()">Add to cart</button>
</div>
</div>
</div>
<button class="back-button" (click)="backToProductOverview()">Back to all products</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

@use '../../../../../support/styling/common-styles' as common;

header {
@include common.header-style;
}

div.container {
margin-top: 25px;
margin-bottom: 25px;
Expand Down Expand Up @@ -50,12 +54,21 @@ div.container {
}
}

.confirmation-button {
margin-bottom: 50px;
@include common.button-primary;
.button-container {
display: flex;
gap: 20px;
margin: 50px 0;

button {
@include common.button-primary;
}
}

.back-button {
margin: 50px 0;
@include common.button-secondary;
}

.counter-button {
@include common.button-primary;
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,6 @@ describe('ProductDetailComponent', () => {
expect(component).toBeTruthy();
});

describe('showConfirmation', () => {
it('should dispatch navigate action to order page', () => {
component.showConfirmation();

expect(store.dispatch).toHaveBeenCalledWith(navigate({ url: '/order' }));
});
});

describe('backToProductOverview', () => {
it('should dispatch navigate action to root page', () => {
component.backToProductOverview();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,57 @@
* SPDX-License-Identifier: MIT
*/

import { ChangeDetectionStrategy, Component, OnInit, signal } from '@angular/core';
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
inject,
OnDestroy,
OnInit,
signal,
} from '@angular/core';
import { Store } from '@ngrx/store';

import { selectCurrentProductDetails } from '@app/catalog/product/store/product.selectors';
import { navigate } from '@app/shared/navigation/navigation.actions';
import { StateWithCatalog } from '@app/catalog/store/catalog.reducer';
import { loadProductDetails } from '@app/catalog/product/store/product.actions';
import { ActivatedRoute } from '@angular/router';
import { ShoppingCartStore } from '@app/shared/signal-store/shopping-cart.store';
import { Product } from '@models/product';
import { Subscription } from 'rxjs';
import { productToProductInCart } from '@models/product.mapper';

@Component({
selector: 'app-product-detail',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './product-detail.component.html',
styleUrls: ['./product-detail.component.scss'],
})
export class ProductDetailComponent implements OnInit {
export class ProductDetailComponent implements OnInit, OnDestroy {
product$ = this.store.select(selectCurrentProductDetails);
private loadedProduct: Product;
private loadProductSubscription: Subscription;

public shoppingCartSignalStore = inject(ShoppingCartStore);

productNumber = signal(1);

constructor(private store: Store<StateWithCatalog>, private route: ActivatedRoute) {}
constructor(
private store: Store<StateWithCatalog>,
private route: ActivatedRoute,
private cdr: ChangeDetectorRef,
) {}

backToProductOverview(): void {
this.store.dispatch(navigate({ url: '/' }));
}

showConfirmation(): void {
this.store.dispatch(navigate({ url: '/order' }));
addToCart(): void {
this.shoppingCartSignalStore.addProduct({
...productToProductInCart(this.loadedProduct, this.productNumber()),
});
this.cdr.markForCheck();
}

increseProductNumber(): void {
Expand All @@ -41,8 +64,17 @@ export class ProductDetailComponent implements OnInit {
this.productNumber.update((c) => (c > 1 ? c - 1 : 1));
}

ngOnInit() {
public ngOnInit() {
const productId: number = Number.parseInt(this.route.snapshot.paramMap.get('id'));
this.store.dispatch(loadProductDetails({ productId: productId }));
this.loadProductSubscription = this.product$.subscribe({
next: (product: Product) => (this.loadedProduct = product),
error: (error: Error) =>
console.log(`Error while loading product in ProductDetailsComponent: ${error}`),
});
}

public ngOnDestroy() {
this.loadProductSubscription.unsubscribe();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,10 @@
* SPDX-License-Identifier: MIT
*/

header {
background-color: var(--color-highlight);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: var(--color-highlight-text);
letter-spacing: 0.2em;
padding: 20px;

h1 {
font-size: 65px;
font-weight: 100;
margin: 30px 0;
}
@use '../../../../../support/styling/common-styles' as common;

h2 {
font-size: 35px;
font-weight: 100;
}
}

app-theme-switcher {
align-self: end;
header {
@include common.header-style;
}

div.container {
Expand Down
12 changes: 10 additions & 2 deletions src/app/catalog/product/product.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: MIT
*/

import { CommonModule } from '@angular/common';
import { AsyncPipe, CommonModule } from '@angular/common';
import { provideHttpClient } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { provideEffects } from '@ngrx/effects';
Expand All @@ -15,12 +15,20 @@ import { ProductEffects } from '@app/catalog/product/store/product.effects';
import { RecommendationModule } from '@app/catalog/recommendation/recommendation.module';
import { ThemeSwitcherComponent } from '@app/shared/components/theme/theme-switcher.component';
import { ProductComponent } from '@app/shared/components/product/product.component';
import { ShoppingCartStore } from '@app/shared/signal-store/shopping-cart.store';
import { ViewportService } from '@app/catalog/recommendation/services/viewport.service';

@NgModule({
declarations: [ProductDetailComponent, ProductMasterComponent],
exports: [ProductDetailComponent, ProductMasterComponent],
imports: [CommonModule, RecommendationModule, ProductComponent, ThemeSwitcherComponent],
providers: [ProductService, ViewportService, provideEffects(ProductEffects), provideHttpClient()],
providers: [
ProductService,
provideEffects(ProductEffects),
provideHttpClient(),
AsyncPipe,
ShoppingCartStore,
ViewportService,
],
})
export class ProductModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@
~ SPDX-FileCopyrightText: (c) 2022 Carl Zeiss AG
~ SPDX-License-Identifier: MIT
-->

<header>
<app-theme-switcher></app-theme-switcher>
<div id="confirmation-info">
<h1>Order confirmed.</h1>
<h2>Your ice cream is on its way to you.</h2>
</div>
</header>
<div class="container">
<div class="row">
<div id="confirmation-info">
<h3>Order confirmed.</h3>
<h2>Your ice cream is on its way to you.</h2>
<div class="purchased-products" *ngIf="purchasedProducts as products">
<h2>Purchased Products</h2>

<div class="items">
<div class="item" *ngFor="let product of products">
<img [attr.src]="product.image" />
<span>{{ product.title }}</span>
<span>{{ product.price }} €</span>
<span>X {{ product.count }}</span>
</div>
</div>
</div>
<button id="back-button" (click)="backToProductOverview()">Back to all products</button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,36 @@

@use '../../../../support/styling/common-styles' as common;

div.container {
width: auto;
h2 {
font-size: 35px;
font-weight: 100;
}

h3 {
font-size: 25px;
font-weight: 100;
margin-bottom: 0;
}
header {
@include common.header-style;
}

div.container {
#back-button {
margin: 25px 0;
@include common.button-secondary;
}

#confirmation-info {
background-color: var(--color-highlight);
color: var(--color-highlight-text);
.purchased-products {
padding: 20px;

.items {
display: grid;
gap: 10px;

.item {
display: grid;
grid-template-columns: 1fr 1fr 1fr auto;

img {
width: 8em;
}

span {
align-content: center;
padding: 10px;
}
}
}
}
}
Loading

0 comments on commit 399b035

Please sign in to comment.