Correction demander pour le brief + ajout des infos rating + bouton reset

This commit is contained in:
Julian Tomczyk 2022-03-01 11:55:28 +01:00
parent f6601fcd9c
commit 1f1c069bdd
51 changed files with 6740 additions and 6523 deletions

View File

@ -4,13 +4,15 @@ This project was generated with [Angular CLI](https://github.com/angular/angular
## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change
any of the source files.
Run `npm run api` for the api server. Reach to `http://localhost:3000/`
Run `npm run api` for the api server. Reach to `http://localhost:3000/`
## Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
Run `ng generate component component-name` to generate a new component. You can also
use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
@ -22,8 +24,10 @@ Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a
package that implements end-to-end testing capabilities.
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
To get more help on the Angular CLI use `ng help` or go check out
the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.

12100
db.json

File diff suppressed because it is too large Load Diff

View File

@ -28,8 +28,8 @@ module.exports = function (config) {
dir: require('path').join(__dirname, './coverage/la-belle-plante'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' }
{type: 'html'},
{type: 'text-summary'}
]
},
reporters: ['progress', 'kjhtml'],

2
package-lock.json generated
View File

@ -7185,7 +7185,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
@ -7485,7 +7484,6 @@
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
"node_modules/json-server": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/json-server/-/json-server-0.17.0.tgz",

View File

@ -1,26 +1,27 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CardPlanteComponent } from './components/card-plante/card-plante.component';
import { PageAccueilComponent } from './pages/page-accueil/page-accueil.component';
import { PageDetailsComponent } from './pages/page-details/page-details.component';
import { PageNotFoundComponent } from './pages/page-not-found/page-not-found.component';
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {PageAccueilComponent} from './pages/page-accueil/page-accueil.component';
import {PageDetailsComponent} from './pages/page-details/page-details.component';
import {PageNotFoundComponent} from './pages/page-not-found/page-not-found.component';
const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{path: '', redirectTo: 'home', pathMatch: 'full'},
{
path: 'home', component: PageAccueilComponent },
{ path: 'details/:productId', component: PageDetailsComponent},
{path : 'account',
loadChildren : () => import('./modules/account/account.module')
.then(m => m.AccountModule)
path: 'home', component: PageAccueilComponent
},
{ path: '**', component: PageNotFoundComponent }
{path: 'details/:productId', component: PageDetailsComponent},
{
path: 'account',
loadChildren: () => import('./modules/account/account.module')
.then(m => m.AccountModule)
},
{path: '**', component: PageNotFoundComponent}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
export class AppRoutingModule {
}

View File

@ -1,6 +1,6 @@
import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
import {TestBed} from '@angular/core/testing';
import {RouterTestingModule} from '@angular/router/testing';
import {AppComponent} from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {

View File

@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import {Component} from '@angular/core';
@Component({
selector: 'app-root',

View File

@ -1,17 +1,17 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NavBarComponent } from './components/nav-bar/nav-bar.component';
import { PageAccueilComponent } from './pages/page-accueil/page-accueil.component';
import { PageDetailsComponent } from './pages/page-details/page-details.component';
import { PageNotFoundComponent } from './pages/page-not-found/page-not-found.component';
import { FilterSideBarComponent } from './components/filter-side-bar/filter-side-bar.component';
import { CardPlanteComponent } from './components/card-plante/card-plante.component';
import { HttpClientModule } from '@angular/common/http';
import { IconComponent } from './components/icon/icon.component';
import { AvisBarComponent } from './components/avis-bar/avis-bar.component';
import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component';
import {NavBarComponent} from './components/nav-bar/nav-bar.component';
import {PageAccueilComponent} from './pages/page-accueil/page-accueil.component';
import {PageDetailsComponent} from './pages/page-details/page-details.component';
import {PageNotFoundComponent} from './pages/page-not-found/page-not-found.component';
import {FilterSideBarComponent} from './components/filter-side-bar/filter-side-bar.component';
import {CardPlanteComponent} from './components/card-plante/card-plante.component';
import {HttpClientModule} from '@angular/common/http';
import {IconComponent} from './components/icon/icon.component';
import {AvisBarComponent} from './components/avis-bar/avis-bar.component';
@NgModule({
declarations: [
@ -35,4 +35,5 @@ import { AvisBarComponent } from './components/avis-bar/avis-bar.component';
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
export class AppModule {
}

View File

@ -1,9 +1,16 @@
<div (mouseleave)="onMouseLeave()">
<app-icon *ngFor="let star of starStates; let starIndex = index"
[iconName]="star.stateHoverUser ? 'star-fill' : 'star'"
[iconSize]="1.2"
[iconColor]="'#ffbf00'"
(mouseover)="onMouseOver(starIndex)"
(click)="onClickStar(starIndex)"
></app-icon>
<div (mouseover)="isOver = true" *ngIf="isOver === false">
<app-icon *ngFor="let star of starStates; let starIndex = index"
[iconName]="star.stateRatingProduct ? 'star-fill' : 'star'"
[iconSize]="1.2"
[iconColor]="'#ffbf00'"
></app-icon>
</div>
<div (mouseleave)="onMouseLeave()" *ngIf="isOver">
<app-icon *ngFor="let star of starStates; let starIndex = index"
[iconName]="star.stateHoverUser ? 'star-fill' : 'star'"
[iconSize]="1.2"
[iconColor]="'#ffbf00'"
(mouseover)="onMouseOver(starIndex)"
(click)="onClickStar(starIndex)"
></app-icon>
</div>

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { AvisBarComponent } from './avis-bar.component';
import {AvisBarComponent} from './avis-bar.component';
describe('AvisBarComponent', () => {
let component: AvisBarComponent;
@ -8,9 +8,9 @@ describe('AvisBarComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AvisBarComponent ]
declarations: [AvisBarComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
@Component({
selector: 'app-avis-bar',
@ -6,30 +6,42 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core';
styleUrls: ['./avis-bar.component.scss']
})
export class AvisBarComponent implements OnInit {
starStates: {stateSelectedUser : boolean, stateHoverUser : boolean}[];
starStates: { stateSelectedUser: boolean, stateHoverUser: boolean, stateRatingProduct: boolean }[];
@Output() stateNumber = new EventEmitter
starStateNumber: number = 0;
@Input() ratingIndex: number = 0;
isOver: boolean;
constructor() {
this.starStates = [];
this.isOver = false;
for (let index = 0; index < 5; index++) {
this.starStates.push(
{
stateSelectedUser : false,
stateHoverUser : false
stateSelectedUser: false,
stateHoverUser: false,
stateRatingProduct: false
}
);
}
}
}
ngOnInit(): void {
for (let i = 0; i < 5; i++) {
if (i < this.ratingIndex) {
this.starStates[i].stateRatingProduct = true;
} else {
this.starStates[i].stateRatingProduct = false;
}
}
}
onMouseOver(index: number) {
console.log("star over", index);
for (let i = 0; i < this.starStates.length ; i++) {
if(i <= index) {
this.isOver = true;
for (let i = 0; i < this.starStates.length; i++) {
if (i <= index) {
this.starStates[i].stateHoverUser = true;
} else {
this.starStates[i].stateHoverUser = false;
@ -39,12 +51,14 @@ export class AvisBarComponent implements OnInit {
onMouseLeave() {
// this.starState = ['star', 'star', 'star', 'star', 'star'];
this.isOver = false;
const tempTab = [];
for (let index = 0; index < this.starStates.length; index++) {
tempTab.push(
{
stateSelectedUser : this.starStates[index].stateSelectedUser,
stateHoverUser : this.starStates[index].stateSelectedUser
stateSelectedUser: this.starStates[index].stateSelectedUser,
stateHoverUser: this.starStates[index].stateSelectedUser,
stateRatingProduct: this.starStates[index].stateRatingProduct
}
);
}
@ -53,16 +67,17 @@ export class AvisBarComponent implements OnInit {
onClickStar(starIndex: number) {
this.starStateNumber = 0;
for (let i = 0; i < this.starStates.length ; i++) {
if(i <= starIndex) {
for (let i = 0; i < this.starStates.length; i++) {
if (i <= starIndex) {
this.starStates[i].stateSelectedUser = true;
this.starStates[i].stateRatingProduct = true;
this.starStateNumber++;
} else {
this.starStates[i].stateSelectedUser = false;
this.starStates[i].stateRatingProduct = false;
}
}
//console.log(`Rating : ${this.starStateNumber}`);
this.stateNumber.emit(this.starStateNumber);
}
}

View File

@ -1,20 +1,21 @@
<div class="plant card mb-4" style="width: 14rem;">
<app-icon class="like"
<app-icon class="like"
[iconName]="'heart'"
[iconColor]="'#e35d6a'"
(click)="onClickLike()"></app-icon>
<img src="{{plant.product_url_picture}}" class="card-img-top" alt="Image de {{ plant.product_name }}" (click) = "onGetId(plant.product_id)">
<div class="card-body">
<h6 class="card-title" (click) = "onGetId(plant.product_id)">{{ plant.product_name }}</h6>
<div class="card-content">
<app-avis-bar></app-avis-bar>
</div>
<div class="d-flex flex-row align-items-end justify-content-between">
<div class="card-content">
{{ plant.product_unitprice_ati }} €
</div>
<a href="#" class="btn btn-success">Pour moi !</a>
</div>
<img src="{{plant.product_url_picture}}" class="card-img-top" alt="Image de {{ plant.product_name }}"
(click)="onGetId(plant.product_id)">
<div class="card-body">
<h6 class="card-title" (click)="onGetId(plant.product_id)">{{ plant.product_name }}</h6>
<div class="card-content">
<app-avis-bar [ratingIndex]="plant.product_rating"></app-avis-bar>
</div>
<div class="d-flex flex-row align-items-end justify-content-between">
<div class="card-content">
{{ plant.product_unitprice_ati }} €
</div>
<a href="#" class="btn btn-success">Pour moi !</a>
</div>
</div>
</div>

View File

@ -1,14 +1,15 @@
.plant {
min-height: 22rem;
.card-body {
display: flex;
flex-direction: column;
justify-content: space-between;
}
min-height: 22rem;
.card-body {
display: flex;
flex-direction: column;
justify-content: space-between;
}
}
.like {
position: absolute;
right: 0.7rem;
top: 0.5rem;
}
position: absolute;
right: 0.7rem;
top: 0.5rem;
}

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { CardPlanteComponent } from './card-plante.component';
import {CardPlanteComponent} from './card-plante.component';
describe('CardPlanteComponent', () => {
let component: CardPlanteComponent;
@ -8,9 +8,9 @@ describe('CardPlanteComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ CardPlanteComponent ]
declarations: [CardPlanteComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,5 +1,5 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Router } from '@angular/router';
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {Router} from '@angular/router';
@Component({
@ -12,17 +12,20 @@ export class CardPlanteComponent implements OnInit {
@Output() clickLike = new EventEmitter();
@Output() clickCardId = new EventEmitter();
constructor(private router : Router) {}
constructor(private router: Router) {
}
ngOnInit(): void {
}
onClickLike() {
console.log('click');
this.clickLike.emit();
}
onGetId(id : string){
onGetId(id: string) {
this.clickCardId.emit(id);
this.router.navigateByUrl('/details/'+ id);
this.router.navigateByUrl('/details/' + id);
}
}

View File

@ -1,44 +1,52 @@
<div class="custom-side-bar flex-shrink-0 bg-white border-end">
<div class="p-3">
<span class="fs-5 fw-semibold">Filtres</span>
<span class="fs-5 fw-semibold">Filtres</span>
</div>
<ul class="list-unstyled ps-0 border-top">
<div class="p-3">
<p class="mb-1 fs-5 fw-semibold">Catégories</p>
<div *ngFor="let category of listCategories; let indexCat = index" class="form-check">
<div class="p-3">
<p class="mb-1 fs-5 fw-semibold">Catégories</p>
<div *ngFor="let category of listCategories; let indexCat = index" class="form-check">
<input class="form-check-input" type="checkbox" value="testcategory" id="checkBoxCategory{{indexCat}}" (click)="onCheckCategory(category,$event)">
<input class="form-check-input" type="checkbox" value="testcategory" id="checkBoxCategory{{indexCat}}"
(click)="onCheckCategory(category,$event)">
<label class="form-check-label" for="checkBoxCategory{{indexCat}}">
{{ category }}
</label>
</div>
<div *ngIf="listCategories.length == 0 ">
Aucune catégorie disponible
</div>
</div>
</ul>
<ul class="list-unstyled ps-0 border-top">
<div class="p-3">
<p class="mb-1 fs-5 fw-semibold">Prix</p>
<div class="d-flex justify-content-center">
<input #minNum id="numberMin" type="number" placeholder="min" min=0 value="" class="me-2" style="width: 45%;">
<input #maxNum id="numberMax" type="number" placeholder="max" value="" class="me-2" style="width: 45%;">
</div>
<label class="form-check-label" for="checkBoxCategory{{indexCat}}">
{{ category }}
</label>
</div>
<div *ngIf="listCategories.length == 0 ">
Aucune catégorie disponible
</div>
</div>
</ul>
<ul class="list-unstyled ps-0 border-top">
<div class="p-3">
<p class="mb-1 fs-5 fw-semibold">Prix</p>
<div class="d-flex justify-content-center">
<input #minNum id="numberMin" type="number" placeholder="min" min=0 value="" class="me-2" style="width: 45%;">
<input #maxNum id="numberMax" type="number" placeholder="max" value="" class="me-2" style="width: 45%;">
</div>
<div class="d-flex justify-content-center">
<button class="btn btn-success m-3" (click)="onSendValues(minNum, maxNum)">Valider</button>
</div>
</div>
</ul>
<ul class="list-unstyled ps-0 border-top">
<div class="p-3">
<p class="mb-1 fs-5 fw-semibold">Avis</p>
<div class="flex-column justify-content-start">
<app-avis-bar (stateNumber)="onStateNumberChange($event)"></app-avis-bar>
<button class="btn btn-success me-2" (click)="onSendRating()">Valider</button>
</div>
</div>
</ul>
<div class="d-flex justify-content-center">
<button class="btn btn-success m-3" (click)="onSendValues(minNum, maxNum)">Valider</button>
</div>
</div>
</ul>
<ul class="list-unstyled ps-0 border-top">
<div class="p-3">
<p class="mb-1 fs-5 fw-semibold">Avis</p>
<div class="flex-column justify-content-start">
<app-avis-bar (stateNumber)="onStateNumberChange($event)"></app-avis-bar>
<button class="btn btn-success me-2" (click)="onSendRating()">Valider</button>
</div>
</div>
</ul>
<ul class="list-unstyled ps-0 border-top">
<div class="p-3">
<div class="flex-column justify-content-start">
<button class="btn btn-success me-2" (click)="onReset()">Réinitialiser</button>
</div>
</div>
</ul>
</div>

View File

@ -1,5 +1,5 @@
.custom-side-bar {
min-height: calc(100vh - 54px);
width: 280px;
height: 100%;
}
min-height: calc(100vh - 54px);
width: 280px;
height: 100%;
}

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { FilterSideBarComponent } from './filter-side-bar.component';
import {FilterSideBarComponent} from './filter-side-bar.component';
describe('FilterSideBarComponent', () => {
let component: FilterSideBarComponent;
@ -8,9 +8,9 @@ describe('FilterSideBarComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ FilterSideBarComponent ]
declarations: [FilterSideBarComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
@Component({
selector: 'app-filter-side-bar',
@ -10,10 +10,10 @@ export class FilterSideBarComponent implements OnInit {
@Output() checkCategory = new EventEmitter();
@Output() stateNumber = new EventEmitter();
@Output() rangeNumber = new EventEmitter();
@Output() reset = new EventEmitter();
filterStateNumber: number = 0;
public selectedCategory: string[];
constructor() {
this.listCategories = [];
this.selectedCategory = [];
@ -45,13 +45,23 @@ export class FilterSideBarComponent implements OnInit {
this.filterStateNumber = stateNumber;
}
onSendRating():void {
onSendRating(): void {
this.stateNumber.emit(this.filterStateNumber);
}
onSendValues(minNum: any, maxNum: any): void {
if (minNum.value == '') {
minNum.value = 0;
}
if (maxNum.value == '') {
maxNum.value = 1000;
}
let rangeArray: number[] = [parseFloat(minNum.value), parseFloat(maxNum.value)];
console.log(typeof(rangeArray[0]));
this.rangeNumber.emit(rangeArray);
}
onReset(): void {
this.reset.emit();
}
}

View File

@ -1,2 +1,2 @@
<i class="bi-{{iconName}}"
[ngStyle]="{'font-size.rem': iconSize, 'color': iconColor}"></i>
<i class="bi-{{iconName}}"
[ngStyle]="{'font-size.rem': iconSize, 'color': iconColor}"></i>

View File

@ -1,3 +1,3 @@
i {
cursor: pointer;
}
cursor: pointer;
}

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { IconComponent } from './icon.component';
import {IconComponent} from './icon.component';
describe('IconComponent', () => {
let component: IconComponent;
@ -8,9 +8,9 @@ describe('IconComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ IconComponent ]
declarations: [IconComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import {Component, Input, OnInit} from '@angular/core';
@Component({
selector: 'app-icon',
@ -9,7 +9,9 @@ export class IconComponent implements OnInit {
@Input() iconName!: string;
@Input() iconSize!: number;
@Input() iconColor!: string;
constructor() { }
constructor() {
}
ngOnInit(): void {
}

View File

@ -1,27 +1,27 @@
<nav class="navbar sticky-top navbar-expand-lg navbar-light bg-light shadow ">
<div class="container-fluid">
<a class="navbar-brand" href="#">🪴 La Belle Plante</a>
<button class="navbar-toggler"
<div class="container-fluid">
<a class="navbar-brand" href="#">🪴 La Belle Plante</a>
<button class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarNavAltMarkup"
aria-controls="navbarNavAltMarkup"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav">
<a routerLink="home" routerLinkActive="active-custom" class="nav-link">Accueil</a>
<a routerLink="details" routerLinkActive="active-custom" class="nav-link">Details</a>
<a routerLink="account/signin" routerLinkActive="active-custom" class="nav-link">Se connecter</a>
<a class="nav-link">Panier</a>
<a class="nav-link disabled">Plus d'option bientôt</a>
<a class="nav-link disabled" *ngIf="likeCounter == 0"> Pas de plante likée</a>
<a class="nav-link disabled" *ngIf="likeCounter == 1">Plante likée : {{ likeCounter }}</a>
<a class="nav-link disabled" *ngIf="likeCounter > 1">Plantes likées : {{ likeCounter }}</a>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav">
<a routerLink="home" routerLinkActive="active-custom" class="nav-link">Accueil</a>
<a routerLink="details" routerLinkActive="active-custom" class="nav-link">Details</a>
<a routerLink="account/signin" routerLinkActive="active-custom" class="nav-link">Se connecter</a>
<a class="nav-link">Panier</a>
<a class="nav-link disabled">Plus d'option bientôt</a>
<a class="nav-link disabled" *ngIf="likeCounter == 0"> Pas de plante likée</a>
<a class="nav-link disabled" *ngIf="likeCounter == 1">Plante likée : {{ likeCounter }}</a>
<a class="nav-link disabled" *ngIf="likeCounter > 1">Plantes likées : {{ likeCounter }}</a>
</div>
</div>
</div>
</div>
</div>
</nav>

View File

@ -1,3 +1,3 @@
.active-custom {
color: green !important;
}
color: green !important;
}

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { NavBarComponent } from './nav-bar.component';
import {NavBarComponent} from './nav-bar.component';
describe('NavBarComponent', () => {
let component: NavBarComponent;
@ -8,9 +8,9 @@ describe('NavBarComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ NavBarComponent ]
declarations: [NavBarComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,6 +1,6 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { PlantouneService } from 'src/app/services/plantoune.service';
import {Component, OnDestroy, OnInit} from '@angular/core';
import {Subscription} from 'rxjs';
import {PlantouneService} from 'src/app/services/plantoune.service';
@Component({
selector: 'app-nav-bar',
@ -13,19 +13,19 @@ export class NavBarComponent implements OnInit, OnDestroy {
constructor(private plantouneService: PlantouneService) {
this.likeCounter = 0;
}
}
ngOnInit(): void {
this.subPlantLiked = this.plantouneService.plantLiked$.subscribe(
() => {
console.log('Get new event from Subject');
this.likeCounter ++;
this.likeCounter++;
}
)
}
ngOnDestroy(): void {
this.subPlantLiked.unsubscribe();
this.subPlantLiked.unsubscribe();
}
}

View File

@ -1,16 +1,16 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PageForgotPasswordComponent } from './pages/page-forgot-password/page-forgot-password.component';
import { PageResetPasswordComponent } from './pages/page-reset-password/page-reset-password.component';
import { PageSigninComponent } from './pages/page-signin/page-signin.component';
import { PageSignupComponent } from './pages/page-signup/page-signup.component';
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {PageForgotPasswordComponent} from './pages/page-forgot-password/page-forgot-password.component';
import {PageResetPasswordComponent} from './pages/page-reset-password/page-reset-password.component';
import {PageSigninComponent} from './pages/page-signin/page-signin.component';
import {PageSignupComponent} from './pages/page-signup/page-signup.component';
const routes: Routes = [
{path : '', redirectTo:'signin', pathMatch: 'full'},
{path : "signin", component : PageSigninComponent},
{path : "signup", component : PageSignupComponent},
{path : "forgot-password", component : PageForgotPasswordComponent},
{path : "reset-password", component : PageResetPasswordComponent}
{path: '', redirectTo: 'signin', pathMatch: 'full'},
{path: "signin", component: PageSigninComponent},
{path: "signup", component: PageSignupComponent},
{path: "forgot-password", component: PageForgotPasswordComponent},
{path: "reset-password", component: PageResetPasswordComponent}
];
@ -18,4 +18,5 @@ const routes: Routes = [
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AccountRoutingModule { }
export class AccountRoutingModule {
}

View File

@ -1,11 +1,11 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import { AccountRoutingModule } from './account-routing.module';
import { PageSignupComponent } from './pages/page-signup/page-signup.component';
import { PageSigninComponent } from './pages/page-signin/page-signin.component';
import { PageForgotPasswordComponent } from './pages/page-forgot-password/page-forgot-password.component';
import { PageResetPasswordComponent } from './pages/page-reset-password/page-reset-password.component';
import {AccountRoutingModule} from './account-routing.module';
import {PageSignupComponent} from './pages/page-signup/page-signup.component';
import {PageSigninComponent} from './pages/page-signin/page-signin.component';
import {PageForgotPasswordComponent} from './pages/page-forgot-password/page-forgot-password.component';
import {PageResetPasswordComponent} from './pages/page-reset-password/page-reset-password.component';
@NgModule({
@ -20,4 +20,5 @@ import { PageResetPasswordComponent } from './pages/page-reset-password/page-res
AccountRoutingModule
]
})
export class AccountModule { }
export class AccountModule {
}

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { PageForgotPasswordComponent } from './page-forgot-password.component';
import {PageForgotPasswordComponent} from './page-forgot-password.component';
describe('PageForgotPasswordComponent', () => {
let component: PageForgotPasswordComponent;
@ -8,9 +8,9 @@ describe('PageForgotPasswordComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PageForgotPasswordComponent ]
declarations: [PageForgotPasswordComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'app-page-forgot-password',
@ -7,7 +7,8 @@ import { Component, OnInit } from '@angular/core';
})
export class PageForgotPasswordComponent implements OnInit {
constructor() { }
constructor() {
}
ngOnInit(): void {
}

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { PageResetPasswordComponent } from './page-reset-password.component';
import {PageResetPasswordComponent} from './page-reset-password.component';
describe('PageResetPasswordComponent', () => {
let component: PageResetPasswordComponent;
@ -8,9 +8,9 @@ describe('PageResetPasswordComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PageResetPasswordComponent ]
declarations: [PageResetPasswordComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'app-page-reset-password',
@ -7,7 +7,8 @@ import { Component, OnInit } from '@angular/core';
})
export class PageResetPasswordComponent implements OnInit {
constructor() { }
constructor() {
}
ngOnInit(): void {
}

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { PageSigninComponent } from './page-signin.component';
import {PageSigninComponent} from './page-signin.component';
describe('PageSigninComponent', () => {
let component: PageSigninComponent;
@ -8,9 +8,9 @@ describe('PageSigninComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PageSigninComponent ]
declarations: [PageSigninComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'app-page-signin',
@ -7,7 +7,8 @@ import { Component, OnInit } from '@angular/core';
})
export class PageSigninComponent implements OnInit {
constructor() { }
constructor() {
}
ngOnInit(): void {
}

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { PageSignupComponent } from './page-signup.component';
import {PageSignupComponent} from './page-signup.component';
describe('PageSignupComponent', () => {
let component: PageSignupComponent;
@ -8,9 +8,9 @@ describe('PageSignupComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PageSignupComponent ]
declarations: [PageSignupComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'app-page-signup',
@ -7,7 +7,8 @@ import { Component, OnInit } from '@angular/core';
})
export class PageSignupComponent implements OnInit {
constructor() { }
constructor() {
}
ngOnInit(): void {
}

View File

@ -1,23 +1,25 @@
<div class="d-flex align-items-stretch">
<app-filter-side-bar [listCategories]="listCategoriesFilter" (stateNumber)="onRatingFilter($event)" (rangeNumber)="onPriceFilter($event)" (checkCategory)="onListCategory($event)"></app-filter-side-bar>
<app-filter-side-bar [listCategories]="listCategoriesFilter" (stateNumber)="onRatingFilter($event)"
(rangeNumber)="onPriceFilter($event)" (checkCategory)="onListCategory($event)"
(reset)="onResetFilter()"></app-filter-side-bar>
<div class="custom-main container p-3">
<input class="form-control"
type="text"
placeholder="Recherche ta belle plante"
aria-label="Input Recherche ta belle plante"
(input)="onRecherchePlante($event)">
<div class="py-3">
Trier par :
<button class="btn btn-outline-success btn-sm me-2" (click)="onPriceTri()">Prix</button>
<button class="btn btn-outline-success btn-sm me-2" (click)="onAlphaTri()">Ordre Alpha</button>
<button class="btn btn-outline-success btn-sm me-2" (click)="onRatingTri()">Avis</button>
</div>
<div class="row">
<div class="col" *ngFor="let product of listData">
<app-card-plante [plant]="product" (clickLike)="onEventLike()">
</app-card-plante>
</div>
</div>
<input class="form-control"
type="text"
placeholder="Recherche ta belle plante"
aria-label="Input Recherche ta belle plante"
(input)="onRecherchePlante($event)">
<div class="py-3">
Trier par :
<button class="btn btn-outline-success btn-sm me-2" (click)="onPriceTri()">Prix</button>
<button class="btn btn-outline-success btn-sm me-2" (click)="onAlphaTri()">Ordre Alpha</button>
<button class="btn btn-outline-success btn-sm me-2" (click)="onRatingTri()">Avis</button>
</div>
</div>
<div class="row">
<div class="col" *ngFor="let product of listData">
<app-card-plante [plant]="product" (clickLike)="onEventLike()">
</app-card-plante>
</div>
</div>
</div>
</div>

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { PageAccueilComponent } from './page-accueil.component';
import {PageAccueilComponent} from './page-accueil.component';
describe('PageAccueilComponent', () => {
let component: PageAccueilComponent;
@ -8,9 +8,9 @@ describe('PageAccueilComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PageAccueilComponent ]
declarations: [PageAccueilComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,9 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { PlantouneService } from 'src/app/services/plantoune.service';
import {Component, OnInit} from '@angular/core';
import {PlantouneService} from 'src/app/services/plantoune.service';
import * as _ from 'underscore';
import { contains, includes } from 'underscore';
@Component({
@ -13,19 +10,21 @@ import { contains, includes } from 'underscore';
})
export class PageAccueilComponent implements OnInit {
public listData: any[];
public listPricePlant : any[];
public clickCounter : any;
public listDataGlobal : any[];
public listPricePlant: any[];
public clickCounter: any;
public listDataGlobal: any[];
public listDataFilter: any[];
public listCategoriesFilter: string[];
public dataFilterCategory : any;
public category: string[];
public choix: string;
public rangeNumber: number[];
public stateNumber: number;
public isCategoryFilterActive: boolean;
public isPricingFilterActive: boolean;
public isRatingFilterActive: boolean;
public isSearchFilterActive: boolean;
constructor(private plantouneService: PlantouneService) {
this.listData = [];
@ -35,23 +34,27 @@ export class PageAccueilComponent implements OnInit {
this.clickCounter = 0;
this.listDataFilter = [];
this.category = [];
this.choix = '';
this.rangeNumber = [];
this.stateNumber = 0;
this.isCategoryFilterActive = false;
this.isPricingFilterActive = false;
this.isRatingFilterActive = false;
this.isSearchFilterActive = false;
this.clickCounter = 0;
}
}
/**
* equivalent de la ligne du dessus
*
* plantouneService;
*
* constructor(plantouneService: PlantouneService) {
* this.plantouneService = plantouneService; }
*/
/**
* equivalent de la ligne du dessus
*
* plantouneService;
*
* constructor(plantouneService: PlantouneService) {
* this.plantouneService = plantouneService; }
*/
ngOnInit(): void {
@ -61,7 +64,7 @@ export class PageAccueilComponent implements OnInit {
this.listDataGlobal = [...listPlant];
this.listDataFilter = [...this.listDataGlobal];
console.log(this.listDataGlobal);
/**
* Technique avec Underscore JS pour recupérer les catégories uniques de nos plantes
*/
@ -72,7 +75,6 @@ export class PageAccueilComponent implements OnInit {
// console.log(listUniqCategories);
/**
* Technique native JS pour recupérer les catégories uniques de nos plantes
*/
@ -84,7 +86,7 @@ export class PageAccueilComponent implements OnInit {
this.listData = [...listPlant];
this.listData.length = 9;
this.listDataGlobal = [...listPlant]
console.log(this.listData);
}
)
@ -94,137 +96,292 @@ export class PageAccueilComponent implements OnInit {
this.plantouneService.plantLiked$.next('');
}
onRecherchePlante(choix: any) {
// onRecherchePlante(choix: any) {
//
// this.clickCounter ++
// console.log(this.clickCounter)
// this.listData = [...this.listDataGlobal];
// if (this.clickCounter %2) {
// this.listData.sort((a, b) => parseFloat(a.product_price) - parseFloat(b.product_price));
// }else{
// this.listData.sort((a, b) => parseFloat(b.product_price) - parseFloat(a.product_price));
// }
// const search = choix.target.value
// if (search == '') {
// this.listData = [...this.listDataGlobal];
// }
// console.log(search);
// this.listData = this.listData.filter((plant) => {
// if(plant.product_name.toLowerCase().includes(search.toLowerCase())){
// return plant;
// }
// });
// //Equivaut à la ligne ci-dessous (version abrégée)
// //this.listData = this.listDataGlobal.filter((plant) => plant.product_name.toLowerCase().includes(search.toLowerCase()))
// console.log(this.listData);
// if (this.listData.length >= 9) {this.listData.length=9}
// }
this.clickCounter ++
console.log(this.clickCounter)
if (this.clickCounter %2) {
this.listData.sort((a, b) => parseFloat(a.product_price) - parseFloat(b.product_price));
}else{
this.listData.sort((a, b) => parseFloat(b.product_price) - parseFloat(a.product_price));
}
const search = choix.target.value
console.log(search);
this.listData = this.listDataGlobal.filter((plant) => {
if(plant.product_name.toLowerCase().includes(search.toLowerCase())){
return plant;
}
});
//Equivaut à la ligne ci-dessous (version abrégée)
//this.listData = this.listDataGlobal.filter((plant) => plant.product_name.toLowerCase().includes(search.toLowerCase()))
console.log(this.listData);
if (this.listData.length >= 9) {this.listData.length=9}
}
// onListCategory(categoryArray: string[]) {
// // this.listData=listData;
// //console.log(typeof(valueText));
//
// if (categoryArray.length == 0) {
// this.listData = [...this.listDataGlobal];
//
// } else if (categoryArray.length > 0) {
// let listProductsByCategory: string[] = [];
// this.listDataGlobal.forEach(product => {
//
// categoryArray.forEach(categorySelected => {
// if (product.product_breadcrumb_label == categorySelected) {
// listProductsByCategory.push(product);
// }
// });
// });
// this.listData = [...listProductsByCategory];
// }
//
// if (this.listData.length >= 9) {
// this.listData.length = 9;
// }
// }
onListCategory(categoryArray: string[]) {
// this.listData=listData;
//console.log(typeof(valueText));
if(categoryArray.length == 0) {
this.listData = [...this.listDataGlobal];
} else if(categoryArray.length > 0) {
let listProductsByCategory:string[] = [];
this.listDataGlobal.forEach(product => {
categoryArray.forEach(categorySelected => {
if (product.product_breadcrumb_label == categorySelected){
listProductsByCategory.push(product);
}
});
});
this.listData= [...listProductsByCategory];
}
if(this.listData.length>=9){
this.listData.length=9;
}
}
onRatingFilter(stateNumber: number): void {
this.stateNumber = stateNumber;
this.isRatingFilterActive = true;
this.onApplyFilters();
}
onPriceFilter(rangeNumber: number[]) {
this.rangeNumber = [...rangeNumber];
this.isPricingFilterActive = true;
this.onApplyFilters();
}
onApplyFilters(): void {
this.clickCounter = 0;
if(this.isPricingFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
if(parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0] && parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1]) {
listDataFinal.push(product);
}
});
this.listData = [...listDataFinal];
}
if(this.isRatingFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
if(product.product_rating >= this.stateNumber) {
listDataFinal.push(product);
}
});
this.listData = [...listDataFinal];
}
if(this.isPricingFilterActive && this.isRatingFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
if(parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0]
&& parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1]
&& product.product_rating >= this.stateNumber) {
listDataFinal.push(product);
}
});
this.listData = [...listDataFinal];
console.log(this.listData);
}
if(this.listData.length >= 9) this.listData.length = 9;
}
//Tri des prix des plantes par ordre croissant ou décroissant
onPriceTri() : void {
this.clickCounter ++
console.log(this.clickCounter)
if (this.clickCounter %2) {
this.listData.sort((a, b) => parseFloat(a.product_price) - parseFloat(b.product_price));
}else{
this.listData.sort((a, b) => parseFloat(b.product_price) - parseFloat(a.product_price));
}
}
//Tri des noms des plantes par ordre alphanumérique
onAlphaTri() : void {
this.clickCounter ++
if (this.clickCounter %2) {
this.listData.sort((a, b) => (a.product_name > b.product_name) ? 1 : -1)
}else{
this.listData.sort((a, b) => (b.product_name > a.product_name) ? 1 : -1)
}
}
//Tri des avis des plantes par ordre croissant ou décroissant
onRatingTri() : void{
this.clickCounter ++
if (this.clickCounter %2) {
this.listData.sort((a, b) => (a.product_rating > b.product_rating) ? 1 : -1)
}else{
this.listData.sort((a, b) => (b.product_rating > a.product_rating) ? 1 : -1)
}
}
if (categoryArray.length == 0) {
this.listData = [...this.listDataGlobal];
this.isCategoryFilterActive = false;
} else {
this.category = [...categoryArray];
this.isCategoryFilterActive = true;
}
this.onApplyFilters();
}
onRecherchePlante(choix: any) {
this.choix = choix.target.value;
this.isSearchFilterActive = true;
this.onApplyFilters();
}
onRatingFilter(stateNumber: number): void {
this.stateNumber = stateNumber;
this.isRatingFilterActive = true;
this.onApplyFilters();
}
onPriceFilter(rangeNumber: number[]) {
this.rangeNumber = [...rangeNumber];
this.isPricingFilterActive = true;
this.onApplyFilters();
}
onApplyFilters(): void {
this.clickCounter = 0;
if (this.isCategoryFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
this.category.forEach(categorySelected => {
if (product.product_breadcrumb_label == categorySelected) {
listDataFinal.push(product);
}
});
});
this.listData = [...listDataFinal];
}
if (this.isSearchFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
if (product.product_name.toLowerCase().includes(this.choix.toLowerCase())) {
listDataFinal.push(product);
}
});
this.listData = [...listDataFinal];
}
if (this.isPricingFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
if (parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0]
&& parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1]) {
listDataFinal.push(product);
}
});
this.listData = [...listDataFinal];
}
if (this.isRatingFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
if (product.product_rating >= this.stateNumber) {
listDataFinal.push(product);
}
});
this.listData = [...listDataFinal];
}
if (this.isSearchFilterActive && this.isCategoryFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
this.category.forEach(categorySelected => {
if (product.product_breadcrumb_label == categorySelected
&& product.product_name.toLowerCase().includes(this.choix.toLowerCase())) {
listDataFinal.push(product);
}
});
});
this.listData = [...listDataFinal];
}
if (this.isPricingFilterActive && this.isCategoryFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
this.category.forEach(categorySelected => {
if (product.product_breadcrumb_label == categorySelected
&& parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0]
&& parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1]) {
listDataFinal.push(product);
}
});
});
this.listData = [...listDataFinal];
}
if (this.isRatingFilterActive && this.isCategoryFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
this.category.forEach(categorySelected => {
if (product.product_breadcrumb_label == categorySelected
&& product.product_rating >= this.stateNumber) {
listDataFinal.push(product);
}
});
});
this.listData = [...listDataFinal];
}
if (this.isSearchFilterActive && this.isPricingFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
if (parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0]
&& parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1]
&& product.product_name.toLowerCase().includes(this.choix.toLowerCase())) {
listDataFinal.push(product);
}
});
this.listData = [...listDataFinal];
}
if (this.isSearchFilterActive && this.isRatingFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
if (product.product_rating >= this.stateNumber
&& product.product_name.toLowerCase().includes(this.choix.toLowerCase())) {
listDataFinal.push(product);
}
});
this.listData = [...listDataFinal];
}
if (this.isPricingFilterActive && this.isRatingFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
if (parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0]
&& parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1]
&& product.product_rating >= this.stateNumber) {
listDataFinal.push(product);
}
});
this.listData = [...listDataFinal];
}
if (this.isSearchFilterActive && this.isPricingFilterActive && this.isRatingFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
if (product.product_rating >= this.stateNumber && parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0]
&& parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1]
&& product.product_name.toLowerCase().includes(this.choix.toLowerCase())) {
listDataFinal.push(product);
}
});
this.listData = [...listDataFinal];
}
if (this.isCategoryFilterActive && this.isSearchFilterActive && this.isPricingFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
this.category.forEach(categorySelected => {
if (product.product_breadcrumb_label == categorySelected
&& parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0]
&& parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1]
&& product.product_name.toLowerCase().includes(this.choix.toLowerCase())) {
listDataFinal.push(product);
}
});
});
this.listData = [...listDataFinal];
}
if (this.isRatingFilterActive && this.isCategoryFilterActive && this.isSearchFilterActive && this.isPricingFilterActive) {
let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
this.category.forEach(categorySelected => {
if (product.product_breadcrumb_label == categorySelected
&& product.product_rating >= this.stateNumber
&& parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0]
&& parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1]
&& product.product_name.toLowerCase().includes(this.choix.toLowerCase())) {
listDataFinal.push(product);
}
});
});
this.listData = [...listDataFinal];
}
if (this.listData.length >= 9) this.listData.length = 9;
}
onResetFilter(): void {
window.location.reload();
}
//Tri des prix des plantes par ordre croissant ou décroissant
onPriceTri(): void {
this.clickCounter++
console.log(this.clickCounter)
if (this.clickCounter % 2) {
this.listData.sort((a, b) => parseFloat(a.product_price) - parseFloat(b.product_price));
} else {
this.listData.sort((a, b) => parseFloat(b.product_price) - parseFloat(a.product_price));
}
}
//Tri des noms des plantes par ordre alphanumérique
onAlphaTri(): void {
this.clickCounter++
if (this.clickCounter % 2) {
this.listData.sort((a, b) => (a.product_name > b.product_name) ? 1 : -1)
} else {
this.listData.sort((a, b) => (b.product_name > a.product_name) ? 1 : -1)
}
}
//Tri des avis des plantes par ordre croissant ou décroissant
onRatingTri(): void {
this.clickCounter++
if (this.clickCounter % 2) {
this.listData.sort((a, b) => (a.product_rating > b.product_rating) ? 1 : -1)
} else {
this.listData.sort((a, b) => (b.product_rating > a.product_rating) ? 1 : -1)
}
}
}

View File

@ -1,31 +1,33 @@
<div class="d-flex justify-content-center" *ngIf="detailsPlant">
<div class="d-flex align-items-center flex-column">
<img src="{{detailsPlant.product_url_picture}}" class="col-sm-5" style="width: 30rem;"
alt="Image de {{ detailsPlant.product_name }}">
<div class="card-content">
<app-avis-bar></app-avis-bar>
</div>
</div>
<div class="d-flex align-items-start flex-column mt-4 ">
<h4 style=" color: green;">{{detailsPlant.product_breadcrumb_label}}</h4>
<h2 class="card-title" style="font-size: 30px;">{{ detailsPlant.product_name }}</h2>
<div>
</div>
<div class="card-content">
</div>
<div style="border-style: solid; border-color: green; margin: auto; text-align: left; margin-right: 20%;padding: 2%;">
<p>
Plante appréciant la chaleur et un bon réseau wifi,
interconnectée avec son propriétaire et détestant les chats.
Beaucoup de café et un peu deau. Ne pas sortir en extérieur, sauf en terrasse. Floraison totale au
mois de juin.
</p>
</div>
<a href="#" class="card-content" class="btn btn-success">Je l'ajoute à mon panier : {{ detailsPlant.product_unitprice_ati }} €</a>
<div>Quantité restante : {{detailsPlant.product_qty}}</div>
<a href="#" class="btn btn-success" style="margin-left: 75%" >Voir mon panier</a>
</div>
</div>
<div class="d-flex align-items-center flex-column">
<img src="{{detailsPlant.product_url_picture}}" class="col-sm-5" style="width: 30rem;"
alt="Image de {{ detailsPlant.product_name }}">
<div class="card-content">
<app-avis-bar [ratingIndex]="detailsPlant.product_rating"></app-avis-bar>
</div>
</div>
<div class="d-flex align-items-start flex-column mt-4 ">
<h4 style=" color: green;">{{detailsPlant.product_breadcrumb_label}}</h4>
<h2 class="card-title" style="font-size: 30px;">{{ detailsPlant.product_name }}</h2>
<div>
</div>
<div class="card-content">
</div>
<div
style="border-style: solid; border-color: green; margin: auto; text-align: left; margin-right: 20%;padding: 2%;">
<p>
Plante appréciant la chaleur et un bon réseau wifi,
interconnectée avec son propriétaire et détestant les chats.
Beaucoup de café et un peu deau. Ne pas sortir en extérieur, sauf en terrasse. Floraison totale au
mois de juin.
</p>
</div>
<a href="#" class="card-content" class="btn btn-success">Je l'ajoute à mon panier
: {{ detailsPlant.product_unitprice_ati }} €</a>
<div>Quantité restante : {{detailsPlant.product_qty}}</div>
<a href="#" class="btn btn-success" style="margin-left: 75%">Voir mon panier</a>
</div>
</div>

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { PageDetailsComponent } from './page-details.component';
import {PageDetailsComponent} from './page-details.component';
describe('PageDetailsComponent', () => {
let component: PageDetailsComponent;
@ -8,9 +8,9 @@ describe('PageDetailsComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PageDetailsComponent ]
declarations: [PageDetailsComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { PlantouneService } from 'src/app/services/plantoune.service';
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {PlantouneService} from 'src/app/services/plantoune.service';
@Component({
@ -33,10 +33,10 @@ export class PageDetailsComponent implements OnInit {
// Faire appel au service et récuperer et executer la requete http et lui fournir le productId
this.plantouneService.getPlantById(productIdFromRoute).subscribe
(plant => {
this.detailsPlant = plant[0];
console.log(this.detailsPlant);
})
(plant => {
this.detailsPlant = plant[0];
console.log(this.detailsPlant);
})
})

View File

@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import { PageNotFoundComponent } from './page-not-found.component';
import {PageNotFoundComponent} from './page-not-found.component';
describe('PageNotFoundComponent', () => {
let component: PageNotFoundComponent;
@ -8,9 +8,9 @@ describe('PageNotFoundComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PageNotFoundComponent ]
declarations: [PageNotFoundComponent]
})
.compileComponents();
.compileComponents();
});
beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'app-page-not-found',
@ -7,7 +7,8 @@ import { Component, OnInit } from '@angular/core';
})
export class PageNotFoundComponent implements OnInit {
constructor() { }
constructor() {
}
ngOnInit(): void {
}

View File

@ -1,6 +1,6 @@
import { TestBed } from '@angular/core/testing';
import {TestBed} from '@angular/core/testing';
import { PlantouneService } from './plantoune.service';
import {PlantouneService} from './plantoune.service';
describe('PlantouneService', () => {
let service: PlantouneService;

View File

@ -1,21 +1,22 @@
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable, Subject} from 'rxjs';
import {HttpClient} from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class PlantouneService {
plantLiked$ = new Subject<any>();
constructor(private httpClient: HttpClient) { }
constructor(private httpClient: HttpClient) {
}
getData(): Observable<any[]> {
return this.httpClient.get<any[]>('http://localhost:3000/list_products');
}
getPlantById(id : any): Observable<any[]> {
getPlantById(id: any): Observable<any[]> {
return this.httpClient.get<any[]>('http://localhost:3000/list_products?product_id=' + id);
}
}

View File

@ -9,6 +9,6 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">
</head>
<body>
<app-root></app-root>
<app-root></app-root>
</body>
</html>

View File

@ -1,8 +1,8 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import {enableProdMode} from '@angular/core';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import {AppModule} from './app/app.module';
import {environment} from './environments/environment';
if (environment.production) {
enableProdMode();

View File

@ -45,7 +45,7 @@
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js'; // Included with Angular CLI.
import 'zone.js'; // Included with Angular CLI.
/***************************************************************************************************

View File

@ -1,11 +1,8 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import {getTestBed} from '@angular/core/testing';
import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing';
declare const require: {
context(path: string, deep?: boolean, filter?: RegExp): {