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 ## 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 ## 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 ## Build
@ -22,8 +24,10 @@ Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.
## Running end-to-end tests ## 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 ## 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'), dir: require('path').join(__dirname, './coverage/la-belle-plante'),
subdir: '.', subdir: '.',
reporters: [ reporters: [
{ type: 'html' }, {type: 'html'},
{ type: 'text-summary' } {type: 'text-summary'}
] ]
}, },
reporters: ['progress', 'kjhtml'], reporters: ['progress', 'kjhtml'],

2
package-lock.json generated
View File

@ -7185,7 +7185,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/is-typedarray": { "node_modules/is-typedarray": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
@ -7485,7 +7484,6 @@
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true "dev": true
}, },
"node_modules/json-server": { "node_modules/json-server": {
"version": "0.17.0", "version": "0.17.0",
"resolved": "https://registry.npmjs.org/json-server/-/json-server-0.17.0.tgz", "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 {NgModule} from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; 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 { PageAccueilComponent } from './pages/page-accueil/page-accueil.component'; import {PageDetailsComponent} from './pages/page-details/page-details.component';
import { PageDetailsComponent } from './pages/page-details/page-details.component'; import {PageNotFoundComponent} from './pages/page-not-found/page-not-found.component';
import { PageNotFoundComponent } from './pages/page-not-found/page-not-found.component';
const routes: Routes = [ const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' }, {path: '', redirectTo: 'home', pathMatch: 'full'},
{ {
path: 'home', component: PageAccueilComponent }, path: 'home', component: PageAccueilComponent
{ path: 'details/:productId', component: PageDetailsComponent},
{path : 'account',
loadChildren : () => import('./modules/account/account.module')
.then(m => m.AccountModule)
}, },
{ path: '**', component: PageNotFoundComponent } {path: 'details/:productId', component: PageDetailsComponent},
{
path: 'account',
loadChildren: () => import('./modules/account/account.module')
.then(m => m.AccountModule)
},
{path: '**', component: PageNotFoundComponent}
]; ];
@NgModule({ @NgModule({
imports: [RouterModule.forRoot(routes)], imports: [RouterModule.forRoot(routes)],
exports: [RouterModule] exports: [RouterModule]
}) })
export class AppRoutingModule { } export class AppRoutingModule {
}

View File

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

View File

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

View File

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

View File

@ -1,9 +1,16 @@
<div (mouseleave)="onMouseLeave()"> <div (mouseover)="isOver = true" *ngIf="isOver === false">
<app-icon *ngFor="let star of starStates; let starIndex = index" <app-icon *ngFor="let star of starStates; let starIndex = index"
[iconName]="star.stateHoverUser ? 'star-fill' : 'star'" [iconName]="star.stateRatingProduct ? 'star-fill' : 'star'"
[iconSize]="1.2" [iconSize]="1.2"
[iconColor]="'#ffbf00'" [iconColor]="'#ffbf00'"
(mouseover)="onMouseOver(starIndex)" ></app-icon>
(click)="onClickStar(starIndex)" </div>
></app-icon> <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> </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', () => { describe('AvisBarComponent', () => {
let component: AvisBarComponent; let component: AvisBarComponent;
@ -8,9 +8,9 @@ describe('AvisBarComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ AvisBarComponent ] declarations: [AvisBarComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { 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({ @Component({
selector: 'app-avis-bar', selector: 'app-avis-bar',
@ -6,30 +6,42 @@ import { Component, EventEmitter, OnInit, Output } from '@angular/core';
styleUrls: ['./avis-bar.component.scss'] styleUrls: ['./avis-bar.component.scss']
}) })
export class AvisBarComponent implements OnInit { export class AvisBarComponent implements OnInit {
starStates: {stateSelectedUser : boolean, stateHoverUser : boolean}[]; starStates: { stateSelectedUser: boolean, stateHoverUser: boolean, stateRatingProduct: boolean }[];
@Output() stateNumber = new EventEmitter @Output() stateNumber = new EventEmitter
starStateNumber: number = 0; starStateNumber: number = 0;
@Input() ratingIndex: number = 0;
isOver: boolean;
constructor() { constructor() {
this.starStates = []; this.starStates = [];
this.isOver = false;
for (let index = 0; index < 5; index++) { for (let index = 0; index < 5; index++) {
this.starStates.push( this.starStates.push(
{ {
stateSelectedUser : false, stateSelectedUser: false,
stateHoverUser : false stateHoverUser: false,
stateRatingProduct: false
} }
); );
} }
} }
ngOnInit(): void { 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) { onMouseOver(index: number) {
console.log("star over", index); console.log("star over", index);
for (let i = 0; i < this.starStates.length ; i++) { this.isOver = true;
if(i <= index) { for (let i = 0; i < this.starStates.length; i++) {
if (i <= index) {
this.starStates[i].stateHoverUser = true; this.starStates[i].stateHoverUser = true;
} else { } else {
this.starStates[i].stateHoverUser = false; this.starStates[i].stateHoverUser = false;
@ -39,12 +51,14 @@ export class AvisBarComponent implements OnInit {
onMouseLeave() { onMouseLeave() {
// this.starState = ['star', 'star', 'star', 'star', 'star']; // this.starState = ['star', 'star', 'star', 'star', 'star'];
this.isOver = false;
const tempTab = []; const tempTab = [];
for (let index = 0; index < this.starStates.length; index++) { for (let index = 0; index < this.starStates.length; index++) {
tempTab.push( tempTab.push(
{ {
stateSelectedUser : this.starStates[index].stateSelectedUser, stateSelectedUser: this.starStates[index].stateSelectedUser,
stateHoverUser : 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) { onClickStar(starIndex: number) {
this.starStateNumber = 0; this.starStateNumber = 0;
for (let i = 0; i < this.starStates.length ; i++) { for (let i = 0; i < this.starStates.length; i++) {
if(i <= starIndex) { if (i <= starIndex) {
this.starStates[i].stateSelectedUser = true; this.starStates[i].stateSelectedUser = true;
this.starStates[i].stateRatingProduct = true;
this.starStateNumber++; this.starStateNumber++;
} else { } else {
this.starStates[i].stateSelectedUser = false; this.starStates[i].stateSelectedUser = false;
this.starStates[i].stateRatingProduct = false;
} }
} }
//console.log(`Rating : ${this.starStateNumber}`); //console.log(`Rating : ${this.starStateNumber}`);
this.stateNumber.emit(this.starStateNumber); this.stateNumber.emit(this.starStateNumber);
} }
} }

View File

@ -1,20 +1,21 @@
<div class="plant card mb-4" style="width: 14rem;"> <div class="plant card mb-4" style="width: 14rem;">
<app-icon class="like" <app-icon class="like"
[iconName]="'heart'" [iconName]="'heart'"
[iconColor]="'#e35d6a'" [iconColor]="'#e35d6a'"
(click)="onClickLike()"></app-icon> (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)"> <img src="{{plant.product_url_picture}}" class="card-img-top" alt="Image de {{ plant.product_name }}"
<div class="card-body"> (click)="onGetId(plant.product_id)">
<h6 class="card-title" (click) = "onGetId(plant.product_id)">{{ plant.product_name }}</h6> <div class="card-body">
<div class="card-content"> <h6 class="card-title" (click)="onGetId(plant.product_id)">{{ plant.product_name }}</h6>
<app-avis-bar></app-avis-bar> <div class="card-content">
</div> <app-avis-bar [ratingIndex]="plant.product_rating"></app-avis-bar>
<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>
<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> </div>

View File

@ -1,14 +1,15 @@
.plant { .plant {
min-height: 22rem; min-height: 22rem;
.card-body {
display: flex; .card-body {
flex-direction: column; display: flex;
justify-content: space-between; flex-direction: column;
} justify-content: space-between;
}
} }
.like { .like {
position: absolute; position: absolute;
right: 0.7rem; right: 0.7rem;
top: 0.5rem; 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', () => { describe('CardPlanteComponent', () => {
let component: CardPlanteComponent; let component: CardPlanteComponent;
@ -8,9 +8,9 @@ describe('CardPlanteComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ CardPlanteComponent ] declarations: [CardPlanteComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { beforeEach(() => {

View File

@ -1,5 +1,5 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import { Router } from '@angular/router'; import {Router} from '@angular/router';
@Component({ @Component({
@ -12,17 +12,20 @@ export class CardPlanteComponent implements OnInit {
@Output() clickLike = new EventEmitter(); @Output() clickLike = new EventEmitter();
@Output() clickCardId = new EventEmitter(); @Output() clickCardId = new EventEmitter();
constructor(private router : Router) {} constructor(private router: Router) {
}
ngOnInit(): void { ngOnInit(): void {
} }
onClickLike() { onClickLike() {
console.log('click'); console.log('click');
this.clickLike.emit(); this.clickLike.emit();
} }
onGetId(id : string){
onGetId(id: string) {
this.clickCardId.emit(id); 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="custom-side-bar flex-shrink-0 bg-white border-end">
<div class="p-3"> <div class="p-3">
<span class="fs-5 fw-semibold">Filtres</span> <span class="fs-5 fw-semibold">Filtres</span>
</div> </div>
<ul class="list-unstyled ps-0 border-top"> <ul class="list-unstyled ps-0 border-top">
<div class="p-3"> <div class="p-3">
<p class="mb-1 fs-5 fw-semibold">Catégories</p> <p class="mb-1 fs-5 fw-semibold">Catégories</p>
<div *ngFor="let category of listCategories; let indexCat = index" class="form-check"> <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}}"> <label class="form-check-label" for="checkBoxCategory{{indexCat}}">
{{ category }} {{ category }}
</label> </label>
</div> </div>
<div *ngIf="listCategories.length == 0 "> <div *ngIf="listCategories.length == 0 ">
Aucune catégorie disponible Aucune catégorie disponible
</div> </div>
</div> </div>
</ul> </ul>
<ul class="list-unstyled ps-0 border-top"> <ul class="list-unstyled ps-0 border-top">
<div class="p-3"> <div class="p-3">
<p class="mb-1 fs-5 fw-semibold">Prix</p> <p class="mb-1 fs-5 fw-semibold">Prix</p>
<div class="d-flex justify-content-center"> <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 #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%;"> <input #maxNum id="numberMax" type="number" placeholder="max" value="" class="me-2" style="width: 45%;">
</div> </div>
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<button class="btn btn-success m-3" (click)="onSendValues(minNum, maxNum)">Valider</button> <button class="btn btn-success m-3" (click)="onSendValues(minNum, maxNum)">Valider</button>
</div> </div>
</div> </div>
</ul> </ul>
<ul class="list-unstyled ps-0 border-top"> <ul class="list-unstyled ps-0 border-top">
<div class="p-3"> <div class="p-3">
<p class="mb-1 fs-5 fw-semibold">Avis</p> <p class="mb-1 fs-5 fw-semibold">Avis</p>
<div class="flex-column justify-content-start"> <div class="flex-column justify-content-start">
<app-avis-bar (stateNumber)="onStateNumberChange($event)"></app-avis-bar> <app-avis-bar (stateNumber)="onStateNumberChange($event)"></app-avis-bar>
<button class="btn btn-success me-2" (click)="onSendRating()">Valider</button> <button class="btn btn-success me-2" (click)="onSendRating()">Valider</button>
</div> </div>
</div> </div>
</ul> </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> </div>

View File

@ -1,5 +1,5 @@
.custom-side-bar { .custom-side-bar {
min-height: calc(100vh - 54px); min-height: calc(100vh - 54px);
width: 280px; width: 280px;
height: 100%; 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', () => { describe('FilterSideBarComponent', () => {
let component: FilterSideBarComponent; let component: FilterSideBarComponent;
@ -8,9 +8,9 @@ describe('FilterSideBarComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ FilterSideBarComponent ] declarations: [FilterSideBarComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { 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({ @Component({
selector: 'app-filter-side-bar', selector: 'app-filter-side-bar',
@ -10,10 +10,10 @@ export class FilterSideBarComponent implements OnInit {
@Output() checkCategory = new EventEmitter(); @Output() checkCategory = new EventEmitter();
@Output() stateNumber = new EventEmitter(); @Output() stateNumber = new EventEmitter();
@Output() rangeNumber = new EventEmitter(); @Output() rangeNumber = new EventEmitter();
@Output() reset = new EventEmitter();
filterStateNumber: number = 0; filterStateNumber: number = 0;
public selectedCategory: string[]; public selectedCategory: string[];
constructor() { constructor() {
this.listCategories = []; this.listCategories = [];
this.selectedCategory = []; this.selectedCategory = [];
@ -45,13 +45,23 @@ export class FilterSideBarComponent implements OnInit {
this.filterStateNumber = stateNumber; this.filterStateNumber = stateNumber;
} }
onSendRating():void { onSendRating(): void {
this.stateNumber.emit(this.filterStateNumber); this.stateNumber.emit(this.filterStateNumber);
} }
onSendValues(minNum: any, maxNum: any): void { 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)]; let rangeArray: number[] = [parseFloat(minNum.value), parseFloat(maxNum.value)];
console.log(typeof(rangeArray[0]));
this.rangeNumber.emit(rangeArray); this.rangeNumber.emit(rangeArray);
} }
onReset(): void {
this.reset.emit();
}
} }

View File

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

View File

@ -1,3 +1,3 @@
i { 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', () => { describe('IconComponent', () => {
let component: IconComponent; let component: IconComponent;
@ -8,9 +8,9 @@ describe('IconComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ IconComponent ] declarations: [IconComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { beforeEach(() => {

View File

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

View File

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

View File

@ -1,3 +1,3 @@
.active-custom { .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', () => { describe('NavBarComponent', () => {
let component: NavBarComponent; let component: NavBarComponent;
@ -8,9 +8,9 @@ describe('NavBarComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ NavBarComponent ] declarations: [NavBarComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { beforeEach(() => {

View File

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

View File

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

View File

@ -1,11 +1,11 @@
import { NgModule } from '@angular/core'; import {NgModule} from '@angular/core';
import { CommonModule } from '@angular/common'; import {CommonModule} from '@angular/common';
import { AccountRoutingModule } from './account-routing.module'; import {AccountRoutingModule} from './account-routing.module';
import { PageSignupComponent } from './pages/page-signup/page-signup.component'; import {PageSignupComponent} from './pages/page-signup/page-signup.component';
import { PageSigninComponent } from './pages/page-signin/page-signin.component'; import {PageSigninComponent} from './pages/page-signin/page-signin.component';
import { PageForgotPasswordComponent } from './pages/page-forgot-password/page-forgot-password.component'; import {PageForgotPasswordComponent} from './pages/page-forgot-password/page-forgot-password.component';
import { PageResetPasswordComponent } from './pages/page-reset-password/page-reset-password.component'; import {PageResetPasswordComponent} from './pages/page-reset-password/page-reset-password.component';
@NgModule({ @NgModule({
@ -20,4 +20,5 @@ import { PageResetPasswordComponent } from './pages/page-reset-password/page-res
AccountRoutingModule 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', () => { describe('PageForgotPasswordComponent', () => {
let component: PageForgotPasswordComponent; let component: PageForgotPasswordComponent;
@ -8,9 +8,9 @@ describe('PageForgotPasswordComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ PageForgotPasswordComponent ] declarations: [PageForgotPasswordComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core'; import {Component, OnInit} from '@angular/core';
@Component({ @Component({
selector: 'app-page-forgot-password', selector: 'app-page-forgot-password',
@ -7,7 +7,8 @@ import { Component, OnInit } from '@angular/core';
}) })
export class PageForgotPasswordComponent implements OnInit { export class PageForgotPasswordComponent implements OnInit {
constructor() { } constructor() {
}
ngOnInit(): void { 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', () => { describe('PageResetPasswordComponent', () => {
let component: PageResetPasswordComponent; let component: PageResetPasswordComponent;
@ -8,9 +8,9 @@ describe('PageResetPasswordComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ PageResetPasswordComponent ] declarations: [PageResetPasswordComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core'; import {Component, OnInit} from '@angular/core';
@Component({ @Component({
selector: 'app-page-reset-password', selector: 'app-page-reset-password',
@ -7,7 +7,8 @@ import { Component, OnInit } from '@angular/core';
}) })
export class PageResetPasswordComponent implements OnInit { export class PageResetPasswordComponent implements OnInit {
constructor() { } constructor() {
}
ngOnInit(): void { 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', () => { describe('PageSigninComponent', () => {
let component: PageSigninComponent; let component: PageSigninComponent;
@ -8,9 +8,9 @@ describe('PageSigninComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ PageSigninComponent ] declarations: [PageSigninComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core'; import {Component, OnInit} from '@angular/core';
@Component({ @Component({
selector: 'app-page-signin', selector: 'app-page-signin',
@ -7,7 +7,8 @@ import { Component, OnInit } from '@angular/core';
}) })
export class PageSigninComponent implements OnInit { export class PageSigninComponent implements OnInit {
constructor() { } constructor() {
}
ngOnInit(): void { 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', () => { describe('PageSignupComponent', () => {
let component: PageSignupComponent; let component: PageSignupComponent;
@ -8,9 +8,9 @@ describe('PageSignupComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ PageSignupComponent ] declarations: [PageSignupComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { beforeEach(() => {

View File

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

View File

@ -1,23 +1,25 @@
<div class="d-flex align-items-stretch"> <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"> <div class="custom-main container p-3">
<input class="form-control" <input class="form-control"
type="text" type="text"
placeholder="Recherche ta belle plante" placeholder="Recherche ta belle plante"
aria-label="Input Recherche ta belle plante" aria-label="Input Recherche ta belle plante"
(input)="onRecherchePlante($event)"> (input)="onRecherchePlante($event)">
<div class="py-3"> <div class="py-3">
Trier par : 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)="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)="onAlphaTri()">Ordre Alpha</button>
<button class="btn btn-outline-success btn-sm me-2" (click)="onRatingTri()">Avis</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>
</div> </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', () => { describe('PageAccueilComponent', () => {
let component: PageAccueilComponent; let component: PageAccueilComponent;
@ -8,9 +8,9 @@ describe('PageAccueilComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ PageAccueilComponent ] declarations: [PageAccueilComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { beforeEach(() => {

View File

@ -1,9 +1,6 @@
import { Component, OnInit } from '@angular/core'; import {Component, OnInit} from '@angular/core';
import { PlantouneService } from 'src/app/services/plantoune.service'; import {PlantouneService} from 'src/app/services/plantoune.service';
import * as _ from 'underscore'; import * as _ from 'underscore';
import { contains, includes } from 'underscore';
@Component({ @Component({
@ -13,19 +10,21 @@ import { contains, includes } from 'underscore';
}) })
export class PageAccueilComponent implements OnInit { export class PageAccueilComponent implements OnInit {
public listData: any[]; public listData: any[];
public listPricePlant : any[]; public listPricePlant: any[];
public clickCounter : any; public clickCounter: any;
public listDataGlobal : any[]; public listDataGlobal: any[];
public listDataFilter: any[]; public listDataFilter: any[];
public listCategoriesFilter: string[]; public listCategoriesFilter: string[];
public dataFilterCategory : any;
public category: string[];
public choix: string;
public rangeNumber: number[]; public rangeNumber: number[];
public stateNumber: number; public stateNumber: number;
public isCategoryFilterActive: boolean;
public isPricingFilterActive: boolean; public isPricingFilterActive: boolean;
public isRatingFilterActive: boolean; public isRatingFilterActive: boolean;
public isSearchFilterActive: boolean;
constructor(private plantouneService: PlantouneService) { constructor(private plantouneService: PlantouneService) {
this.listData = []; this.listData = [];
@ -35,23 +34,27 @@ export class PageAccueilComponent implements OnInit {
this.clickCounter = 0; this.clickCounter = 0;
this.listDataFilter = []; this.listDataFilter = [];
this.category = [];
this.choix = '';
this.rangeNumber = []; this.rangeNumber = [];
this.stateNumber = 0; this.stateNumber = 0;
this.isCategoryFilterActive = false;
this.isPricingFilterActive = false; this.isPricingFilterActive = false;
this.isRatingFilterActive = false; this.isRatingFilterActive = false;
this.isSearchFilterActive = false;
this.clickCounter = 0; this.clickCounter = 0;
} }
/** /**
* equivalent de la ligne du dessus * equivalent de la ligne du dessus
* *
* plantouneService; * plantouneService;
* *
* constructor(plantouneService: PlantouneService) { * constructor(plantouneService: PlantouneService) {
* this.plantouneService = plantouneService; } * this.plantouneService = plantouneService; }
*/ */
ngOnInit(): void { ngOnInit(): void {
@ -61,7 +64,7 @@ export class PageAccueilComponent implements OnInit {
this.listDataGlobal = [...listPlant]; this.listDataGlobal = [...listPlant];
this.listDataFilter = [...this.listDataGlobal]; this.listDataFilter = [...this.listDataGlobal];
console.log(this.listDataGlobal); console.log(this.listDataGlobal);
/** /**
* Technique avec Underscore JS pour recupérer les catégories uniques de nos plantes * 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); // console.log(listUniqCategories);
/** /**
* Technique native JS pour recupérer les catégories uniques de nos plantes * 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 = [...listPlant];
this.listData.length = 9; this.listData.length = 9;
this.listDataGlobal = [...listPlant] this.listDataGlobal = [...listPlant]
console.log(this.listData); console.log(this.listData);
} }
) )
@ -94,137 +96,292 @@ export class PageAccueilComponent implements OnInit {
this.plantouneService.plantLiked$.next(''); 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 ++ // onListCategory(categoryArray: string[]) {
console.log(this.clickCounter) // // this.listData=listData;
if (this.clickCounter %2) { // //console.log(typeof(valueText));
this.listData.sort((a, b) => parseFloat(a.product_price) - parseFloat(b.product_price)); //
}else{ // if (categoryArray.length == 0) {
this.listData.sort((a, b) => parseFloat(b.product_price) - parseFloat(a.product_price)); // this.listData = [...this.listDataGlobal];
} //
const search = choix.target.value // } else if (categoryArray.length > 0) {
console.log(search); // let listProductsByCategory: string[] = [];
this.listData = this.listDataGlobal.filter((plant) => { // this.listDataGlobal.forEach(product => {
if(plant.product_name.toLowerCase().includes(search.toLowerCase())){ //
return plant; // categoryArray.forEach(categorySelected => {
} // if (product.product_breadcrumb_label == categorySelected) {
}); // listProductsByCategory.push(product);
//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.listData = [...listProductsByCategory];
} // }
//
// if (this.listData.length >= 9) {
// this.listData.length = 9;
// }
// }
onListCategory(categoryArray: string[]) { onListCategory(categoryArray: string[]) {
// this.listData=listData; if (categoryArray.length == 0) {
//console.log(typeof(valueText)); this.listData = [...this.listDataGlobal];
this.isCategoryFilterActive = false;
if(categoryArray.length == 0) { } else {
this.listData = [...this.listDataGlobal]; this.category = [...categoryArray];
this.isCategoryFilterActive = true;
} else if(categoryArray.length > 0) { }
let listProductsByCategory:string[] = [];
this.listDataGlobal.forEach(product => { this.onApplyFilters();
}
categoryArray.forEach(categorySelected => {
if (product.product_breadcrumb_label == categorySelected){ onRecherchePlante(choix: any) {
listProductsByCategory.push(product); this.choix = choix.target.value;
} this.isSearchFilterActive = true;
});
}); this.onApplyFilters();
this.listData= [...listProductsByCategory]; }
}
onRatingFilter(stateNumber: number): void {
if(this.listData.length>=9){ this.stateNumber = stateNumber;
this.listData.length=9; this.isRatingFilterActive = true;
}
} this.onApplyFilters();
}
onRatingFilter(stateNumber: number): void {
this.stateNumber = stateNumber; onPriceFilter(rangeNumber: number[]) {
this.isRatingFilterActive = true; this.rangeNumber = [...rangeNumber];
this.isPricingFilterActive = true;
this.onApplyFilters();
} this.onApplyFilters();
}
onPriceFilter(rangeNumber: number[]) {
this.rangeNumber = [...rangeNumber]; onApplyFilters(): void {
this.isPricingFilterActive = true; this.clickCounter = 0;
this.onApplyFilters(); if (this.isCategoryFilterActive) {
} let listDataFinal: any = [];
this.listDataGlobal.forEach(product => {
onApplyFilters(): void { this.category.forEach(categorySelected => {
this.clickCounter = 0; if (product.product_breadcrumb_label == categorySelected) {
listDataFinal.push(product);
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]) { this.listData = [...listDataFinal];
listDataFinal.push(product); }
}
}); if (this.isSearchFilterActive) {
this.listData = [...listDataFinal]; let listDataFinal: any = [];
} this.listDataGlobal.forEach(product => {
if (product.product_name.toLowerCase().includes(this.choix.toLowerCase())) {
if(this.isRatingFilterActive) { listDataFinal.push(product);
let listDataFinal: any = []; }
this.listDataGlobal.forEach(product => { });
if(product.product_rating >= this.stateNumber) { this.listData = [...listDataFinal];
listDataFinal.push(product); }
}
}); if (this.isPricingFilterActive) {
this.listData = [...listDataFinal]; let listDataFinal: any = [];
} this.listDataGlobal.forEach(product => {
if (parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0]
if(this.isPricingFilterActive && this.isRatingFilterActive) { && parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1]) {
let listDataFinal: any = []; listDataFinal.push(product);
this.listDataGlobal.forEach(product => { }
if(parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0] });
&& parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1] this.listData = [...listDataFinal];
&& product.product_rating >= this.stateNumber) { }
listDataFinal.push(product);
} if (this.isRatingFilterActive) {
}); let listDataFinal: any = [];
this.listData = [...listDataFinal]; this.listDataGlobal.forEach(product => {
console.log(this.listData); if (product.product_rating >= this.stateNumber) {
} listDataFinal.push(product);
}
if(this.listData.length >= 9) this.listData.length = 9; });
} this.listData = [...listDataFinal];
}
//Tri des prix des plantes par ordre croissant ou décroissant
onPriceTri() : void { if (this.isSearchFilterActive && this.isCategoryFilterActive) {
let listDataFinal: any = [];
this.clickCounter ++ this.listDataGlobal.forEach(product => {
console.log(this.clickCounter) this.category.forEach(categorySelected => {
if (this.clickCounter %2) { if (product.product_breadcrumb_label == categorySelected
this.listData.sort((a, b) => parseFloat(a.product_price) - parseFloat(b.product_price)); && product.product_name.toLowerCase().includes(this.choix.toLowerCase())) {
}else{ listDataFinal.push(product);
this.listData.sort((a, b) => parseFloat(b.product_price) - parseFloat(a.product_price)); }
} });
} });
this.listData = [...listDataFinal];
//Tri des noms des plantes par ordre alphanumérique }
onAlphaTri() : void {
if (this.isPricingFilterActive && this.isCategoryFilterActive) {
this.clickCounter ++ let listDataFinal: any = [];
if (this.clickCounter %2) { this.listDataGlobal.forEach(product => {
this.listData.sort((a, b) => (a.product_name > b.product_name) ? 1 : -1) this.category.forEach(categorySelected => {
}else{ if (product.product_breadcrumb_label == categorySelected
this.listData.sort((a, b) => (b.product_name > a.product_name) ? 1 : -1) && parseFloat(product.product_unitprice_ati) >= this.rangeNumber[0]
} && parseFloat(product.product_unitprice_ati) <= this.rangeNumber[1]) {
} listDataFinal.push(product);
}
//Tri des avis des plantes par ordre croissant ou décroissant });
onRatingTri() : void{ });
this.clickCounter ++ this.listData = [...listDataFinal];
if (this.clickCounter %2) { }
this.listData.sort((a, b) => (a.product_rating > b.product_rating) ? 1 : -1)
}else{ if (this.isRatingFilterActive && this.isCategoryFilterActive) {
this.listData.sort((a, b) => (b.product_rating > a.product_rating) ? 1 : -1) 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 justify-content-center" *ngIf="detailsPlant">
<div class="d-flex align-items-center flex-column"> <div class="d-flex align-items-center flex-column">
<img src="{{detailsPlant.product_url_picture}}" class="col-sm-5" style="width: 30rem;" <img src="{{detailsPlant.product_url_picture}}" class="col-sm-5" style="width: 30rem;"
alt="Image de {{ detailsPlant.product_name }}"> alt="Image de {{ detailsPlant.product_name }}">
<div class="card-content"> <div class="card-content">
<app-avis-bar></app-avis-bar> <app-avis-bar [ratingIndex]="detailsPlant.product_rating"></app-avis-bar>
</div> </div>
</div> </div>
<div class="d-flex align-items-start flex-column mt-4 "> <div class="d-flex align-items-start flex-column mt-4 ">
<h4 style=" color: green;">{{detailsPlant.product_breadcrumb_label}}</h4> <h4 style=" color: green;">{{detailsPlant.product_breadcrumb_label}}</h4>
<h2 class="card-title" style="font-size: 30px;">{{ detailsPlant.product_name }}</h2> <h2 class="card-title" style="font-size: 30px;">{{ detailsPlant.product_name }}</h2>
<div> <div>
</div> </div>
<div class="card-content"> <div class="card-content">
</div> </div>
<div style="border-style: solid; border-color: green; margin: auto; text-align: left; margin-right: 20%;padding: 2%;"> <div
<p> style="border-style: solid; border-color: green; margin: auto; text-align: left; margin-right: 20%;padding: 2%;">
Plante appréciant la chaleur et un bon réseau wifi, <p>
interconnectée avec son propriétaire et détestant les chats. Plante appréciant la chaleur et un bon réseau wifi,
Beaucoup de café et un peu deau. Ne pas sortir en extérieur, sauf en terrasse. Floraison totale au interconnectée avec son propriétaire et détestant les chats.
mois de juin. Beaucoup de café et un peu deau. Ne pas sortir en extérieur, sauf en terrasse. Floraison totale au
</p> mois de juin.
</div> </p>
<a href="#" class="card-content" class="btn btn-success">Je l'ajoute à mon panier : {{ detailsPlant.product_unitprice_ati }} €</a> </div>
<a href="#" class="card-content" class="btn btn-success">Je l'ajoute à mon panier
<div>Quantité restante : {{detailsPlant.product_qty}}</div> : {{ detailsPlant.product_unitprice_ati }} €</a>
<a href="#" class="btn btn-success" style="margin-left: 75%" >Voir mon panier</a>
</div> <div>Quantité restante : {{detailsPlant.product_qty}}</div>
<a href="#" class="btn btn-success" style="margin-left: 75%">Voir mon panier</a>
</div> </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', () => { describe('PageDetailsComponent', () => {
let component: PageDetailsComponent; let component: PageDetailsComponent;
@ -8,9 +8,9 @@ describe('PageDetailsComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ PageDetailsComponent ] declarations: [PageDetailsComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { beforeEach(() => {

View File

@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core'; import {Component, OnInit} from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import {ActivatedRoute} from '@angular/router';
import { PlantouneService } from 'src/app/services/plantoune.service'; import {PlantouneService} from 'src/app/services/plantoune.service';
@Component({ @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 // Faire appel au service et récuperer et executer la requete http et lui fournir le productId
this.plantouneService.getPlantById(productIdFromRoute).subscribe this.plantouneService.getPlantById(productIdFromRoute).subscribe
(plant => { (plant => {
this.detailsPlant = plant[0]; this.detailsPlant = plant[0];
console.log(this.detailsPlant); 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', () => { describe('PageNotFoundComponent', () => {
let component: PageNotFoundComponent; let component: PageNotFoundComponent;
@ -8,9 +8,9 @@ describe('PageNotFoundComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
declarations: [ PageNotFoundComponent ] declarations: [PageNotFoundComponent]
}) })
.compileComponents(); .compileComponents();
}); });
beforeEach(() => { beforeEach(() => {

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core'; import {Component, OnInit} from '@angular/core';
@Component({ @Component({
selector: 'app-page-not-found', selector: 'app-page-not-found',
@ -7,7 +7,8 @@ import { Component, OnInit } from '@angular/core';
}) })
export class PageNotFoundComponent implements OnInit { export class PageNotFoundComponent implements OnInit {
constructor() { } constructor() {
}
ngOnInit(): void { 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', () => { describe('PlantouneService', () => {
let service: PlantouneService; let service: PlantouneService;

View File

@ -1,21 +1,22 @@
import { Injectable } from '@angular/core'; import {Injectable} from '@angular/core';
import { Observable, Subject } from 'rxjs'; import {Observable, Subject} from 'rxjs';
import { HttpClient } from '@angular/common/http'; import {HttpClient} from '@angular/common/http';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class PlantouneService { export class PlantouneService {
plantLiked$ = new Subject<any>(); plantLiked$ = new Subject<any>();
constructor(private httpClient: HttpClient) { } constructor(private httpClient: HttpClient) {
}
getData(): Observable<any[]> { getData(): Observable<any[]> {
return this.httpClient.get<any[]>('http://localhost:3000/list_products'); 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); 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"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">
</head> </head>
<body> <body>
<app-root></app-root> <app-root></app-root>
</body> </body>
</html> </html>

View File

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

View File

@ -45,7 +45,7 @@
/*************************************************************************************************** /***************************************************************************************************
* Zone JS is required by default for Angular itself. * 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 // This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/testing'; import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing'; import {getTestBed} from '@angular/core/testing';
import { import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing';
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: { declare const require: {
context(path: string, deep?: boolean, filter?: RegExp): { context(path: string, deep?: boolean, filter?: RegExp): {