10 changed files with 276 additions and 1 deletions
Split View
Diff Options
-
4src/app/app.module.ts
-
0src/app/components/product-list/product-list.component.css
-
60src/app/components/product-list/product-list.component.html
-
25src/app/components/product-list/product-list.component.spec.ts
-
87src/app/components/product-list/product-list.component.ts
-
4src/app/models/product-category.ts
-
12src/app/models/product.ts
-
16src/app/services/product-service.service.spec.ts
-
68src/app/services/product-service.service.ts
-
1tsconfig.json
@ -0,0 +1,60 @@ |
|||
<div class="main-content"> |
|||
<div class="section-content section-content-p30"> |
|||
<div class="container-fluid"> |
|||
<div *ngFor="let prod of products" class="col-md-3"> |
|||
<div class="card card-cascade card-ecommerce wider shadow mb-5 "> |
|||
<div class="view view-cascade overlay text-center"> |
|||
<a routerLink="/products/{{ prod.id }}"> |
|||
<img src="{{ prod.imageUrl }}" alt="prod.imageUrl" class="img-responsive"> |
|||
</a> |
|||
<a> |
|||
<div class="mask rgba-white-slight"></div> |
|||
</a> |
|||
</div> |
|||
<div class="card-body card-body-cascade text-center"> |
|||
<h4 class="card-title"><strong><a routerLink="/products/{{ prod.id }}">{{ prod.name }}</a></strong></h4> |
|||
<p class="card-text">This is a Mobile phone with all the advance features and at best price. </p> |
|||
<p class="price">{{ prod.unitPrice | currency:'USD' }}</p> |
|||
<ul class="row rating"> |
|||
<li><i class="fa fa-star"></i></li> |
|||
<li><i class="fa fa-star"></i></li> |
|||
<li><i class="fa fa-star"></i></li> |
|||
<li><i class="fa fa-star"></i></li> |
|||
<li><i class="fa fa-star"></i></li> |
|||
</ul> |
|||
<div class="card-footer"> |
|||
<a (click)="addToCart(prod)" class="clickable"> ADD TO CART </a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div *ngIf="products?.length == 0" class="alert alert-warning col-md-12" role="alert" > |
|||
No products found. |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
|
|||
<div class="footer-pagination"> |
|||
<div class="row"> |
|||
<div class="col-md-6"></div> |
|||
<div class="col-md-6"> |
|||
<div class="row"> |
|||
<div class="col-md-9"> |
|||
<!-- <ngb-pagination [(page)]="thePageNumber" |
|||
[pageSize]="thePageSize" |
|||
[collectionSize]="theTotalElements" |
|||
(pageChange)="listProducts()"> |
|||
|
|||
</ngb-pagination> --> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,25 @@ |
|||
import { ComponentFixture, TestBed } from '@angular/core/testing'; |
|||
|
|||
import { ProductListComponent } from './product-list.component'; |
|||
|
|||
describe('ProductListComponent', () => { |
|||
let component: ProductListComponent; |
|||
let fixture: ComponentFixture<ProductListComponent>; |
|||
|
|||
beforeEach(async () => { |
|||
await TestBed.configureTestingModule({ |
|||
declarations: [ ProductListComponent ] |
|||
}) |
|||
.compileComponents(); |
|||
}); |
|||
|
|||
beforeEach(() => { |
|||
fixture = TestBed.createComponent(ProductListComponent); |
|||
component = fixture.componentInstance; |
|||
fixture.detectChanges(); |
|||
}); |
|||
|
|||
it('should create', () => { |
|||
expect(component).toBeTruthy(); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,87 @@ |
|||
import { Component, OnInit } from '@angular/core'; |
|||
import {Product} from './../../models/product'; |
|||
import {ProductServiceService} from './../../services/product-service.service'; |
|||
import {ActivatedRoute} from '@angular/router'; |
|||
|
|||
|
|||
@Component({ |
|||
selector: 'app-product-list', |
|||
templateUrl: './product-list.component.html', |
|||
styleUrls: ['./product-list.component.css'] |
|||
}) |
|||
export class ProductListComponent implements OnInit { |
|||
products: Product[] = []; |
|||
currentCategory: number = 1; |
|||
previousCategory: number = 1; |
|||
searchMode: boolean = false; |
|||
|
|||
thePageNumber: number = 1; |
|||
thePageSize: number = 10; |
|||
theTotalElements: number = 0; |
|||
|
|||
|
|||
constructor( |
|||
private productService: ProductServiceService, |
|||
private route: ActivatedRoute, |
|||
//private cartService: CartService
|
|||
) { } |
|||
|
|||
ngOnInit() { |
|||
this.route.paramMap.subscribe(() => { |
|||
this.listProducts(); |
|||
}); |
|||
} |
|||
|
|||
|
|||
listProducts() { |
|||
this.searchMode = this.route.snapshot.paramMap.has("keyword"); |
|||
|
|||
if (this.searchMode) { |
|||
this.handleSearchProducts(); |
|||
} else { |
|||
this.handleListProducts(); |
|||
} |
|||
} |
|||
|
|||
|
|||
handleSearchProducts() { |
|||
const keyWord: string = this.route.snapshot.paramMap.get("keyword"); |
|||
|
|||
this.productService |
|||
.searchProductsList(keyWord) |
|||
.subscribe((data) => { |
|||
this.products = data; |
|||
}); |
|||
} |
|||
|
|||
|
|||
handleListProducts() { |
|||
const hasCaregoryId: boolean = this.route.snapshot.paramMap.has("id"); |
|||
|
|||
if (hasCaregoryId) { |
|||
this.currentCategory = +this.route.snapshot.paramMap.get("id"); |
|||
} else { |
|||
this.currentCategory = 1; |
|||
} |
|||
|
|||
if(this.previousCategory !== this.currentCategory){ |
|||
this.thePageNumber = 1; |
|||
} |
|||
this.previousCategory = this.currentCategory; |
|||
|
|||
this.productService |
|||
.getProductsListPaginate(this.thePageNumber - 1, this.thePageSize, this.currentCategory) |
|||
.subscribe(this.processResult()); |
|||
} |
|||
|
|||
processResult() { |
|||
return data =>{ |
|||
this.products = data._embedded.products; |
|||
this.thePageNumber = data.page.number + 1; |
|||
this.thePageSize = data.page.size; |
|||
this.theTotalElements = data.page.totalElements; |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,4 @@ |
|||
export class ProductCategory { |
|||
id: number; |
|||
categoryName: string; |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
export class Product { |
|||
id: number; |
|||
sku: string; |
|||
name: string; |
|||
description: string; |
|||
unitPrice: number; |
|||
imageUrl: string; |
|||
active: boolean; |
|||
unitsInStock: number; |
|||
dateCreated: Date; |
|||
lastUpdated: Date; |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
import { TestBed } from '@angular/core/testing'; |
|||
|
|||
import { ProductServiceService } from './product-service.service'; |
|||
|
|||
describe('ProductServiceService', () => { |
|||
let service: ProductServiceService; |
|||
|
|||
beforeEach(() => { |
|||
TestBed.configureTestingModule({}); |
|||
service = TestBed.inject(ProductServiceService); |
|||
}); |
|||
|
|||
it('should be created', () => { |
|||
expect(service).toBeTruthy(); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,68 @@ |
|||
import { Injectable } from '@angular/core'; |
|||
import { HttpClient } from '@angular/common/http'; |
|||
import { Observable } from 'rxjs'; |
|||
import { map } from 'rxjs/operators'; |
|||
import {Product} from './../models/product'; |
|||
import {ProductCategory} from './../models/product-category'; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root' |
|||
}) |
|||
export class ProductServiceService { |
|||
|
|||
private baseUrl: string = 'http://localhost:9090/api/products'; |
|||
private categoryUrl: string = 'http://localhost:9090/api/product-category'; |
|||
|
|||
constructor(private http: HttpClient) { } |
|||
|
|||
getProductsListPaginate(thePage: number, thePageSize: number, theCategoryId: number): Observable<GetResponseProduct> |
|||
{ |
|||
const searchUrl = `${this.baseUrl}/search/findByCategoryId?id=${theCategoryId}`+`&page=${thePage}&size=${thePageSize}`; |
|||
return this.http.get<GetResponseProduct>(searchUrl); |
|||
} |
|||
|
|||
getProductsList(theCategoryId: number): Observable<Product[]>{ |
|||
const searchUrl = `${this.baseUrl}/search/findByCategoryId?id=${theCategoryId}`; |
|||
return this.getProducts(searchUrl); |
|||
} |
|||
|
|||
searchProductsList(value: string): Observable<Product[]> { |
|||
const searchUrl = `${this.baseUrl}/search/findByNameContaining?name=${value}`; |
|||
return this.getProducts(searchUrl); |
|||
} |
|||
|
|||
private getProducts(searchUrl: string): Observable<Product[]> { |
|||
return this.http.get<GetResponseProduct>(searchUrl).pipe( |
|||
map(response => response._embedded.products) |
|||
); |
|||
} |
|||
|
|||
getProductCategories(): Observable<ProductCategory[]> { |
|||
return this.http.get<GetResponseCategory>(this.categoryUrl).pipe( |
|||
map(response=> response._embedded.productCategory) |
|||
) |
|||
} |
|||
|
|||
getProduct(theProductId: number): Observable<Product> { |
|||
const productUrl = `${this.baseUrl}/${theProductId}`; |
|||
return this.http.get<Product>(productUrl); |
|||
} |
|||
} |
|||
|
|||
interface GetResponseProduct{ |
|||
_embedded : { |
|||
products: Product[]; |
|||
}, |
|||
page: { |
|||
size: number, |
|||
totalElements: number, |
|||
totalPages: number, |
|||
number: number |
|||
} |
|||
} |
|||
|
|||
interface GetResponseCategory{ |
|||
_embedded : { |
|||
productCategory: ProductCategory[]; |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue