10 changed files with 276 additions and 1 deletions
Unified 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