Completed Cache

This commit is contained in:
Charles Showalter 2022-05-31 17:15:00 -07:00
parent f6735a38fe
commit d875c033d9
19 changed files with 153 additions and 77 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -1,26 +1,26 @@
[
{
"Id": 1,
"Name": "Angular"
"Name": "ABS"
},
{
"Id": 2,
"Name": "NetCore"
"Name": "Cyberpower"
},
{
"Id": 3,
"Name": "VS Code"
"Name": "Skytech"
},
{
"Id": 4,
"Name": "React"
"Name": "Velztorm"
},
{
"Id": 5,
"Name": "Typescript"
"Name": "Bose"
},
{
"Id": 6,
"Name": "Redis"
"Name": "Beats"
}
]

View File

@ -1,51 +1,51 @@
[
{
"Name": "Angular Speedster Board 2000",
"Name": "ABS Gladiator Gaming PC",
"Description": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.",
"Price": 200,
"PictureUrl": "images/products/sb-ang1.png",
"Price": 1749,
"PictureUrl": "images/products/ABS-Gladiator-Gaming-PC-1749.jpg",
"ProductTypeId": 1,
"ProductBrandId": 1
},
{
"Name": "Green Angular Board 3000",
"Name": "CyberpowerPC Gaming Desktop Gamer Master",
"Description": "Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus.",
"Price": 150,
"PictureUrl": "images/products/sb-ang2.png",
"Price": 1699,
"PictureUrl": "images/products/CyberpowerPC-Gaming-Desktop-Gamer-Master-1699.jpg",
"ProductTypeId": 1,
"ProductBrandId": 1
"ProductBrandId": 2
},
{
"Name": "Core Board Speed Rush 3",
"Name": "Skytech Archangel 3.0 Gaming Computer PC Desktop",
"Description": "Suspendisse dui purus, scelerisque at, vulputate vitae, pretium mattis, nunc. Mauris eget neque at sem venenatis eleifend. Ut nonummy.",
"Price": 180,
"PictureUrl": "images/products/sb-core1.png",
"Price": 1199,
"PictureUrl": "images/products/Skytech-Archangel-3.0-Gaming-Computer-PC-Desktop-1199.jpg",
"ProductTypeId": 1,
"ProductBrandId": 2
"ProductBrandId": 3
},
{
"Name": "Net Core Super Board",
"Name": "Velztorm Nix Custom Built Gaming Desktop PC",
"Description": "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci.",
"Price": 300,
"PictureUrl": "images/products/sb-core2.png",
"ProductTypeId": 1,
"ProductBrandId": 2
},
{
"Name": "React Board Super Whizzy Fast",
"Description": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.",
"Price": 250,
"PictureUrl": "images/products/sb-react1.png",
"Price": 1449,
"PictureUrl": "images/products/Velztorm-Nix-Custom-Built-Gaming-Desktop-PC-1449.jpg",
"ProductTypeId": 1,
"ProductBrandId": 4
},
{
"Name": "Typescript Entry Board",
"Description": "Aenean nec lorem. In porttitor. Donec laoreet nonummy augue.",
"Price": 120,
"PictureUrl": "images/products/sb-ts1.png",
"Name": "ABS Legend Gaming PC - Intel i9 12900K",
"Description": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna.",
"Price": 4149,
"PictureUrl": "images/products/ABS-Legend-Gaming-PC-Intel-i9-12900K.jpg",
"ProductTypeId": 1,
"ProductBrandId": 5
"ProductBrandId": 1
},
{
"Name": "Skytech Chronos Gaming PC Desktop",
"Description": "Aenean nec lorem. In porttitor. Donec laoreet nonummy augue.",
"Price": 1599,
"PictureUrl": "images/products/Skytech-Chronos-Gaming-PC-Desktop.jpg",
"ProductTypeId": 1,
"ProductBrandId": 3
},
{
"Name": "Core Blue Hat",

View File

@ -1,18 +1,18 @@
[
{
"Id": 1,
"Name": "Boards"
"Name": "Computers"
},
{
"Id": 2,
"Name": "Hats"
"Name": "Headphones"
},
{
"Id": 3,
"Name": "Boots"
"Name": "Gadgets"
},
{
"Id": 4,
"Name": "Gloves"
"Name": "Accessories"
}
]

View File

@ -1,3 +1,3 @@
# SkiNet
# SkyNet
Built upon ASP.NET, Angular, Bootstrap, and Stripe for Credit Card Processing!

View File

@ -8,7 +8,7 @@ import { AccountService } from './account/account.service';
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
title = 'SkiNet';
title = 'SkyNet';
constructor(private basketService: BasketService, private accountService: AccountService) {}

View File

@ -2,6 +2,7 @@
[boundaryLinks]="true"
[totalItems]="totalCount"
(pageChanged)="onPagerChange($event)"
[ngModel]="pageNumber"
[itemsPerPage]="pageSize"
previousText="‹"
nextText="›"

View File

@ -8,6 +8,7 @@ import { Component, EventEmitter, Input, Output, OnInit } from '@angular/core';
export class PagerComponent implements OnInit {
@Input() totalCount: number;
@Input() pageSize: number;
@Input() pageNumber: number;
@Output() pageChanged = new EventEmitter<number>();
constructor() { }

View File

@ -1,8 +1,15 @@
import { IProduct } from "./product"
export interface IPagination {
pageIndex: number
pageSize: number
count: number
data: IProduct[]
}
pageIndex: number;
pageSize: number;
count: number;
data: IProduct[];
}
export class Pagination implements IPagination {
pageIndex: number;
pageSize: number;
count: number;
data: IProduct[] = [];
}

View File

@ -29,6 +29,7 @@ import { RouterModule } from '@angular/router';
CarouselModule.forRoot(),
BsDropdownModule.forRoot(),
ReactiveFormsModule,
FormsModule,
CdkStepperModule,
RouterModule
],
@ -40,6 +41,7 @@ import { RouterModule } from '@angular/router';
OrderTotalsComponent,
FormsModule,
ReactiveFormsModule,
FormsModule,
BsDropdownModule,
TextInputsComponent,
CdkStepperModule,

View File

@ -5,6 +5,7 @@
<h5 class="text-warning ml-3">Sort</h5>
<select class="form-select mb-3" style="width: 100%;" (change)="onSortSelected($event.target.value)">
<option *ngFor="let sort of sortOptions"
[selected]="shopParams.sort === sort.value"
[value]="sort.value"
>
{{sort.name}}
@ -57,6 +58,7 @@
<app-pager
[pageSize]="shopParams.pageSize"
[totalCount]="totalCount"
[pageNumber]="shopParams.pageNumber"
(pageChanged)="onPageChange($event)"
></app-pager>
</div>

View File

@ -15,7 +15,7 @@ export class ShopComponent implements OnInit {
products: IProduct[];
brands: IBrand[];
productType: IType[];
shopParams = new ShopParams();
shopParams: ShopParams;
totalCount: number;
sortOptions = [
{name: 'Name', value: 'name'},
@ -23,21 +23,21 @@ export class ShopComponent implements OnInit {
{name: 'Price: High to Low', value: 'priceDesc'}
];
constructor(private shopService: ShopService) { }
constructor(private shopService: ShopService) {
this.shopParams = this.shopService.getShopParams();
}
ngOnInit(): void {
this.getProducts();
this.getProducts(true);
this.getBrands();
this.getTypes();
}
getProducts(){
this.shopService.getProducts(this.shopParams).subscribe(
getProducts(useCache = false){
this.shopService.getProducts(useCache).subscribe(
{
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); },
@ -67,38 +67,49 @@ export class ShopComponent implements OnInit {
}
onBrandSelected(brandId: number){
this.shopParams.brandId = brandId;
this.shopParams.pageNumber = 1;
const params = this.shopService.getShopParams();
params.brandId = brandId;
params.pageNumber = 1;
this.shopService.setShopParams(params);
this.getProducts();
}
onTypeSelected(typeId: number){
this.shopParams.typeId = typeId;
this.shopParams.pageNumber = 1;
const params = this.shopService.getShopParams();
params.typeId = typeId;
params.pageNumber = 1;
this.shopService.setShopParams(params);
this.getProducts();
}
onSortSelected(sort: string){
this.shopParams.sort = sort;
const params = this.shopService.getShopParams();
params.sort = sort;
this.shopService.setShopParams(params);
this.getProducts();
}
onPageChange(e: any){
if (this.shopParams.pageNumber !== e){
this.shopParams.pageNumber = e;
this.getProducts();
const params = this.shopService.getShopParams();
if (params.pageNumber !== e){
params.pageNumber = e;
this.shopService.setShopParams(params);
this.getProducts(true);
}
}
onSearch(){
this.shopParams.search = this.searchTerm.nativeElement.value;
this.shopParams.pageNumber = 1;
const params = this.shopService.getShopParams()
params.search = this.searchTerm.nativeElement.value;
params.pageNumber = 1;
this.shopService.setShopParams(params);
this.getProducts();
}
OnReset(){
this.searchTerm.nativeElement.value = '';
this.shopParams = new ShopParams();
this.shopService.setShopParams(this.shopParams);
this.getProducts();
}

View File

@ -1,56 +1,108 @@
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 { IPagination, Pagination } from '../shared/models/pagination';
import { IType } from '../shared/models/producttype';
import { map } from 'rxjs/operators'
import { ShopParams } from '../shared/models/shopparams';
import { IProduct } from '../shared/models/product';
import { of } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ShopService {
baseURL = 'https://localhost:5001/api/'
baseURL = 'https://localhost:5001/api/';
products: IProduct[] = [];
brands: IBrand[] = [];
types: IType[] = [];
pagination = new Pagination();
shopParams = new ShopParams();
productCache = new Map();
constructor(private http: HttpClient) { }
getProducts(shopParams: ShopParams){
getProducts(useCache: boolean){
if (useCache === false){
this.productCache = new Map();
}
if(this.productCache.size > 0 && useCache === true){
if(this.productCache.has(Object.values(this.shopParams).join('-'))) {
this.pagination.data = this.productCache.get(Object.values(this.shopParams).join('-'));
return of(this.pagination);
}
}
let params = new HttpParams();
if (shopParams.brandId !== 0){
params = params.append('brandId', shopParams.brandId.toString());
if (this.shopParams.brandId !== 0){
params = params.append('brandId', this.shopParams.brandId.toString());
}
if(shopParams.typeId !== 0){
params = params.append('typeId', shopParams.typeId.toString());
if(this.shopParams.typeId !== 0){
params = params.append('typeId', this.shopParams.typeId.toString());
}
if (shopParams.search){
params = params.append('search', shopParams.search);
if (this.shopParams.search){
params = params.append('search', this.shopParams.search);
}
params = params.append('sort', shopParams.sort);
params = params.append('pageIndex', shopParams.pageNumber.toString());
params = params.append('pageIndex', shopParams.pageSize.toString());
params = params.append('sort', this.shopParams.sort);
params = params.append('pageIndex', this.shopParams.pageNumber.toString());
params = params.append('pageIndex', this.shopParams.pageSize.toString());
return this.http.get<IPagination>(this.baseURL + 'products', {observe: 'response', params})
.pipe(
map(response => {
return response.body;
this.productCache.set(Object.values(this.shopParams).join('-'), response.body.data);
this.pagination = response.body;
return this.pagination;
})
);
}
setShopParams(params: ShopParams){
this.shopParams = params;
}
getShopParams(){
return this.shopParams;
}
getProduct(id: number){
let product: IProduct;
this.productCache.forEach((products: IProduct[]) => {
product = products.find(p => p.id === id);
})
if(product){
return of(product);
}
return this.http.get<IProduct>(this.baseURL + 'products/' + id);
}
getBrands(){
return this.http.get<IBrand[]>(this.baseURL + 'products/brands');
if(this.brands.length > 0){
return of(this.brands);
}
return this.http.get<IBrand[]>(this.baseURL + 'products/brands').pipe(
map(response => {
this.brands = response;
return response;
})
);
}
getTypes(){
return this.http.get<IType[]>(this.baseURL + 'products/types');
if(this.types.length > 0){
return of(this.types);
}
return this.http.get<IType[]>(this.baseURL + 'products/types').pipe(
map(response => {
this.types = response;
return response;
})
);
}
}

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>SkiNet</title>
<title>SkyNet</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">