Change Theme, Animations, and Loading Spinners
This commit is contained in:
parent
3f0a50d2bd
commit
f3ef7e326e
@ -30,7 +30,9 @@
|
|||||||
"styles": [
|
"styles": [
|
||||||
"./node_modules/font-awesome/css/font-awesome.css",
|
"./node_modules/font-awesome/css/font-awesome.css",
|
||||||
"./node_modules/ngx-toastr/toastr.css",
|
"./node_modules/ngx-toastr/toastr.css",
|
||||||
"src/styles.scss"
|
"src/styles.scss",
|
||||||
|
"./node_modules/ngx-spinner/animations/ball-clip-rotate-multiple.css",
|
||||||
|
"./node_modules/bootswatch/dist/cyborg/bootstrap.min.css"
|
||||||
],
|
],
|
||||||
"scripts": []
|
"scripts": []
|
||||||
},
|
},
|
||||||
|
32
client/package-lock.json
generated
32
client/package-lock.json
generated
@ -17,8 +17,10 @@
|
|||||||
"@angular/platform-browser-dynamic": "~13.3.0",
|
"@angular/platform-browser-dynamic": "~13.3.0",
|
||||||
"@angular/router": "~13.3.0",
|
"@angular/router": "~13.3.0",
|
||||||
"bootstrap": "^5.1.3",
|
"bootstrap": "^5.1.3",
|
||||||
|
"bootswatch": "^5.1.3",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"ngx-bootstrap": "^8.0.0",
|
"ngx-bootstrap": "^8.0.0",
|
||||||
|
"ngx-spinner": "^13.1.1",
|
||||||
"ngx-toastr": "^14.3.0",
|
"ngx-toastr": "^14.3.0",
|
||||||
"rxjs": "~7.5.0",
|
"rxjs": "~7.5.0",
|
||||||
"tslib": "^2.3.0",
|
"tslib": "^2.3.0",
|
||||||
@ -3511,6 +3513,11 @@
|
|||||||
"@popperjs/core": "^2.10.2"
|
"@popperjs/core": "^2.10.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bootswatch": {
|
||||||
|
"version": "5.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/bootswatch/-/bootswatch-5.1.3.tgz",
|
||||||
|
"integrity": "sha512-NmZFN6rOCoXWQ/PkzmD8FFWDe24kocX9OXWHNVaLxVVnpqpAzEbMFsf8bAfKwVtpNXibasZCzv09B5fLieAh2g=="
|
||||||
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
@ -7976,6 +7983,18 @@
|
|||||||
"rxjs": "^6.5.3 || ^7.4.0"
|
"rxjs": "^6.5.3 || ^7.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ngx-spinner": {
|
||||||
|
"version": "13.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ngx-spinner/-/ngx-spinner-13.1.1.tgz",
|
||||||
|
"integrity": "sha512-6aJz4KxIsBrlQckJxcM3CEvMcYbZoSDnQZPu0F/ZYAYunbBOTb9iydw0Gjczg9moum1VURWjX5dTVKmFo85c2Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^13.0.0",
|
||||||
|
"@angular/core": "^13.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ngx-toastr": {
|
"node_modules/ngx-toastr": {
|
||||||
"version": "14.3.0",
|
"version": "14.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-14.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-14.3.0.tgz",
|
||||||
@ -14317,6 +14336,11 @@
|
|||||||
"integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==",
|
"integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==",
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
|
"bootswatch": {
|
||||||
|
"version": "5.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/bootswatch/-/bootswatch-5.1.3.tgz",
|
||||||
|
"integrity": "sha512-NmZFN6rOCoXWQ/PkzmD8FFWDe24kocX9OXWHNVaLxVVnpqpAzEbMFsf8bAfKwVtpNXibasZCzv09B5fLieAh2g=="
|
||||||
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
@ -17564,6 +17588,14 @@
|
|||||||
"tslib": "^2.0.0"
|
"tslib": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ngx-spinner": {
|
||||||
|
"version": "13.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ngx-spinner/-/ngx-spinner-13.1.1.tgz",
|
||||||
|
"integrity": "sha512-6aJz4KxIsBrlQckJxcM3CEvMcYbZoSDnQZPu0F/ZYAYunbBOTb9iydw0Gjczg9moum1VURWjX5dTVKmFo85c2Q==",
|
||||||
|
"requires": {
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ngx-toastr": {
|
"ngx-toastr": {
|
||||||
"version": "14.3.0",
|
"version": "14.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-14.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-14.3.0.tgz",
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
"@angular/platform-browser-dynamic": "~13.3.0",
|
"@angular/platform-browser-dynamic": "~13.3.0",
|
||||||
"@angular/router": "~13.3.0",
|
"@angular/router": "~13.3.0",
|
||||||
"bootstrap": "^5.1.3",
|
"bootstrap": "^5.1.3",
|
||||||
|
"bootswatch": "^5.1.3",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"ngx-bootstrap": "^8.0.0",
|
"ngx-bootstrap": "^8.0.0",
|
||||||
|
"ngx-spinner": "^13.1.1",
|
||||||
"ngx-toastr": "^14.3.0",
|
"ngx-toastr": "^14.3.0",
|
||||||
"rxjs": "~7.5.0",
|
"rxjs": "~7.5.0",
|
||||||
"tslib": "^2.3.0",
|
"tslib": "^2.3.0",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
<ngx-spinner>
|
||||||
|
<h3>Loading...</h3>
|
||||||
|
</ngx-spinner>
|
||||||
<app-nav-bar></app-nav-bar>
|
<app-nav-bar></app-nav-bar>
|
||||||
<app-section-header></app-section-header>
|
<app-section-header></app-section-header>
|
||||||
<div class="container">
|
<router-outlet></router-outlet>
|
||||||
<router-outlet></router-outlet>
|
|
||||||
</div>
|
|
||||||
|
@ -9,6 +9,8 @@ import { CoreModule } from './core/core.module';
|
|||||||
import { ShopModule } from './shop/shop.module';
|
import { ShopModule } from './shop/shop.module';
|
||||||
import { HomeModule } from './home/home.module';
|
import { HomeModule } from './home/home.module';
|
||||||
import { ErrorInterceptor } from './core/interceptors/error.interceptor';
|
import { ErrorInterceptor } from './core/interceptors/error.interceptor';
|
||||||
|
import { NgxSpinnerModule } from 'ngx-spinner';
|
||||||
|
import { LoadingInterceptor } from './core/interceptors/loading.interceptor';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -20,10 +22,12 @@ import { ErrorInterceptor } from './core/interceptors/error.interceptor';
|
|||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
CoreModule,
|
CoreModule,
|
||||||
HomeModule
|
HomeModule,
|
||||||
|
NgxSpinnerModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true}
|
{provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true},
|
||||||
|
{provide: HTTP_INTERCEPTORS, useClass: LoadingInterceptor, multi: true}
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
HttpEvent,
|
HttpEvent,
|
||||||
HttpInterceptor
|
HttpInterceptor
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
import { catchError, Observable, throwError } from 'rxjs';
|
import { catchError, delay, Observable, throwError } from 'rxjs';
|
||||||
import { NavigationExtras, Router } from '@angular/router';
|
import { NavigationExtras, Router } from '@angular/router';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
import { ToastrService } from 'ngx-toastr';
|
||||||
|
|
||||||
|
20
client/src/app/core/interceptors/loading.interceptor.ts
Normal file
20
client/src/app/core/interceptors/loading.interceptor.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http";
|
||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { delay, finalize, Observable } from "rxjs";
|
||||||
|
import { BusyService } from "../services/busy.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class LoadingInterceptor implements HttpInterceptor {
|
||||||
|
constructor(private busyService: BusyService) {}
|
||||||
|
|
||||||
|
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
|
this.busyService.busy();
|
||||||
|
return next.handle(req).pipe(
|
||||||
|
delay(1000),
|
||||||
|
finalize(()=> {
|
||||||
|
this.busyService.idle();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
<div class="d-flex flex-column flex-md-row align-items-center justify-content-between p-3 px-md-4 mb-3 bg-white border-bottom shadown-sm fixed-top">
|
<div class="d-flex flex-column flex-md-row align-items-center justify-content-between p-3 px-md-4 mb-3 border-bottom border-dark fixed-top" style="background-color: #0d0d0e;">
|
||||||
<img class="logo" src="/assets/images/logo.png" style="max-height: 70px;" alt="logo" routerLink="/">
|
<img class="logo" src="/assets/images/logo.png" style="max-height: 70px;" alt="logo" routerLink="/">
|
||||||
<nav class="me-3 my-md-0 mr-md-3 text-uppercase" style="font-size: larger;">
|
<nav class="me-3 my-md-0 mr-md-3 text-uppercase" style="font-size: larger;">
|
||||||
<a class="me-3 py-2" [routerLink]="['/']" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">Home</a>
|
<a class="me-3 py-2" [routerLink]="['/']" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">Home</a>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<ng-container *ngIf="(breadcrumb$ | async) as breadcrumbs">
|
<ng-container *ngIf="(breadcrumb$ | async) as breadcrumbs">
|
||||||
<section *ngIf="breadcrumbs.length > 0 && breadcrumbs[breadcrumbs.length-1].label !== 'Home'" class="py-5" style="margin-top: 105px; background-color:#f5f5f5;">
|
<section *ngIf="breadcrumbs.length > 0 && breadcrumbs[breadcrumbs.length-1].label !== 'Home'" class="py-5" style="margin-top: 105px;">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row d-flex align-item-center">
|
<div class="row d-flex align-item-center">
|
||||||
<div class="col-9">
|
<div class="col-9">
|
||||||
<h1>{{breadcrumbs.length > 0 && breadcrumbs[breadcrumbs.length-1].label | titlecase}}</h1>
|
<h1 class="text-dark">{{breadcrumbs.length > 0 && breadcrumbs[breadcrumbs.length-1].label | titlecase}}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<xng-breadcrumb></xng-breadcrumb>
|
<xng-breadcrumb></xng-breadcrumb>
|
||||||
|
30
client/src/app/core/services/busy.service.ts
Normal file
30
client/src/app/core/services/busy.service.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { NgxSpinnerService } from 'ngx-spinner';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class BusyService {
|
||||||
|
busyRequestCount = 0;
|
||||||
|
|
||||||
|
constructor(private spinnerService: NgxSpinnerService) { }
|
||||||
|
|
||||||
|
busy(){
|
||||||
|
this.busyRequestCount++;
|
||||||
|
this.spinnerService.show(undefined, {
|
||||||
|
type: 'ball-clip-rotate-multiple',
|
||||||
|
size: 'large',
|
||||||
|
bdColor: 'rgba(0, 0, 0, 0.8)',
|
||||||
|
color: '#dddddd'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
idle(){
|
||||||
|
this.busyRequestCount--;
|
||||||
|
if (this.busyRequestCount <= 0){
|
||||||
|
this.busyRequestCount = 0;
|
||||||
|
this.spinnerService.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1 +1,16 @@
|
|||||||
<p>home works!</p>
|
<carousel>
|
||||||
|
<slide>
|
||||||
|
<img src="assets/images/hero1.jpg" alt="first slide" style="display: block; width: 100%">
|
||||||
|
</slide>
|
||||||
|
<slide>
|
||||||
|
<img src="assets/images/hero2.jpg" alt="first slide" style="display: block; width: 100%">
|
||||||
|
</slide>
|
||||||
|
<slide>
|
||||||
|
<img src="assets/images/hero3.jpg" alt="first slide" style="display: block; width: 100%">
|
||||||
|
</slide>
|
||||||
|
</carousel>
|
||||||
|
<section class="featured">
|
||||||
|
<div class="d-flex justify-content-center pt-5">
|
||||||
|
<h1>Welcome to our Shop!</h1>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
.featured {
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
object-fit: cover;
|
||||||
|
height: 600px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { HomeComponent } from './home.component';
|
import { HomeComponent } from './home.component';
|
||||||
|
import { SharedModule } from '../shared/shared.module';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -9,7 +10,8 @@ import { HomeComponent } from './home.component';
|
|||||||
HomeComponent
|
HomeComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule
|
CommonModule,
|
||||||
|
SharedModule
|
||||||
],
|
],
|
||||||
exports: [HomeComponent]
|
exports: [HomeComponent]
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
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 { PaginationModule } from 'ngx-bootstrap/pagination';
|
||||||
|
import { CarouselModule } from 'ngx-bootstrap/carousel';
|
||||||
import { PagingHeaderComponent } from './components/paging-header/paging-header.component';
|
import { PagingHeaderComponent } from './components/paging-header/paging-header.component';
|
||||||
import { PagerComponent } from './components/pager/pager.component';
|
import { PagerComponent } from './components/pager/pager.component';
|
||||||
|
|
||||||
@ -13,12 +14,14 @@ import { PagerComponent } from './components/pager/pager.component';
|
|||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
PaginationModule.forRoot()
|
PaginationModule.forRoot(),
|
||||||
|
CarouselModule.forRoot()
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
PaginationModule,
|
PaginationModule,
|
||||||
PagingHeaderComponent,
|
PagingHeaderComponent,
|
||||||
PagerComponent
|
PagerComponent,
|
||||||
|
CarouselModule
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class SharedModule { }
|
export class SharedModule { }
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
<div class="row" *ngIf="product">
|
<div class="container mt-5">
|
||||||
<div class="col-6">
|
<div class="row" *ngIf="product">
|
||||||
<img src="{{product.pictureUrl}}" alt="{{product.name}}" class="img-fluid w-100">
|
<div class="col-6">
|
||||||
</div>
|
<img src="{{product.pictureUrl}}" alt="{{product.name}}" class="img-fluid w-100">
|
||||||
<div class="col-6">
|
|
||||||
<h3>{{product.name}}</h3>
|
|
||||||
<p>{{product.price | currency}}</p>
|
|
||||||
<div class="d-flex justify-content-start align-items-center">
|
|
||||||
<i class="fa fa-minus-circle text-warning me-2" style="cursor: pointer; font-size: 2em"></i>
|
|
||||||
<span class="font-weight-bold" style="font-size: 1.5em;">2</span>
|
|
||||||
<i class="fa fa-plus-circle text-warning mx-2" style="cursor: pointer; font-size: 2em"></i>
|
|
||||||
<button class="btn btn-outline-secondary btn-lg ms-4">Ad to Cart</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-6">
|
||||||
<div class="row mt-5">
|
<h3>{{product.name}}</h3>
|
||||||
<div class="col-12 ms-3">
|
<p style="font-size: 2em;">{{product.price | currency}}</p>
|
||||||
<h4>Description</h4>
|
<div class="d-flex justify-content-start align-items-center">
|
||||||
<p>{{product.description}}</p>
|
<i class="fa fa-minus-circle text-warning me-2" style="cursor: pointer; font-size: 2em"></i>
|
||||||
|
<span class="font-weight-bold" style="font-size: 1.5em;">2</span>
|
||||||
|
<i class="fa fa-plus-circle text-warning mx-2" style="cursor: pointer; font-size: 2em"></i>
|
||||||
|
<button class="btn btn-outline-secondary btn-lg ms-4">Ad to Cart</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="col-12 ms-3">
|
||||||
|
<h4>Description</h4>
|
||||||
|
<p>{{product.description}}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -12,7 +12,9 @@ import { ShopService } from '../shop.service';
|
|||||||
export class ProductDetailsComponent implements OnInit {
|
export class ProductDetailsComponent implements OnInit {
|
||||||
product: IProduct;
|
product: IProduct;
|
||||||
|
|
||||||
constructor(private shopService: ShopService, private activatedRoute: ActivatedRoute, private bcService: BreadcrumbService) { }
|
constructor(private shopService: ShopService, private activatedRoute: ActivatedRoute, private bcService: BreadcrumbService) {
|
||||||
|
this.bcService.set('@productDetails', ' ');
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loadProduct();
|
this.loadProduct();
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
<div class="card h-100 shadow-sm">
|
<div class="card h-100 shadow-sm">
|
||||||
<img src="{{product.pictureUrl}}" alt="{{product.name}}" class="img-fluid bg-light">
|
<div class="image position-relative" style="cursor: pointer;">
|
||||||
<div class="d-flex align-items-center justify-content-center hover-overlay">
|
<img src="{{product.pictureUrl}}" alt="{{product.name}}" class="img-fluid bg-light">
|
||||||
<button type="button" class="btn btn-sm btn-primary fa fa-shopping-cart me-2"></button>
|
<div class="d-flex align-items-center justify-content-center hover-overlay">
|
||||||
<button routerLink="/shop/{{product.id}}" type="button" class="btn btn-sm btn-primary">View</button>
|
<button type="button" class="btn btn-sm btn-primary fa fa-shopping-cart me-2"></button>
|
||||||
</div>
|
<button routerLink="/shop/{{product.id}}" type="button" class="btn btn-sm btn-primary">View</button>
|
||||||
<div class="card-body d-flex flex-column">
|
</div>
|
||||||
<a routerLink="/shop/{{product.id}}">
|
</div>
|
||||||
<h6 class="text-uppercase">{{product.name}}</h6>
|
<div class="card-body d-flex flex-column">
|
||||||
</a>
|
<a routerLink="/shop/{{product.id}}">
|
||||||
<span class="mb-2">{{product.price | currency}}</span>
|
<h6 class="text-uppercase">{{product.name}}</h6>
|
||||||
</div>
|
</a>
|
||||||
|
<span class="mb-2">{{product.price | currency}}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,3 +2,36 @@
|
|||||||
width: 30%;
|
width: 30%;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image :hover {
|
||||||
|
opacity: 1;
|
||||||
|
& button {
|
||||||
|
transform: none;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover-overlay {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background-color: rgba($color: rgb(0, 0, 0), $alpha: 0.5);
|
||||||
|
opacity: 0;
|
||||||
|
transition: all 0.5s;
|
||||||
|
|
||||||
|
& button {
|
||||||
|
z-index: 1000;
|
||||||
|
transition: all 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
& button:first-of-type {
|
||||||
|
transform: translateX(-20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
& button:last-of-type {
|
||||||
|
transform: translateX(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,32 +1,34 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mt-5">
|
<div class="row mt-5">
|
||||||
<section class="col-3">
|
<section class="col-3">
|
||||||
<h5 class="text-warning ml-3">Sort</h5>
|
<ng-container *ngIf="productType && brands">
|
||||||
<select class="form-select mb-3" style="width: 100%;" (change)="onSortSelected($event.target.value)">
|
<h5 class="text-warning ml-3">Sort</h5>
|
||||||
<option *ngFor="let sort of sortOptions"
|
<select class="form-select mb-3" style="width: 100%;" (change)="onSortSelected($event.target.value)">
|
||||||
[value]="sort.value"
|
<option *ngFor="let sort of sortOptions"
|
||||||
>
|
[value]="sort.value"
|
||||||
{{sort.name}}
|
>
|
||||||
</option>
|
{{sort.name}}
|
||||||
</select>
|
</option>
|
||||||
<h5 class="text-warning ml-3">Brands</h5>
|
</select>
|
||||||
<ul class="list-group my-3">
|
<h5 class="text-warning ml-3">Brands</h5>
|
||||||
<li class="list-group-item"
|
<ul class="list-group my-3">
|
||||||
*ngFor="let brand of brands"
|
<li class="list-group-item" style="cursor: pointer;"
|
||||||
[class.active]="brand.id === this.shopParams.brandId"
|
*ngFor="let brand of brands"
|
||||||
[value]="brand.id"
|
[class.active]="brand.id === this.shopParams.brandId"
|
||||||
(click)="onBrandSelected(brand.id)"
|
[value]="brand.id"
|
||||||
>{{brand.name}}</li>
|
(click)="onBrandSelected(brand.id)"
|
||||||
</ul>
|
>{{brand.name}}</li>
|
||||||
<h5 class="text-warning ml-3">Type</h5>
|
</ul>
|
||||||
<ul class="list-group my-3">
|
<h5 class="text-warning ml-3">Type</h5>
|
||||||
<li class="list-group-item"
|
<ul class="list-group my-3">
|
||||||
*ngFor="let type of productType"
|
<li class="list-group-item" style="cursor: pointer;"
|
||||||
[class.active]="type.id === this.shopParams.typeId"
|
*ngFor="let type of productType"
|
||||||
[value]="type.id"
|
[class.active]="type.id === this.shopParams.typeId"
|
||||||
(click)="onTypeSelected(type.id)"
|
[value]="type.id"
|
||||||
>{{type.name}}</li>
|
(click)="onTypeSelected(type.id)"
|
||||||
</ul>
|
>{{type.name}}</li>
|
||||||
|
</ul>
|
||||||
|
</ng-container>
|
||||||
</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">
|
||||||
@ -35,7 +37,7 @@
|
|||||||
[pageSize]="this.shopParams.pageSize"
|
[pageSize]="this.shopParams.pageSize"
|
||||||
[pageNumber]="this.shopParams.pageNumber"
|
[pageNumber]="this.shopParams.pageNumber"
|
||||||
></app-paging-header>
|
></app-paging-header>
|
||||||
<div class="row g-2 align-items-center">
|
<div class="row g-2 align-items-center" *ngIf="products">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<input (keyup.enter)="onSearch()" style="width:300px" #search placeholder="Search" type="text" class="form-control">
|
<input (keyup.enter)="onSearch()" style="width:300px" #search placeholder="Search" type="text" class="form-control">
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,7 +11,7 @@ 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;
|
@ViewChild('search', {static: false}) searchTerm: ElementRef;
|
||||||
products: IProduct[];
|
products: IProduct[];
|
||||||
brands: IBrand[];
|
brands: IBrand[];
|
||||||
productType: IType[];
|
productType: IType[];
|
||||||
|
@ -17,6 +17,11 @@ label.xng-breadcrumb-trail {
|
|||||||
color: orange;
|
color: orange;
|
||||||
}
|
}
|
||||||
|
|
||||||
xng-breadcrumb-separator {
|
.xng-breadcrumb-separator {
|
||||||
padding: 0 0;
|
padding: 0 0;
|
||||||
|
color: #343a40;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xng-breadcrumb-link, a.xng-breadcrumb-link {
|
||||||
|
color: #343a40;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user