Added Hooks
This commit is contained in:
parent
df23d64061
commit
bb8ea8cfae
@ -39,4 +39,4 @@
|
|||||||
"karma-jasmine-html-reporter": "~1.7.0",
|
"karma-jasmine-html-reporter": "~1.7.0",
|
||||||
"typescript": "~4.6.2"
|
"typescript": "~4.6.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
11
client/src/app/shared/components/pager/pager.component.html
Normal file
11
client/src/app/shared/components/pager/pager.component.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<pagination
|
||||||
|
[boundaryLinks]="true"
|
||||||
|
[totalItems]="totalCount"
|
||||||
|
(pageChanged)="onPagerChange($event)"
|
||||||
|
[itemsPerPage]="pageSize"
|
||||||
|
previousText="‹"
|
||||||
|
nextText="›"
|
||||||
|
firstText="«"
|
||||||
|
lastText="»"
|
||||||
|
>
|
||||||
|
</pagination>
|
22
client/src/app/shared/components/pager/pager.component.ts
Normal file
22
client/src/app/shared/components/pager/pager.component.ts
Normal file
@ -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<number>();
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
onPagerChange(e: any){
|
||||||
|
this.pageChanged.emit(e.page);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<header>
|
||||||
|
<span *ngIf="totalCount && totalCount > 0">
|
||||||
|
Showing
|
||||||
|
<strong>
|
||||||
|
{{(pageNumber-1) * pageSize+1}} -
|
||||||
|
{{pageNumber*pageSize > this.totalCount ? this.totalCount : pageNumber*pageSize}}
|
||||||
|
</strong> of <strong>{{totalCount}}</strong> Results
|
||||||
|
</span>
|
||||||
|
<span *ngIf="totalCount === 0">There are <strong>0 </strong>results for this filter.</span>
|
||||||
|
</header>
|
@ -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 {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
4
client/src/app/shared/models/brand.ts
Normal file
4
client/src/app/shared/models/brand.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface IBrand {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
}
|
4
client/src/app/shared/models/producttype.ts
Normal file
4
client/src/app/shared/models/producttype.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface IType {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
}
|
8
client/src/app/shared/models/shopparams.ts
Normal file
8
client/src/app/shared/models/shopparams.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export class ShopParams {
|
||||||
|
brandId: number = 0;
|
||||||
|
typeId: number = 0;
|
||||||
|
sort = 'name';
|
||||||
|
pageNumber: number = 1;
|
||||||
|
pageSize: number = 6;
|
||||||
|
search: string;
|
||||||
|
}
|
@ -1,12 +1,24 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
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({
|
@NgModule({
|
||||||
declarations: [],
|
declarations: [
|
||||||
|
PagingHeaderComponent,
|
||||||
|
PagerComponent
|
||||||
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule
|
CommonModule,
|
||||||
|
PaginationModule.forRoot()
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
PaginationModule,
|
||||||
|
PagingHeaderComponent,
|
||||||
|
PagerComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class SharedModule { }
|
export class SharedModule { }
|
||||||
|
13
client/src/app/shop/product-item/product-item.component.html
Normal file
13
client/src/app/shop/product-item/product-item.component.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<div class="card h-100 shadow-sm">
|
||||||
|
<img src="{{product.pictureUrl}}" alt="{{product.name}}" class="img-fluid bg-light">
|
||||||
|
<div class="card-body d-flex flex-column">
|
||||||
|
<a href="">
|
||||||
|
<h6 class="text-uppercase">{{product.name}}</h6>
|
||||||
|
</a>
|
||||||
|
<span class="mb-2">{{product.price | currency}}</span>
|
||||||
|
<div class="btn-group mt-auto">
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary fa fa-shopping-cart me-2"></button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
17
client/src/app/shop/product-item/product-item.component.ts
Normal file
17
client/src/app/shop/product-item/product-item.component.ts
Normal file
@ -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 {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,192 +2,62 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<section class="col-3">
|
<section class="col-3">
|
||||||
<h5 class="text-warning ml-3">Sort</h5>
|
<h5 class="text-warning ml-3">Sort</h5>
|
||||||
<select class="custom-select mb-3" style="width: 100%;">
|
<select class="form-select mb-3" style="width: 100%;" (change)="onSortSelected($event.target.value)">
|
||||||
<option selected>Name</option>
|
<option *ngFor="let sort of sortOptions"
|
||||||
<option>Price: Low to High</option>
|
[value]="sort.value"
|
||||||
<option>Price: High to Low</option>
|
>
|
||||||
|
{{sort.name}}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<h5 class="text-warning ml-3">Brands</h5>
|
<h5 class="text-warning ml-3">Brands</h5>
|
||||||
<ul class="list-group my-3">
|
<ul class="list-group my-3">
|
||||||
<li class="list-group-item active" aria-current="true">An active item</li>
|
<li class="list-group-item"
|
||||||
<li class="list-group-item">A second item</li>
|
*ngFor="let brand of brands"
|
||||||
<li class="list-group-item">A third item</li>
|
[class.active]="brand.id === this.shopParams.brandId"
|
||||||
<li class="list-group-item">A fourth item</li>
|
[value]="brand.id"
|
||||||
<li class="list-group-item">And a fifth one</li>
|
(click)="onBrandSelected(brand.id)"
|
||||||
|
>{{brand.name}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h5 class="text-warning ml-3">Type</h5>
|
<h5 class="text-warning ml-3">Type</h5>
|
||||||
<ul class="list-group my-3">
|
<ul class="list-group my-3">
|
||||||
<li class="list-group-item active" aria-current="true">An active item</li>
|
<li class="list-group-item"
|
||||||
<li class="list-group-item">A second item</li>
|
*ngFor="let type of productType"
|
||||||
<li class="list-group-item">A third item</li>
|
[class.active]="type.id === this.shopParams.typeId"
|
||||||
<li class="list-group-item">A fourth item</li>
|
[value]="type.id"
|
||||||
<li class="list-group-item">And a fifth one</li>
|
(click)="onTypeSelected(type.id)"
|
||||||
|
>{{type.name}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<section class="col-9">
|
<section class="col-9">
|
||||||
<div class="d-flex justify-content-between align-items-center pb-2">
|
<div class="d-flex justify-content-between align-items-center pb-2">
|
||||||
<header>
|
<app-paging-header
|
||||||
<span>Showing <strong>10</strong> of <strong>18</strong> Results</span>
|
[totalCount]="totalCount"
|
||||||
</header>
|
[pageSize]="this.shopParams.pageSize"
|
||||||
|
[pageNumber]="this.shopParams.pageNumber"
|
||||||
|
></app-paging-header>
|
||||||
<div class="row g-2 align-items-center">
|
<div class="row g-2 align-items-center">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<input style="width:300px" placeholder="Search" type="text" class="form-control">
|
<input (keyup.enter)="onSearch()" style="width:300px" #search placeholder="Search" type="text" class="form-control">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<button class="btn btn-outline-primary my-3 me-2">Search</button>
|
<button (click)="onSearch()" class="btn btn-outline-primary my-3 me-2">Search</button>
|
||||||
<button class="btn btn-outline-success my-3">Reset</button>
|
<button (click)="OnReset()" class="btn btn-outline-success my-3">Reset</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
|
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
|
||||||
<div class="col">
|
<div class="col mb-3" *ngFor="let item of products">
|
||||||
<div class="card shadow-sm">
|
<app-product-item [product]="item"></app-product-item>
|
||||||
<svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#43484b;"></rect><text x="50%" y="50%" fill="#eceeef" dy=".3em" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#dddad6;">Thumbnail</text></svg>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
|
|
||||||
</div>
|
|
||||||
<small class="text-muted">9 mins</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#43484b;"></rect><text x="50%" y="50%" fill="#eceeef" dy=".3em" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#dddad6;">Thumbnail</text></svg>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
|
|
||||||
</div>
|
|
||||||
<small class="text-muted">9 mins</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#43484b;"></rect><text x="50%" y="50%" fill="#eceeef" dy=".3em" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#dddad6;">Thumbnail</text></svg>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
|
|
||||||
</div>
|
|
||||||
<small class="text-muted">9 mins</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#43484b;"></rect><text x="50%" y="50%" fill="#eceeef" dy=".3em" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#dddad6;">Thumbnail</text></svg>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
|
|
||||||
</div>
|
|
||||||
<small class="text-muted">9 mins</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#43484b;"></rect><text x="50%" y="50%" fill="#eceeef" dy=".3em" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#dddad6;">Thumbnail</text></svg>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
|
|
||||||
</div>
|
|
||||||
<small class="text-muted">9 mins</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#43484b;"></rect><text x="50%" y="50%" fill="#eceeef" dy=".3em" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#dddad6;">Thumbnail</text></svg>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
|
|
||||||
</div>
|
|
||||||
<small class="text-muted">9 mins</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#43484b;"></rect><text x="50%" y="50%" fill="#eceeef" dy=".3em" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#dddad6;">Thumbnail</text></svg>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
|
|
||||||
</div>
|
|
||||||
<small class="text-muted">9 mins</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#43484b;"></rect><text x="50%" y="50%" fill="#eceeef" dy=".3em" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#dddad6;">Thumbnail</text></svg>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
|
|
||||||
</div>
|
|
||||||
<small class="text-muted">9 mins</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<div class="card shadow-sm">
|
|
||||||
<svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Thumbnail" preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#43484b;"></rect><text x="50%" y="50%" fill="#eceeef" dy=".3em" data-darkreader-inline-fill="" style="--darkreader-inline-fill:#dddad6;">Thumbnail</text></svg>
|
|
||||||
|
|
||||||
<div class="card-body">
|
|
||||||
<p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
|
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
|
||||||
<div class="btn-group">
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
|
|
||||||
</div>
|
|
||||||
<small class="text-muted">9 mins</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="d-flex justify-content-center" *ngIf="totalCount > 0">
|
||||||
|
<app-pager
|
||||||
|
[pageSize]="shopParams.pageSize"
|
||||||
|
[totalCount]="totalCount"
|
||||||
|
(pageChanged)="onPageChange($event)"
|
||||||
|
></app-pager>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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 { IProduct } from '../shared/models/product';
|
||||||
|
import { IType } from '../shared/models/producttype';
|
||||||
|
import { ShopParams } from '../shared/models/shopparams';
|
||||||
import { ShopService } from './shop.service';
|
import { ShopService } from './shop.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -8,19 +11,95 @@ import { ShopService } from './shop.service';
|
|||||||
styleUrls: ['./shop.component.scss']
|
styleUrls: ['./shop.component.scss']
|
||||||
})
|
})
|
||||||
export class ShopComponent implements OnInit {
|
export class ShopComponent implements OnInit {
|
||||||
|
@ViewChild('search', {static: true}) searchTerm: ElementRef;
|
||||||
products: IProduct[];
|
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) { }
|
constructor(private shopService: ShopService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
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); },
|
error: (e: any) => { console.log(e); },
|
||||||
complete: () => { console.log('complete'); }
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { ShopComponent } from './shop.component';
|
import { ShopComponent } from './shop.component';
|
||||||
|
import { ProductItemComponent } from './product-item/product-item.component';
|
||||||
|
import { SharedModule } from '../shared/shared.module';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
ShopComponent
|
ShopComponent,
|
||||||
|
ProductItemComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule
|
CommonModule,
|
||||||
|
SharedModule
|
||||||
],
|
],
|
||||||
exports: [ShopComponent]
|
exports: [ShopComponent]
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { IBrand } from '../shared/models/brand';
|
||||||
import { IPagination } from '../shared/models/pagination';
|
import { IPagination } from '../shared/models/pagination';
|
||||||
|
import { IType } from '../shared/models/producttype';
|
||||||
|
import { map } from 'rxjs/operators'
|
||||||
|
import { ShopParams } from '../shared/models/shopparams';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@ -10,7 +14,38 @@ export class ShopService {
|
|||||||
|
|
||||||
constructor(private http: HttpClient) { }
|
constructor(private http: HttpClient) { }
|
||||||
|
|
||||||
getProducts(){
|
getProducts(shopParams: ShopParams){
|
||||||
return this.http.get<IPagination>(this.baseURL + 'products');
|
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<IPagination>(this.baseURL + 'products', {observe: 'response', params})
|
||||||
|
.pipe(
|
||||||
|
map(response => {
|
||||||
|
return response.body;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getBrands(){
|
||||||
|
return this.http.get<IBrand[]>(this.baseURL + 'products/brands');
|
||||||
|
}
|
||||||
|
|
||||||
|
getTypes(){
|
||||||
|
return this.http.get<IType[]>(this.baseURL + 'products/types');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"angularCompilerOptions": {
|
"angularCompilerOptions": {
|
||||||
|
"strictTemplates": true,
|
||||||
|
"strictDomEventTypes": false,
|
||||||
"enableI18nLegacyMessageIdFormat": false
|
"enableI18nLegacyMessageIdFormat": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user