mirror of
https://github.com/Mueller-Patrick/Betterzon.git
synced 2024-12-22 19:55:12 +00:00
BETTERZON-42: Functionality and design of various components for the search product UC
This commit is contained in:
parent
e83b2d7511
commit
acdc9a4e92
|
@ -13,6 +13,8 @@ import {NgApexchartsModule} from 'ng-apexcharts';
|
|||
import { ProductSearchPageComponent } from './pages/product-search-page/product-search-page.component';
|
||||
import { HeaderComponent } from './components/header/header.component';
|
||||
import { NewestPricesListComponent } from './components/newest-prices-list/newest-prices-list.component';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import { PageNotFoundPageComponent } from './pages/page-not-found-page/page-not-found-page.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
@ -24,13 +26,15 @@ import { NewestPricesListComponent } from './components/newest-prices-list/newes
|
|||
ProductDetailsComponent,
|
||||
ProductSearchPageComponent,
|
||||
HeaderComponent,
|
||||
NewestPricesListComponent
|
||||
NewestPricesListComponent,
|
||||
PageNotFoundPageComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRouting,
|
||||
HttpClientModule,
|
||||
NgApexchartsModule
|
||||
NgApexchartsModule,
|
||||
FormsModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
|
|
|
@ -6,11 +6,13 @@ import {ProductListComponent} from './components/product-list/product-list.compo
|
|||
import {LandingpageComponent} from './pages/landingpage/landingpage.component';
|
||||
import {ProductDetailPageComponent} from './pages/product-detail-page/product-detail-page.component';
|
||||
import {ProductSearchPageComponent} from './pages/product-search-page/product-search-page.component';
|
||||
import {PageNotFoundPageComponent} from './pages/page-not-found-page/page-not-found-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{path: '', component: LandingpageComponent},
|
||||
{path: 'search', component: ProductSearchPageComponent},
|
||||
{path: 'product/:id', component: ProductDetailPageComponent}
|
||||
{path: 'product/:id', component: ProductDetailPageComponent},
|
||||
{path: '**', component: PageNotFoundPageComponent}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
.header {
|
||||
width: auto;
|
||||
background-color: dimgrey;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: .25em;
|
||||
}
|
||||
|
||||
#headerContent {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.logo {
|
||||
position: relative;
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
.searchBox {
|
||||
position: relative;
|
||||
margin: auto;
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
.searchBox input {
|
||||
width: 100%;
|
||||
padding: .25em;
|
||||
display: inline-block;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.profileIcon {
|
||||
position: relative;
|
||||
margin: auto;
|
||||
margin-left: 10%;
|
||||
}
|
||||
|
||||
.icon-3d {
|
||||
padding: 10px;
|
||||
color: #fff;
|
||||
}
|
|
@ -1 +1,14 @@
|
|||
<p>header works!</p>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
<header class="header">
|
||||
<div id="headerContent" class='wrap'>
|
||||
<div class="logo">
|
||||
<img src="assets/images/Betterzon.svg" alt="Betterzon Logo" width="50px" (click)="clickedLogo()">
|
||||
</div>
|
||||
<div class="searchBox">
|
||||
<input type="text" [(ngModel)]="searchInput" placeholder="Search" (keyup.enter)="startedSearch()">
|
||||
</div>
|
||||
<div class="profileIcon">
|
||||
Profile
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
@ -1,15 +1,33 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {Router} from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-header',
|
||||
templateUrl: './header.component.html',
|
||||
styleUrls: ['./header.component.css']
|
||||
selector: 'app-header',
|
||||
templateUrl: './header.component.html',
|
||||
styleUrls: ['./header.component.css']
|
||||
})
|
||||
export class HeaderComponent implements OnInit {
|
||||
searchInput: string;
|
||||
|
||||
constructor() { }
|
||||
constructor(
|
||||
private router: Router
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
clickedLogo(): void {
|
||||
this.router.navigate([('/')]);
|
||||
}
|
||||
|
||||
startedSearch(): void {
|
||||
this.redirectTo('/search', {queryParams: {q: this.searchInput}});
|
||||
}
|
||||
|
||||
redirectTo(uri: string, queryParams: object): void {
|
||||
this.router.navigateByUrl('/', {skipLocationChange: true}).then(() =>
|
||||
this.router.navigate([uri], queryParams));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
.priceList {
|
||||
max-width: 50%;
|
||||
margin: auto;
|
||||
margin: auto;
|
||||
align-content: center;
|
||||
text-align: center;
|
||||
}
|
|
@ -1 +1,3 @@
|
|||
<p>newest-prices-list works!</p>
|
||||
<div class="priceList">
|
||||
PriceList
|
||||
</div>
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
margin: auto;
|
||||
margin-bottom: .5em;
|
||||
display: grid;
|
||||
grid-template-columns: 20% 50% 30%;
|
||||
grid-template-columns: 20% 25% 25% 30%;
|
||||
grid-template-areas:
|
||||
'image title priceChart'
|
||||
'image description priceChart'
|
||||
'image priceAlarm bestPrice';
|
||||
'image title title priceChart'
|
||||
'image description description priceChart'
|
||||
'image priceAlarm bestPrice blank';
|
||||
}
|
||||
|
||||
/* Image div */
|
||||
|
@ -54,6 +54,7 @@
|
|||
grid-area: priceAlarm;
|
||||
border-style: solid;
|
||||
border-color: dimgrey;
|
||||
border-radius: 5px;
|
||||
padding: .25em;
|
||||
margin: auto;
|
||||
}
|
||||
|
@ -63,6 +64,7 @@
|
|||
grid-area: bestPrice;
|
||||
border-style: solid;
|
||||
border-color: dimgrey;
|
||||
border-radius: 5px;
|
||||
padding: .25em;
|
||||
margin: auto;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
<meta charset="UTF-8">
|
||||
<div class="productItem">
|
||||
<div class="productImageContainer">
|
||||
<img class="productImage" src="https://www.mueller-patrick.tech/betterzon/images/{{product.image_guid}}.jpg"/>
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<meta charset="UTF-8">
|
||||
<div *ngIf="products.length==0">
|
||||
No Products found!
|
||||
</div>
|
||||
<div class="productItem" *ngFor="let product of products" (click)="clickedProduct(product)">
|
||||
<div class="productImageContainer" *ngIf="showProductPicture===true">
|
||||
<img class="productImage" src="https://www.mueller-patrick.tech/betterzon/images/{{product.image_guid}}.jpg"/>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {ApiService} from '../../services/api.service';
|
||||
import {Product} from '../../models/product';
|
||||
import {Router} from '@angular/router';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-list',
|
||||
|
@ -9,33 +9,57 @@ import {Router} from '@angular/router';
|
|||
styleUrls: ['./product-list.component.css']
|
||||
})
|
||||
export class ProductListComponent implements OnInit {
|
||||
products: Product[];
|
||||
products: Product[] = [];
|
||||
@Input() numberOfProducts: number;
|
||||
@Input() showProductPicture: boolean;
|
||||
type: string;
|
||||
@Input() searchQuery: string;
|
||||
@Input() type: string;
|
||||
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
private router: Router
|
||||
private router: Router,
|
||||
private route: ActivatedRoute
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getProducts();
|
||||
this.loadParams();
|
||||
}
|
||||
|
||||
loadParams(): void {
|
||||
if (!this.numberOfProducts) {
|
||||
this.numberOfProducts = 10;
|
||||
}
|
||||
if (!this.showProductPicture) {
|
||||
this.showProductPicture = false;
|
||||
}
|
||||
this.type = 'PLP';
|
||||
if (!this.searchQuery) {
|
||||
this.searchQuery = '';
|
||||
}
|
||||
if (!this.type) {
|
||||
this.type = '';
|
||||
}
|
||||
|
||||
switch (this.type) {
|
||||
case 'search': {
|
||||
this.getSearchedProducts();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
this.getProducts();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getProducts(): void {
|
||||
this.apiService.getProducts().subscribe(products => this.products = products);
|
||||
}
|
||||
|
||||
getSearchedProducts(): void {
|
||||
this.apiService.getProductsByQuery(this.searchQuery).subscribe(products => this.products = products);
|
||||
}
|
||||
|
||||
clickedProduct(product: Product): void {
|
||||
this.router.navigate([('/product/' + product.product_id)]);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#mainComponents {
|
||||
margin: 5em;
|
||||
margin-top: .5em;
|
||||
margin-bottom: .5em;
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
<app-header></app-header>
|
||||
<app-product-list numberOfProducts="20" [showProductPicture]="true"></app-product-list>
|
||||
<div id="mainComponents">
|
||||
<app-product-list numberOfProducts="20" [showProductPicture]="true"></app-product-list>
|
||||
</div>
|
||||
<app-footer></app-footer>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<h1>404</h1>
|
||||
<p>Page not found!</p>
|
|
@ -0,0 +1,25 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PageNotFoundPageComponent } from './page-not-found-page.component';
|
||||
|
||||
describe('PageNotFoundPageComponent', () => {
|
||||
let component: PageNotFoundPageComponent;
|
||||
let fixture: ComponentFixture<PageNotFoundPageComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PageNotFoundPageComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PageNotFoundPageComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,15 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-page-not-found-page',
|
||||
templateUrl: './page-not-found-page.component.html',
|
||||
styleUrls: ['./page-not-found-page.component.css']
|
||||
})
|
||||
export class PageNotFoundPageComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#mainComponents {
|
||||
padding: 5em;
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
<app-header></app-header>
|
||||
<app-product-details [productId]="productId"></app-product-details>
|
||||
<div id="mainComponents">
|
||||
<app-product-details [productId]="productId"></app-product-details>
|
||||
<app-newest-prices-list></app-newest-prices-list>
|
||||
</div>
|
||||
<app-footer></app-footer>
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#mainComponents {
|
||||
margin: 5em;
|
||||
margin-top: .5em;
|
||||
margin-bottom: .5em;
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
<app-header></app-header>
|
||||
<app-product-list numberOfProducts="20" [showProductPicture]="true"></app-product-list>
|
||||
<div id="mainComponents">
|
||||
<app-product-list numberOfProducts="20" [showProductPicture]="true" searchQuery="{{searchTerm}}"
|
||||
type="search"></app-product-list>
|
||||
</div>
|
||||
<app-footer></app-footer>
|
||||
|
|
|
@ -19,17 +19,24 @@ export class ApiService {
|
|||
getProduct(id): Observable<Product> {
|
||||
try {
|
||||
const prod = this.http.get<Product>((this.apiUrl + '/products/' + id));
|
||||
console.log(prod);
|
||||
return prod;
|
||||
} catch (exception) {
|
||||
process.stderr.write(`ERROR received from ${this.apiUrl}: ${exception}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
getProductsByQuery(query): Observable<Product[]> {
|
||||
try {
|
||||
const prods = this.http.get<Product[]>((this.apiUrl + '/products/search/' + query));
|
||||
return prods;
|
||||
} catch (exception) {
|
||||
process.stderr.write(`ERROR received from ${this.apiUrl}: ${exception}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
getProducts(): Observable<Product[]> {
|
||||
try {
|
||||
const prods = this.http.get<Product[]>((this.apiUrl + '/products'));
|
||||
console.log(prods);
|
||||
return prods;
|
||||
} catch (exception) {
|
||||
process.stderr.write(`ERROR received from ${this.apiUrl}: ${exception}\n`);
|
||||
|
|
1
Frontend/src/assets/images/Betterzon.svg
Normal file
1
Frontend/src/assets/images/Betterzon.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 13 KiB |
|
@ -1 +1,5 @@
|
|||
/* You can add global styles to this file, and also import other style files */
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user