From 8ca857fe8404dddc825d8174ed720c7bd0cd5a64 Mon Sep 17 00:00:00 2001 From: Bello Babakolo Date: Fri, 19 Jan 2024 14:50:07 +0100 Subject: [PATCH] Refactor product page --- .../product-card/product-card.component.html | 94 +++++------ .../product-card/product-card.component.scss | 153 ++++++++++++++---- .../product-card/product-card.component.ts | 46 +----- .../product-variant-card.component.html | 49 ++++++ .../product-variant-card.component.scss} | 2 +- .../product-variant-card.component.ts | 27 ++++ .../product-variants.component.html | 63 -------- .../products/products.component.html | 53 +----- .../product-list/product-list.component.html | 7 + .../product-list/product-list.component.ts | 18 +++ .../product-variants.component.html | 9 ++ .../product-variants.component.ts | 16 +- src/app/features/products/products.module.ts | 21 ++- 13 files changed, 303 insertions(+), 255 deletions(-) create mode 100644 src/app/features/products/components/product-variant-card/product-variant-card.component.html rename src/app/features/products/components/{product-variants/product-variants.component.scss => product-variant-card/product-variant-card.component.scss} (99%) create mode 100644 src/app/features/products/components/product-variant-card/product-variant-card.component.ts delete mode 100644 src/app/features/products/components/product-variants/product-variants.component.html create mode 100644 src/app/features/products/pages/product-list/product-list.component.html create mode 100644 src/app/features/products/pages/product-list/product-list.component.ts create mode 100644 src/app/features/products/pages/product-variants/product-variants.component.html rename src/app/features/products/{components => pages}/product-variants/product-variants.component.ts (57%) diff --git a/src/app/features/products/components/product-card/product-card.component.html b/src/app/features/products/components/product-card/product-card.component.html index e51ee21..61c084e 100644 --- a/src/app/features/products/components/product-card/product-card.component.html +++ b/src/app/features/products/components/product-card/product-card.component.html @@ -1,47 +1,49 @@ - - - - - Product.additionalLabel - - - -
- - - product image - - +
+
+
+ {{ product.product.physical.variants.length }} Varaints +
+
- - {{ product.name }} - {{ - product.price.salePrice | currency: currency - }} - - - + +
+ + + product image + +
+ +
+ +
{{ product.product.name }}
+ diff --git a/src/app/features/products/components/product-card/product-card.component.scss b/src/app/features/products/components/product-card/product-card.component.scss index de20006..ae296e5 100644 --- a/src/app/features/products/components/product-card/product-card.component.scss +++ b/src/app/features/products/components/product-card/product-card.component.scss @@ -1,45 +1,132 @@ -.product-card { - width: 100%; - cursor: pointer; - box-shadow: 0.3em 0.5em 0.5em rgba($color: #000000, $alpha: 0.13); +:host(.product) { + background-color: white; + width: calc(33.333333% - 30px); + @media (max-width: 1100px) { + width: calc(50% - 30px); + } + @media (max-width: 700px) { + width: calc(100% - 30px); + } + margin-left: 10px; + margin-bottom: 10px; + display: grid; + padding: 10px; - &__title { - display: block; - text-align: center; - text-overflow: ellipsis; - letter-spacing: 1px; - padding-bottom: 0.5em; + &:hover { + box-shadow: 0 0 11px rgba(33, 33, 33, 0.2); } - &__price { - display: block; - text-align: center; - font-weight: 700; - padding-bottom: 0.5em; + .product-header { + .additional-label { + margin-left: -10px; + max-height: 0px; + margin-top: 4px; + + .text { + text-transform: uppercase; + font-family: Univers, sans-serif; + font-weight: 300; + font-size: 12px; + background-color: rgba(238, 238, 238, 0.7); + padding: 3px 0 1px 10px; + } + + .rounded-right { + background-color: red; + border: 1px solid transparent; + border-top-right-radius: 50%; + border-bottom-right-radius: 50%; + width: 21px; + background-color: rgba(238, 238, 238, 0.7); + } + } + + .like { + font-size: 18px; + -webkit-text-fill-color: transparent; + -webkit-text-stroke-width: 1px; + -webkit-text-stroke-color: black; + cursor: pointer; + border: 1px solid #dddddd; + border-radius: 50%; + width: 31px; + height: 31px; + text-indent: -1px; + line-height: 31px; + margin-left: auto; + + &:hover, + &.liked { + -webkit-text-fill-color: black; + } + } } - &__image { - min-height: 100%; - max-width: 100%; + .image-wrapper { + margin-top: 10px; + cursor: pointer; width: 100%; + padding-top: 150%; + position: relative; + + .image { + display: block; + width: 100%; + height: 100%; + position: absolute; + top: 0; + } } - &__quick-shop { - background-color: black; - color: white; - text-transform: uppercase; - text-decoration: none; - text-align: center; - position: absolute; - left: 0; - right: 0; - bottom: 0; - transform: translateY(110%); - width: 100%; - transition: transform 0.2s; + .spinner-wrapper { + min-height: 446px; + .spinner { + font-size: 40px; + } } - &:hover &__quick-shop { - transform: translateY(0); + .colors { + margin-top: 5px; + max-height: 26px; + + .color-wrapper { + margin: 2px; + cursor: pointer; + + .color { + width: 21px; + height: 21px; + background-color: white; + border: 1px solid rgb(153, 153, 153); + border-radius: 50%; + } + + padding: 2px; + border: 1px solid white; + border-radius: 50%; + + &.color-selected, + &:hover { + border: 1px solid rgb(153, 153, 153); + } + } + } + + .title { + font-family: Univers, sans-serif; + font-size: 14px; + font-weight: 300; + padding: 12px; + } + + .price { + font-family: Univers, sans-serif; + font-size: 12px; + font-weight: bold; + display: inline-block; + + &::first-letter { + padding-right: 7px; + } } } diff --git a/src/app/features/products/components/product-card/product-card.component.ts b/src/app/features/products/components/product-card/product-card.component.ts index 785b90f..9fc86a5 100644 --- a/src/app/features/products/components/product-card/product-card.component.ts +++ b/src/app/features/products/components/product-card/product-card.component.ts @@ -1,17 +1,16 @@ -import { Component, OnInit, Input } from '@angular/core'; -import { Router } from '@angular/router'; -import { IoRestorecommerceProductPhysicalVariant } from 'src/app/generated/graphql'; -import { ProductService } from '../../services/product.service'; +import { Component, HostBinding, Input } from '@angular/core'; +import { IoRestorecommerceProductProduct } from 'src/app/generated/graphql'; @Component({ selector: 'app-product-card', templateUrl: './product-card.component.html', styleUrls: ['./product-card.component.scss'], }) -export class ProductCardComponent implements OnInit { - @Input() product!: IoRestorecommerceProductPhysicalVariant; +export class ProductCardComponent { + @HostBinding('class') classes = 'column align-centered product'; + @Input() product!: IoRestorecommerceProductProduct; - currency: string; + currency = '€'; selectedColor: number; responsiveImagesConfiguration = [ @@ -27,36 +26,5 @@ export class ProductCardComponent implements OnInit { { width: 400, min: 1382, max: 99999, suffix: '-xl', format: 'jpeg' }, ]; - constructor(private router: Router, private productService: ProductService) {} - - onProductClicked() { - // this.router.navigateByUrl(this.product.urls['self']); - } - - ngOnInit(): void { - this.selectedColor = 0; - } - - onMouseEnter($event: string) { - this.onHoverColorPicker($event); - } - - onMouseLeave($event: string) { - this.onHoverColorPicker($event); - } - - private onHoverColorPicker(colorHovered: string) { - // if (this.product.selectedColor === colorHovered) { - // return; - // } - // if (!this.product.colors.find((color) => color === colorHovered)) { - // this.selectedColor = this.product.selectedColor; - // } else { - // this.selectedColor = colorHovered; - // } - } - - onLikeProduct() { - // this.product.like = !this.product.like; - } + // (click)="onProductClicked(product.id)" } diff --git a/src/app/features/products/components/product-variant-card/product-variant-card.component.html b/src/app/features/products/components/product-variant-card/product-variant-card.component.html new file mode 100644 index 0000000..a73eccd --- /dev/null +++ b/src/app/features/products/components/product-variant-card/product-variant-card.component.html @@ -0,0 +1,49 @@ +
+
+
{{ product.name }}
+
+
+ +
+ + + product image + +
+ +
+ +
{{ product.name }}
+
+ {{ product.price.salePrice | currency : currency }} +
diff --git a/src/app/features/products/components/product-variants/product-variants.component.scss b/src/app/features/products/components/product-variant-card/product-variant-card.component.scss similarity index 99% rename from src/app/features/products/components/product-variants/product-variants.component.scss rename to src/app/features/products/components/product-variant-card/product-variant-card.component.scss index 9d6e403..ae296e5 100644 --- a/src/app/features/products/components/product-variants/product-variants.component.scss +++ b/src/app/features/products/components/product-variant-card/product-variant-card.component.scss @@ -1,4 +1,4 @@ -.product { +:host(.product) { background-color: white; width: calc(33.333333% - 30px); @media (max-width: 1100px) { diff --git a/src/app/features/products/components/product-variant-card/product-variant-card.component.ts b/src/app/features/products/components/product-variant-card/product-variant-card.component.ts new file mode 100644 index 0000000..fedf3a4 --- /dev/null +++ b/src/app/features/products/components/product-variant-card/product-variant-card.component.ts @@ -0,0 +1,27 @@ +import { Component, HostBinding, Input } from '@angular/core'; +import { IoRestorecommerceProductPhysicalVariant } from 'src/app/generated/graphql'; + +@Component({ + selector: 'app-product-variant-card', + templateUrl: './product-variant-card.component.html', + styleUrls: ['./product-variant-card.component.scss'], +}) +export class ProductVariantCardComponent { + @HostBinding('class') classes = 'column align-centered product'; + @Input() product!: IoRestorecommerceProductPhysicalVariant; + + currency = '€'; + + responsiveImagesConfiguration = [ + { width: 400, min: 0, max: 1100.99, suffix: '-xl', format: 'webp' }, + { width: 400, min: 0, max: 1100.99, suffix: '-xl', format: 'jpeg' }, + { width: 190, min: 1101, max: 1156.99, suffix: '-sm', format: 'webp' }, + { width: 190, min: 1101, max: 1156.99, suffix: '-sm', format: 'jpeg' }, + { width: 260, min: 1157, max: 1268.99, suffix: '-md', format: 'webp' }, + { width: 260, min: 1157, max: 1268.99, suffix: '-md', format: 'jpeg' }, + { width: 330, min: 1269, max: 1381.99, suffix: '-lg', format: 'webp' }, + { width: 330, min: 1269, max: 1381.99, suffix: '-lg', format: 'jpeg' }, + { width: 400, min: 1382, max: 99999, suffix: '-xl', format: 'webp' }, + { width: 400, min: 1382, max: 99999, suffix: '-xl', format: 'jpeg' }, + ]; +} diff --git a/src/app/features/products/components/product-variants/product-variants.component.html b/src/app/features/products/components/product-variants/product-variants.component.html deleted file mode 100644 index 119fd6b..0000000 --- a/src/app/features/products/components/product-variants/product-variants.component.html +++ /dev/null @@ -1,63 +0,0 @@ - - - -
-
-
-
{{ variant.additionalLabel }}
-
-
- -
- - - product image - -
-
-
-
-
-
-
{{ variant.name }}
-
- {{ variant.price.salePrice | currency : currency }} -
-
-
-
diff --git a/src/app/features/products/components/products/products.component.html b/src/app/features/products/components/products/products.component.html index 47b347e..c92c0a9 100644 --- a/src/app/features/products/components/products/products.component.html +++ b/src/app/features/products/components/products/products.component.html @@ -55,58 +55,7 @@
-
-
-
-
{{ product.product.physical.variants.length }} Varaints
-
-
- -
- - - product image - -
-
-
-
-
-
-
{{ product.product.name }}
-
- {{ product.price | currency : currency }} -
-
+
diff --git a/src/app/features/products/pages/product-list/product-list.component.html b/src/app/features/products/pages/product-list/product-list.component.html new file mode 100644 index 0000000..82453d8 --- /dev/null +++ b/src/app/features/products/pages/product-list/product-list.component.html @@ -0,0 +1,7 @@ + + + diff --git a/src/app/features/products/pages/product-list/product-list.component.ts b/src/app/features/products/pages/product-list/product-list.component.ts new file mode 100644 index 0000000..02bfa98 --- /dev/null +++ b/src/app/features/products/pages/product-list/product-list.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { Router } from '@angular/router'; +import { ProductService } from 'src/app/features/products/services/product.service'; + +@Component({ + selector: 'app-product-list', + templateUrl: './product-list.component.html', +}) +export class ProductListComponent { + products$ = this.productService.products$; + pageTitle = "Men's shoes"; + + constructor(private productService: ProductService, private router: Router) {} + + onProductClicked(productId: string) { + this.router.navigateByUrl(`products/${productId}`); + } +} diff --git a/src/app/features/products/pages/product-variants/product-variants.component.html b/src/app/features/products/pages/product-variants/product-variants.component.html new file mode 100644 index 0000000..d9b5e0f --- /dev/null +++ b/src/app/features/products/pages/product-variants/product-variants.component.html @@ -0,0 +1,9 @@ + + + + + diff --git a/src/app/features/products/components/product-variants/product-variants.component.ts b/src/app/features/products/pages/product-variants/product-variants.component.ts similarity index 57% rename from src/app/features/products/components/product-variants/product-variants.component.ts rename to src/app/features/products/pages/product-variants/product-variants.component.ts index 30f896f..d13b2fa 100644 --- a/src/app/features/products/components/product-variants/product-variants.component.ts +++ b/src/app/features/products/pages/product-variants/product-variants.component.ts @@ -7,23 +7,9 @@ import { ProductService } from 'src/app/features/products/services/product.servi @Component({ selector: 'app-product-variants', templateUrl: './product-variants.component.html', - styleUrls: ['./product-variants.component.scss'], }) export class ProductVariantsComponent { - currency = '€'; - responsiveImagesConfiguration = [ - { width: 400, min: 0, max: 1100.99, suffix: '-xl', format: 'webp' }, - { width: 400, min: 0, max: 1100.99, suffix: '-xl', format: 'jpg' }, - { width: 190, min: 1101, max: 1156.99, suffix: '-sm', format: 'webp' }, - { width: 190, min: 1101, max: 1156.99, suffix: '-sm', format: 'jpg' }, - { width: 260, min: 1157, max: 1268.99, suffix: '-md', format: 'webp' }, - { width: 260, min: 1157, max: 1268.99, suffix: '-md', format: 'jpg' }, - { width: 330, min: 1269, max: 1381.99, suffix: '-lg', format: 'webp' }, - { width: 330, min: 1269, max: 1381.99, suffix: '-lg', format: 'jpg' }, - { width: 400, min: 1382, max: 99999, suffix: '-xl', format: 'webp' }, - { width: 400, min: 1382, max: 99999, suffix: '-xl', format: 'jpg' }, - ]; - + // Use the route params. productId$ = this.route.params.pipe( map((params) => params.productId as string) ); diff --git a/src/app/features/products/products.module.ts b/src/app/features/products/products.module.ts index 3afa652..c198aa2 100644 --- a/src/app/features/products/products.module.ts +++ b/src/app/features/products/products.module.ts @@ -4,7 +4,7 @@ import { RouterModule, Routes } from '@angular/router'; import { ShoesComponent } from './components/shoes/shoes.component'; import { ShoesProductsComponent } from './components/shoes-products/shoes-products.component'; import { ProductComponent } from './components/product/product.component'; -import { ProductVariantsComponent } from './components/product-variants/product-variants.component'; +import { ProductVariantsComponent } from './pages/product-variants/product-variants.component'; import { ProductsTemplateComponent } from './templates/products-template/products-template.component'; import { ProductCardComponent } from './components/product-card/product-card.component'; import { ProductColorPickerComponent } from './components/product-color-picker/product-color-picker.component'; @@ -25,6 +25,8 @@ import { VCLZoomBoxModule, } from '@vcl/ng-vcl'; import { ProductZoomComponent } from './components/product-zoom/product-zoom.component'; +import { ProductVariantCardComponent } from './components/product-variant-card/product-variant-card.component'; +import { ProductListComponent } from './pages/product-list/product-list.component'; const vclModules = [ VCLSelectModule, @@ -40,16 +42,21 @@ const routes: Routes = [ children: [ { path: '', - component: ShoesProductsComponent, + children: [ + { + path: '', + component: ProductListComponent, + }, + { + path: ':productId', + component: ProductVariantsComponent, + }, + ], }, { path: ':productId/variants/:variantId', component: ProductComponent, }, - { - path: ':productId', - component: ProductVariantsComponent, - }, ], }, ]; @@ -75,6 +82,8 @@ const routes: Routes = [ ProductRecommendComponent, ProductSizePickerComponent, ProductZoomComponent, + ProductVariantCardComponent, + ProductListComponent ], imports: [ CommonModule,