From bb8ea8cfae00a5f13e7559760285c57a58dfd145 Mon Sep 17 00:00:00 2001 From: Charles Showalter Date: Fri, 13 May 2022 13:26:38 -0700 Subject: [PATCH] Added Hooks --- client/package.json | 2 +- .../components/pager/pager.component.html | 11 + .../components/pager/pager.component.scss | 0 .../components/pager/pager.component.ts | 22 ++ .../paging-header.component.html | 10 + .../paging-header.component.scss | 0 .../paging-header/paging-header.component.ts | 18 ++ client/src/app/shared/models/brand.ts | 4 + client/src/app/shared/models/producttype.ts | 4 + client/src/app/shared/models/shopparams.ts | 8 + client/src/app/shared/shared.module.ts | 16 +- .../product-item/product-item.component.html | 13 ++ .../product-item/product-item.component.scss | 0 .../product-item/product-item.component.ts | 17 ++ client/src/app/shop/shop.component.html | 200 +++--------------- client/src/app/shop/shop.component.ts | 87 +++++++- client/src/app/shop/shop.module.ts | 8 +- client/src/app/shop/shop.service.ts | 41 +++- client/tsconfig.json | 2 + 19 files changed, 286 insertions(+), 177 deletions(-) create mode 100644 client/src/app/shared/components/pager/pager.component.html create mode 100644 client/src/app/shared/components/pager/pager.component.scss create mode 100644 client/src/app/shared/components/pager/pager.component.ts create mode 100644 client/src/app/shared/components/paging-header/paging-header.component.html create mode 100644 client/src/app/shared/components/paging-header/paging-header.component.scss create mode 100644 client/src/app/shared/components/paging-header/paging-header.component.ts create mode 100644 client/src/app/shared/models/brand.ts create mode 100644 client/src/app/shared/models/producttype.ts create mode 100644 client/src/app/shared/models/shopparams.ts create mode 100644 client/src/app/shop/product-item/product-item.component.html create mode 100644 client/src/app/shop/product-item/product-item.component.scss create mode 100644 client/src/app/shop/product-item/product-item.component.ts diff --git a/client/package.json b/client/package.json index 46033c0..c9c1b84 100644 --- a/client/package.json +++ b/client/package.json @@ -39,4 +39,4 @@ "karma-jasmine-html-reporter": "~1.7.0", "typescript": "~4.6.2" } -} +} \ No newline at end of file diff --git a/client/src/app/shared/components/pager/pager.component.html b/client/src/app/shared/components/pager/pager.component.html new file mode 100644 index 0000000..9e00589 --- /dev/null +++ b/client/src/app/shared/components/pager/pager.component.html @@ -0,0 +1,11 @@ + + diff --git a/client/src/app/shared/components/pager/pager.component.scss b/client/src/app/shared/components/pager/pager.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/client/src/app/shared/components/pager/pager.component.ts b/client/src/app/shared/components/pager/pager.component.ts new file mode 100644 index 0000000..8874de2 --- /dev/null +++ b/client/src/app/shared/components/pager/pager.component.ts @@ -0,0 +1,22 @@ +import { Component, EventEmitter, Input, Output, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-pager', + templateUrl: './pager.component.html', + styleUrls: ['./pager.component.scss'] +}) +export class PagerComponent implements OnInit { + @Input() totalCount: number; + @Input() pageSize: number; + @Output() pageChanged = new EventEmitter(); + + constructor() { } + + ngOnInit(): void { + } + + onPagerChange(e: any){ + this.pageChanged.emit(e.page); + } + +} diff --git a/client/src/app/shared/components/paging-header/paging-header.component.html b/client/src/app/shared/components/paging-header/paging-header.component.html new file mode 100644 index 0000000..9f442c0 --- /dev/null +++ b/client/src/app/shared/components/paging-header/paging-header.component.html @@ -0,0 +1,10 @@ +
+ + Showing + + {{(pageNumber-1) * pageSize+1}} - + {{pageNumber*pageSize > this.totalCount ? this.totalCount : pageNumber*pageSize}} + of {{totalCount}} Results + + There are 0 results for this filter. +
diff --git a/client/src/app/shared/components/paging-header/paging-header.component.scss b/client/src/app/shared/components/paging-header/paging-header.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/client/src/app/shared/components/paging-header/paging-header.component.ts b/client/src/app/shared/components/paging-header/paging-header.component.ts new file mode 100644 index 0000000..dab57f9 --- /dev/null +++ b/client/src/app/shared/components/paging-header/paging-header.component.ts @@ -0,0 +1,18 @@ +import { Component, Input, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-paging-header', + templateUrl: './paging-header.component.html', + styleUrls: ['./paging-header.component.scss'] +}) +export class PagingHeaderComponent implements OnInit { + @Input() pageNumber: number; + @Input() pageSize: number; + @Input() totalCount: number; + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/client/src/app/shared/models/brand.ts b/client/src/app/shared/models/brand.ts new file mode 100644 index 0000000..7940e2b --- /dev/null +++ b/client/src/app/shared/models/brand.ts @@ -0,0 +1,4 @@ +export interface IBrand { + id: number; + name: string; +} diff --git a/client/src/app/shared/models/producttype.ts b/client/src/app/shared/models/producttype.ts new file mode 100644 index 0000000..b6dd70a --- /dev/null +++ b/client/src/app/shared/models/producttype.ts @@ -0,0 +1,4 @@ +export interface IType { + id: number; + name: string; +} diff --git a/client/src/app/shared/models/shopparams.ts b/client/src/app/shared/models/shopparams.ts new file mode 100644 index 0000000..8d8b2d7 --- /dev/null +++ b/client/src/app/shared/models/shopparams.ts @@ -0,0 +1,8 @@ +export class ShopParams { + brandId: number = 0; + typeId: number = 0; + sort = 'name'; + pageNumber: number = 1; + pageSize: number = 6; + search: string; +} diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 76cf203..2a8c68a 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -1,12 +1,24 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { PaginationModule } from 'ngx-bootstrap/pagination'; +import { PagingHeaderComponent } from './components/paging-header/paging-header.component'; +import { PagerComponent } from './components/pager/pager.component'; @NgModule({ - declarations: [], + declarations: [ + PagingHeaderComponent, + PagerComponent + ], imports: [ - CommonModule + CommonModule, + PaginationModule.forRoot() + ], + exports: [ + PaginationModule, + PagingHeaderComponent, + PagerComponent ] }) export class SharedModule { } diff --git a/client/src/app/shop/product-item/product-item.component.html b/client/src/app/shop/product-item/product-item.component.html new file mode 100644 index 0000000..426b225 --- /dev/null +++ b/client/src/app/shop/product-item/product-item.component.html @@ -0,0 +1,13 @@ +
+ {{product.name}} +
+ +
{{product.name}}
+
+ {{product.price | currency}} +
+ + +
+
+
diff --git a/client/src/app/shop/product-item/product-item.component.scss b/client/src/app/shop/product-item/product-item.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/client/src/app/shop/product-item/product-item.component.ts b/client/src/app/shop/product-item/product-item.component.ts new file mode 100644 index 0000000..175617c --- /dev/null +++ b/client/src/app/shop/product-item/product-item.component.ts @@ -0,0 +1,17 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { IProduct } from 'src/app/shared/models/product'; + +@Component({ + selector: 'app-product-item', + templateUrl: './product-item.component.html', + styleUrls: ['./product-item.component.scss'] +}) +export class ProductItemComponent implements OnInit { + @Input() product: IProduct + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/client/src/app/shop/shop.component.html b/client/src/app/shop/shop.component.html index e3864b9..0975315 100644 --- a/client/src/app/shop/shop.component.html +++ b/client/src/app/shop/shop.component.html @@ -2,192 +2,62 @@
Sort
- +
Brands
    -
  • An active item
  • -
  • A second item
  • -
  • A third item
  • -
  • A fourth item
  • -
  • And a fifth one
  • +
  • {{brand.name}}
Type
    -
  • An active item
  • -
  • A second item
  • -
  • A third item
  • -
  • A fourth item
  • -
  • And a fifth one
  • +
  • {{type.name}}
-
- Showing 10 of 18 Results -
+
- +
- - + +
-
-
- PlaceholderThumbnail - -
-

This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

-
-
- - -
- 9 mins -
-
-
-
-
-
- PlaceholderThumbnail - -
-

This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

-
-
- - -
- 9 mins -
-
-
-
-
-
- PlaceholderThumbnail - -
-

This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

-
-
- - -
- 9 mins -
-
-
-
- -
-
- PlaceholderThumbnail - -
-

This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

-
-
- - -
- 9 mins -
-
-
-
-
-
- PlaceholderThumbnail - -
-

This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

-
-
- - -
- 9 mins -
-
-
-
-
-
- PlaceholderThumbnail - -
-

This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

-
-
- - -
- 9 mins -
-
-
-
- -
-
- PlaceholderThumbnail - -
-

This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

-
-
- - -
- 9 mins -
-
-
-
-
-
- PlaceholderThumbnail - -
-

This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

-
-
- - -
- 9 mins -
-
-
-
-
-
- PlaceholderThumbnail - -
-

This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

-
-
- - -
- 9 mins -
-
-
+
+
+
+ +
diff --git a/client/src/app/shop/shop.component.ts b/client/src/app/shop/shop.component.ts index 3a76bdc..7b18a20 100644 --- a/client/src/app/shop/shop.component.ts +++ b/client/src/app/shop/shop.component.ts @@ -1,5 +1,8 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; +import { IBrand } from '../shared/models/brand'; import { IProduct } from '../shared/models/product'; +import { IType } from '../shared/models/producttype'; +import { ShopParams } from '../shared/models/shopparams'; import { ShopService } from './shop.service'; @Component({ @@ -8,19 +11,95 @@ import { ShopService } from './shop.service'; styleUrls: ['./shop.component.scss'] }) export class ShopComponent implements OnInit { - + @ViewChild('search', {static: true}) searchTerm: ElementRef; products: IProduct[]; + brands: IBrand[]; + productType: IType[]; + shopParams = new ShopParams(); + totalCount: number; + sortOptions = [ + {name: 'Name', value: 'name'}, + {name: 'Price: Low to High', value: 'priceAsc'}, + {name: 'Price: High to Low', value: 'priceDesc'} + ]; constructor(private shopService: ShopService) { } ngOnInit(): void { - this.shopService.getProducts().subscribe( + this.getProducts(); + this.getBrands(); + this.getTypes(); + } + + getProducts(){ + this.shopService.getProducts(this.shopParams).subscribe( { - next: (response) => { this.products = response.data; }, + next: (response) => { + this.products = response.data; + this.shopParams.pageNumber = response.pageIndex; + this.shopParams.pageSize = response.pageSize; + this.totalCount = response.count; + }, error: (e: any) => { console.log(e); }, complete: () => { console.log('complete'); } } ); } + getBrands(){ + this.shopService.getBrands().subscribe( + { + next: (response) => { this.brands = [{id: 0, name: 'All'}, ...response]; }, + error: (e: any) => { console.log(e); }, + complete: () => { console.log('complete'); } + } + ); + } + + getTypes(){ + this.shopService.getTypes().subscribe( + { + next: (response) => { this.productType = [{id: 0, name: 'All'}, ...response]; }, + error: (e: any) => { console.log(e); }, + complete: () => { console.log('complete'); } + } + ); + } + + onBrandSelected(brandId: number){ + this.shopParams.brandId = brandId; + this.shopParams.pageNumber = 1; + this.getProducts(); + } + + onTypeSelected(typeId: number){ + this.shopParams.typeId = typeId; + this.shopParams.pageNumber = 1; + this.getProducts(); + } + + onSortSelected(sort: string){ + this.shopParams.sort = sort; + this.getProducts(); + } + + onPageChange(e: any){ + if (this.shopParams.pageNumber !== e){ + this.shopParams.pageNumber = e; + this.getProducts(); + } + } + + onSearch(){ + this.shopParams.search = this.searchTerm.nativeElement.value; + this.shopParams.pageNumber = 1; + this.getProducts(); + } + + OnReset(){ + this.searchTerm.nativeElement.value = ''; + this.shopParams = new ShopParams(); + this.getProducts(); + } + } diff --git a/client/src/app/shop/shop.module.ts b/client/src/app/shop/shop.module.ts index 80eef53..4e017c3 100644 --- a/client/src/app/shop/shop.module.ts +++ b/client/src/app/shop/shop.module.ts @@ -1,15 +1,19 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ShopComponent } from './shop.component'; +import { ProductItemComponent } from './product-item/product-item.component'; +import { SharedModule } from '../shared/shared.module'; @NgModule({ declarations: [ - ShopComponent + ShopComponent, + ProductItemComponent ], imports: [ - CommonModule + CommonModule, + SharedModule ], exports: [ShopComponent] }) diff --git a/client/src/app/shop/shop.service.ts b/client/src/app/shop/shop.service.ts index 38dd86d..8ff943c 100644 --- a/client/src/app/shop/shop.service.ts +++ b/client/src/app/shop/shop.service.ts @@ -1,6 +1,10 @@ -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; +import { IBrand } from '../shared/models/brand'; import { IPagination } from '../shared/models/pagination'; +import { IType } from '../shared/models/producttype'; +import { map } from 'rxjs/operators' +import { ShopParams } from '../shared/models/shopparams'; @Injectable({ providedIn: 'root' @@ -10,7 +14,38 @@ export class ShopService { constructor(private http: HttpClient) { } - getProducts(){ - return this.http.get(this.baseURL + 'products'); + getProducts(shopParams: ShopParams){ + let params = new HttpParams(); + + if (shopParams.brandId !== 0){ + params = params.append('brandId', shopParams.brandId.toString()); + } + + if(shopParams.typeId !== 0){ + params = params.append('typeId', shopParams.typeId.toString()); + } + + if (shopParams.search){ + params = params.append('search', shopParams.search); + } + + params = params.append('sort', shopParams.sort); + params = params.append('pageIndex', shopParams.pageNumber.toString()); + params = params.append('pageIndex', shopParams.pageSize.toString()); + + return this.http.get(this.baseURL + 'products', {observe: 'response', params}) + .pipe( + map(response => { + return response.body; + }) + ); + } + + getBrands(){ + return this.http.get(this.baseURL + 'products/brands'); + } + + getTypes(){ + return this.http.get(this.baseURL + 'products/types'); } } diff --git a/client/tsconfig.json b/client/tsconfig.json index 7e00c96..8a3290d 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -18,6 +18,8 @@ ] }, "angularCompilerOptions": { + "strictTemplates": true, + "strictDomEventTypes": false, "enableI18nLegacyMessageIdFormat": false } }