Inital Commit
This commit is contained in:
commit
64ead91fc2
68 changed files with 16302 additions and 0 deletions
16
.editorconfig
Normal file
16
.editorconfig
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Editor configuration, see https://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.ts]
|
||||||
|
quote_type = single
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
||||||
42
.gitignore
vendored
Normal file
42
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
|
||||||
|
|
||||||
|
# Compiled output
|
||||||
|
/dist
|
||||||
|
/tmp
|
||||||
|
/out-tsc
|
||||||
|
/bazel-out
|
||||||
|
|
||||||
|
# Node
|
||||||
|
/node_modules
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
.idea/
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.history/*
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
/.angular/cache
|
||||||
|
.sass-cache/
|
||||||
|
/connect.lock
|
||||||
|
/coverage
|
||||||
|
/libpeerconnection.log
|
||||||
|
testem.log
|
||||||
|
/typings
|
||||||
|
|
||||||
|
# System files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
27
README.md
Normal file
27
README.md
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# SecondApp
|
||||||
|
|
||||||
|
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.2.3.
|
||||||
|
|
||||||
|
## Development server
|
||||||
|
|
||||||
|
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
|
||||||
|
|
||||||
|
## 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`.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
## 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.dev/tools/cli) page.
|
||||||
112
angular.json
Normal file
112
angular.json
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
|
"version": 1,
|
||||||
|
"newProjectRoot": "projects",
|
||||||
|
"projects": {
|
||||||
|
"second-app": {
|
||||||
|
"projectType": "application",
|
||||||
|
"schematics": {
|
||||||
|
"@schematics/angular:component": {
|
||||||
|
"standalone": false
|
||||||
|
},
|
||||||
|
"@schematics/angular:directive": {
|
||||||
|
"standalone": false
|
||||||
|
},
|
||||||
|
"@schematics/angular:pipe": {
|
||||||
|
"standalone": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "",
|
||||||
|
"sourceRoot": "src",
|
||||||
|
"prefix": "app",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-angular:application",
|
||||||
|
"options": {
|
||||||
|
"outputPath": "dist/second-app",
|
||||||
|
"index": "src/index.html",
|
||||||
|
"browser": "src/main.ts",
|
||||||
|
"polyfills": [
|
||||||
|
"zone.js"
|
||||||
|
],
|
||||||
|
"tsConfig": "tsconfig.app.json",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"glob": "**/*",
|
||||||
|
"input": "public"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"src/styles.css",
|
||||||
|
"node_modules/bootstrap/dist/css/bootstrap.min.css"
|
||||||
|
],
|
||||||
|
"scripts": [
|
||||||
|
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"type": "initial",
|
||||||
|
"maximumWarning": "500kB",
|
||||||
|
"maximumError": "1MB"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "anyComponentStyle",
|
||||||
|
"maximumWarning": "2kB",
|
||||||
|
"maximumError": "4kB"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputHashing": "all"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"optimization": false,
|
||||||
|
"extractLicenses": false,
|
||||||
|
"sourceMap": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "production"
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"builder": "@angular-devkit/build-angular:dev-server",
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "second-app:build:production"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "second-app:build:development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "development"
|
||||||
|
},
|
||||||
|
"extract-i18n": {
|
||||||
|
"builder": "@angular-devkit/build-angular:extract-i18n"
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"polyfills": [
|
||||||
|
"zone.js",
|
||||||
|
"zone.js/testing"
|
||||||
|
],
|
||||||
|
"tsConfig": "tsconfig.spec.json",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"glob": "**/*",
|
||||||
|
"input": "public"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"src/styles.css"
|
||||||
|
],
|
||||||
|
"scripts": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cli": {
|
||||||
|
"analytics": false
|
||||||
|
}
|
||||||
|
}
|
||||||
14653
package-lock.json
generated
Normal file
14653
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
42
package.json
Normal file
42
package.json
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
"name": "second-app",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"ng": "ng",
|
||||||
|
"start": "json-server -- watch produit.json --port 3500 & ng serve",
|
||||||
|
"build": "ng build",
|
||||||
|
"watch": "ng build --watch --configuration development",
|
||||||
|
"test": "ng test"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/animations": "^18.2.0",
|
||||||
|
"@angular/common": "^18.2.0",
|
||||||
|
"@angular/compiler": "^18.2.0",
|
||||||
|
"@angular/core": "^18.2.0",
|
||||||
|
"@angular/forms": "^18.2.0",
|
||||||
|
"@angular/platform-browser": "^18.2.0",
|
||||||
|
"@angular/platform-browser-dynamic": "^18.2.0",
|
||||||
|
"@angular/router": "^18.2.0",
|
||||||
|
"bootstrap": "^5.3.3",
|
||||||
|
"bootstrap-icons": "^1.11.3",
|
||||||
|
"rxjs": "~7.8.0",
|
||||||
|
"simple-datatables": "^9.2.1",
|
||||||
|
"sweetalert2": "^11.14.5",
|
||||||
|
"tslib": "^2.3.0",
|
||||||
|
"zone.js": "~0.14.10"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular-devkit/build-angular": "^18.2.3",
|
||||||
|
"@angular/cli": "^18.2.3",
|
||||||
|
"@angular/compiler-cli": "^18.2.0",
|
||||||
|
"@types/jasmine": "~5.1.0",
|
||||||
|
"jasmine-core": "~5.2.0",
|
||||||
|
"karma": "~6.4.0",
|
||||||
|
"karma-chrome-launcher": "~3.2.0",
|
||||||
|
"karma-coverage": "~2.2.0",
|
||||||
|
"karma-jasmine": "~5.1.0",
|
||||||
|
"karma-jasmine-html-reporter": "~2.1.0",
|
||||||
|
"typescript": "~5.5.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
95
produit.json
Normal file
95
produit.json
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
{
|
||||||
|
"produits": [
|
||||||
|
{
|
||||||
|
"id": "1",
|
||||||
|
"name": "Produit 1",
|
||||||
|
"price": 100,
|
||||||
|
"quantity": 5,
|
||||||
|
"checked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2",
|
||||||
|
"name": "Produit 2",
|
||||||
|
"price": 200,
|
||||||
|
"quantity": 5,
|
||||||
|
"checked": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3",
|
||||||
|
"name": "Produit 3",
|
||||||
|
"price": 300,
|
||||||
|
"quantity": 5,
|
||||||
|
"checked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4",
|
||||||
|
"name": "Produit 4",
|
||||||
|
"price": 400,
|
||||||
|
"quantity": 5,
|
||||||
|
"checked": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5",
|
||||||
|
"name": "Produit 5",
|
||||||
|
"price": 500,
|
||||||
|
"quantity": 5,
|
||||||
|
"checked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6",
|
||||||
|
"name": "Produit 6",
|
||||||
|
"price": 600,
|
||||||
|
"quantity": 5,
|
||||||
|
"checked": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7",
|
||||||
|
"name": "Produit 7",
|
||||||
|
"price": 700,
|
||||||
|
"quantity": 5,
|
||||||
|
"checked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8",
|
||||||
|
"name": "Produit 8",
|
||||||
|
"price": 800,
|
||||||
|
"quantity": 5,
|
||||||
|
"checked": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9",
|
||||||
|
"name": "Produit 9",
|
||||||
|
"price": 900,
|
||||||
|
"quantity": 5,
|
||||||
|
"checked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "10",
|
||||||
|
"name": "Produit 10",
|
||||||
|
"price": 1000,
|
||||||
|
"quantity": 5,
|
||||||
|
"checked": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "aa4a",
|
||||||
|
"name": "tete",
|
||||||
|
"price": "478",
|
||||||
|
"quantity": 0,
|
||||||
|
"checked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d412",
|
||||||
|
"name": "gg",
|
||||||
|
"price": "15",
|
||||||
|
"quantity": 0,
|
||||||
|
"checked": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9427",
|
||||||
|
"name": "gfdgfgf",
|
||||||
|
"price": "hgg",
|
||||||
|
"quantity": null,
|
||||||
|
"checked": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
48
src/app/about/about.component.css
Normal file
48
src/app/about/about.component.css
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 400px;
|
||||||
|
margin: 50px auto;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
form div {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
margin-top: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: red;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 10px 15px;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
background-color: #ccc;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-box {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #007bff;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
48
src/app/about/about.component.html
Normal file
48
src/app/about/about.component.html
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1>Formulaire Réactif</h1>
|
||||||
|
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
|
||||||
|
<div>
|
||||||
|
<label for="nom">Nom :</label>
|
||||||
|
<input id="nom" formControlName="nom" />
|
||||||
|
<span *ngIf="userForm.get('nom')?.invalid && userForm.get('nom')?.touched">
|
||||||
|
Nom requis (minimum 2 caractères).
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="prenom">Prénom :</label>
|
||||||
|
<input id="prenom" formControlName="prenom" />
|
||||||
|
<span *ngIf="userForm.get('prenom')?.invalid && userForm.get('prenom')?.touched">
|
||||||
|
Prénom requis (minimum 2 caractères).
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="adresse">Adresse :</label>
|
||||||
|
<input id="adresse" formControlName="adresse" />
|
||||||
|
<span *ngIf="userForm.get('adresse')?.invalid && userForm.get('adresse')?.touched">
|
||||||
|
Adresse requise.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="email">Email :</label>
|
||||||
|
<input id="email" formControlName="email" />
|
||||||
|
<span *ngIf="userForm.get('email')?.invalid && userForm.get('email')?.touched">
|
||||||
|
Email valide requis.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" [disabled]="userForm.invalid">Identifier</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Div cachée pour afficher les informations -->
|
||||||
|
<div *ngIf="showInfo" class="info-box">
|
||||||
|
<h2>Informations saisies :</h2>
|
||||||
|
<p><strong>Nom :</strong> {{ userInfo?.nom }}</p>
|
||||||
|
<p><strong>Prénom :</strong> {{ userInfo?.prenom }}</p>
|
||||||
|
<p><strong>Adresse :</strong> {{ userInfo?.adresse }}</p>
|
||||||
|
<p><strong>Email :</strong> {{ userInfo?.email }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
23
src/app/about/about.component.spec.ts
Normal file
23
src/app/about/about.component.spec.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AboutComponent } from './about.component';
|
||||||
|
|
||||||
|
describe('AboutComponent', () => {
|
||||||
|
let component: AboutComponent;
|
||||||
|
let fixture: ComponentFixture<AboutComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [AboutComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(AboutComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
33
src/app/about/about.component.ts
Normal file
33
src/app/about/about.component.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-about',
|
||||||
|
templateUrl: './about.component.html',
|
||||||
|
styleUrl: './about.component.css'
|
||||||
|
})
|
||||||
|
export class AboutComponent {
|
||||||
|
userForm: FormGroup;
|
||||||
|
showInfo: boolean = false; // Pour afficher ou cacher la div
|
||||||
|
userInfo: any = null; // Stockage des informations saisies
|
||||||
|
|
||||||
|
constructor(private fb: FormBuilder) {
|
||||||
|
// Initialiser le formulaire
|
||||||
|
this.userForm = this.fb.group({
|
||||||
|
nom: ['', [Validators.required, Validators.minLength(2)]],
|
||||||
|
prenom: ['', [Validators.required, Validators.minLength(2)]],
|
||||||
|
adresse: ['', Validators.required],
|
||||||
|
email: ['', [Validators.required, Validators.email]],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthode pour afficher les données
|
||||||
|
onSubmit() {
|
||||||
|
if (this.userForm.valid) {
|
||||||
|
this.userInfo = this.userForm.value; // Stocker les informations saisies
|
||||||
|
this.showInfo = true; // Afficher la div
|
||||||
|
} else {
|
||||||
|
alert('Veuillez corriger les erreurs dans le formulaire.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
0
src/app/affproduit/affproduit.component.css
Normal file
0
src/app/affproduit/affproduit.component.css
Normal file
1
src/app/affproduit/affproduit.component.html
Normal file
1
src/app/affproduit/affproduit.component.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<p>affproduit works!</p>
|
||||||
23
src/app/affproduit/affproduit.component.spec.ts
Normal file
23
src/app/affproduit/affproduit.component.spec.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { AffproduitComponent } from './affproduit.component';
|
||||||
|
|
||||||
|
describe('AffproduitComponent', () => {
|
||||||
|
let component: AffproduitComponent;
|
||||||
|
let fixture: ComponentFixture<AffproduitComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [AffproduitComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(AffproduitComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
10
src/app/affproduit/affproduit.component.ts
Normal file
10
src/app/affproduit/affproduit.component.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-affproduit',
|
||||||
|
templateUrl: './affproduit.component.html',
|
||||||
|
styleUrl: './affproduit.component.css'
|
||||||
|
})
|
||||||
|
export class AffproduitComponent {
|
||||||
|
|
||||||
|
}
|
||||||
28
src/app/app-routing.module.ts
Normal file
28
src/app/app-routing.module.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { AboutComponent } from './about/about.component';
|
||||||
|
import { ContactsComponent } from './contacts/contacts.component';
|
||||||
|
import { UserComponent } from './user/user.component';
|
||||||
|
import { ProductComponent } from './product/product.component';
|
||||||
|
import { ProductList2Component } from './product-list2/product-list2.component';
|
||||||
|
import { SimpleproduitComponent } from './simpleproduit/simpleproduit.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{ path: 'about', component: AboutComponent },
|
||||||
|
{ path: 'contacts', component: ContactsComponent },
|
||||||
|
{ path: 'user', component: UserComponent },
|
||||||
|
{ path: 'product', component: ProductComponent },
|
||||||
|
{ path: 'product2', component: ProductList2Component },
|
||||||
|
{ path: 'gestprod', component: SimpleproduitComponent },
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
redirectTo: '/about',
|
||||||
|
pathMatch: 'full'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forRoot(routes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class AppRoutingModule { }
|
||||||
0
src/app/app.component.css
Normal file
0
src/app/app.component.css
Normal file
30
src/app/app.component.html
Normal file
30
src/app/app.component.html
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
<nav class="p-3">
|
||||||
|
<ul class="nav nav-pills">
|
||||||
|
<li>
|
||||||
|
<button routerLink="/about" class="btn btn-outline-success ms-1">A propos<i class="bi bi-house text-success"></i></button>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<button routerLink="/contacts" class="btn btn-outline-success ms-1">Contacts<i class="bi bi-arrow-down-up text-success"></i></button>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<button routerLink="/user" class="btn btn-outline-success ms-1">Usert<i class="bi bi-plus-circle text-success"></i></button>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<button routerLink="/product" class="btn btn-outline-success ms-1">Produit<i class="bi bi-plus-circle text-success"></i></button>
|
||||||
|
</li>
|
||||||
|
<!--<li>
|
||||||
|
<button routerLink="/product2" class="btn btn-outline-success ms-1">Produit2<i class="bi bi-plus-circle text-success"></i></button>
|
||||||
|
</li> -->
|
||||||
|
<li>
|
||||||
|
<button routerLink="/product2" class="btn btn-outline-success ms-1">Produit Observable<i class="bi bi-plus-circle text-success"></i></button>
|
||||||
|
</li>
|
||||||
|
<i class="bi bi-airplane" class="btn btn-outline-success ms-1" routerLink="/product2" ></i>
|
||||||
|
<li>
|
||||||
|
<button routerLink="/gestprod" class="btn btn-outline-success ms-1">Gestion Produit<i class="bi bi-app-indicator text-success"></i></button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
35
src/app/app.component.spec.ts
Normal file
35
src/app/app.component.spec.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forRoot([])
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create the app', () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should have as title 'second-app'`, () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app.title).toEqual('second-app');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render title', () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
|
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, second-app');
|
||||||
|
});
|
||||||
|
});
|
||||||
10
src/app/app.component.ts
Normal file
10
src/app/app.component.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrl: './app.component.css'
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'second-app';
|
||||||
|
}
|
||||||
43
src/app/app.module.ts
Normal file
43
src/app/app.module.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { AboutComponent } from './about/about.component';
|
||||||
|
import { ContactsComponent } from './contacts/contacts.component';
|
||||||
|
import { ProductComponent } from './product/product.component';
|
||||||
|
import { UserComponent } from './user/user.component';
|
||||||
|
import { ProductFormComponent } from './product/product-form/product-form.component';
|
||||||
|
import { ProductListComponent } from './product/product-list/product-list.component';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { provideHttpClient } from '@angular/common/http';
|
||||||
|
import { ProductList2Component } from './product-list2/product-list2.component';
|
||||||
|
import { SimpleproduitComponent } from './simpleproduit/simpleproduit.component';
|
||||||
|
import { CategorieComponent } from './categorie/categorie.component';
|
||||||
|
import { AffproduitComponent } from './affproduit/affproduit.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
AboutComponent,
|
||||||
|
ContactsComponent,
|
||||||
|
ProductComponent,
|
||||||
|
UserComponent,
|
||||||
|
ProductFormComponent,
|
||||||
|
ProductListComponent,
|
||||||
|
ProductList2Component,
|
||||||
|
SimpleproduitComponent,
|
||||||
|
CategorieComponent,
|
||||||
|
AffproduitComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
BrowserModule,
|
||||||
|
AppRoutingModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
FormsModule
|
||||||
|
|
||||||
|
],
|
||||||
|
providers: [provideHttpClient()],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
0
src/app/categorie/categorie.component.css
Normal file
0
src/app/categorie/categorie.component.css
Normal file
1
src/app/categorie/categorie.component.html
Normal file
1
src/app/categorie/categorie.component.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<p>categorie works!</p>
|
||||||
23
src/app/categorie/categorie.component.spec.ts
Normal file
23
src/app/categorie/categorie.component.spec.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { CategorieComponent } from './categorie.component';
|
||||||
|
|
||||||
|
describe('CategorieComponent', () => {
|
||||||
|
let component: CategorieComponent;
|
||||||
|
let fixture: ComponentFixture<CategorieComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [CategorieComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(CategorieComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
10
src/app/categorie/categorie.component.ts
Normal file
10
src/app/categorie/categorie.component.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-categorie',
|
||||||
|
templateUrl: './categorie.component.html',
|
||||||
|
styleUrl: './categorie.component.css'
|
||||||
|
})
|
||||||
|
export class CategorieComponent {
|
||||||
|
|
||||||
|
}
|
||||||
0
src/app/contacts/contacts.component.css
Normal file
0
src/app/contacts/contacts.component.css
Normal file
2
src/app/contacts/contacts.component.html
Normal file
2
src/app/contacts/contacts.component.html
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
<h3>Liste de contacts</h3>
|
||||||
|
<button type="button" class="btn btn-secondary" (click)="onClick()">Retour About</button>
|
||||||
23
src/app/contacts/contacts.component.spec.ts
Normal file
23
src/app/contacts/contacts.component.spec.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ContactsComponent } from './contacts.component';
|
||||||
|
|
||||||
|
describe('ContactsComponent', () => {
|
||||||
|
let component: ContactsComponent;
|
||||||
|
let fixture: ComponentFixture<ContactsComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ContactsComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ContactsComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
21
src/app/contacts/contacts.component.ts
Normal file
21
src/app/contacts/contacts.component.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-contacts',
|
||||||
|
templateUrl: './contacts.component.html',
|
||||||
|
styleUrl: './contacts.component.css'
|
||||||
|
})
|
||||||
|
export class ContactsComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor(private route: Router){}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick() {
|
||||||
|
this.route.navigate(['about']);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
7
src/app/model/product.model.ts
Normal file
7
src/app/model/product.model.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export interface Product {
|
||||||
|
id : number,
|
||||||
|
name : string,
|
||||||
|
price : number,
|
||||||
|
quantity : number,
|
||||||
|
checked : boolean
|
||||||
|
}
|
||||||
0
src/app/product-list2/product-list2.component.css
Normal file
0
src/app/product-list2/product-list2.component.css
Normal file
1
src/app/product-list2/product-list2.component.html
Normal file
1
src/app/product-list2/product-list2.component.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<p *ngFor="let product of listesProduits">{{product.name}} : {{product.price}}</p>
|
||||||
23
src/app/product-list2/product-list2.component.spec.ts
Normal file
23
src/app/product-list2/product-list2.component.spec.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ProductList2Component } from './product-list2.component';
|
||||||
|
|
||||||
|
describe('ProductList2Component', () => {
|
||||||
|
let component: ProductList2Component;
|
||||||
|
let fixture: ComponentFixture<ProductList2Component>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ProductList2Component]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ProductList2Component);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
48
src/app/product-list2/product-list2.component.ts
Normal file
48
src/app/product-list2/product-list2.component.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Product } from '../model/product.model';
|
||||||
|
import { ProductService } from '../services/product.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-product-list2',
|
||||||
|
templateUrl: './product-list2.component.html',
|
||||||
|
styleUrl: './product-list2.component.css'
|
||||||
|
})
|
||||||
|
export class ProductList2Component implements OnInit {
|
||||||
|
listesProduits: Product[] = [];
|
||||||
|
produitSelectionne: Product | null = null;
|
||||||
|
|
||||||
|
constructor(private productService:ProductService){}
|
||||||
|
ngOnInit(): void {
|
||||||
|
|
||||||
|
//Méthode 1
|
||||||
|
// this.getProducts();
|
||||||
|
|
||||||
|
//Méthode 2
|
||||||
|
/*this.productService.getProduits2().subscribe(data => {
|
||||||
|
this.listesProduits = data;
|
||||||
|
});*/
|
||||||
|
|
||||||
|
//Methode 3
|
||||||
|
this.productService.getProduits2().subscribe({
|
||||||
|
|
||||||
|
next: (productsList) => {
|
||||||
|
this.listesProduits = productsList;
|
||||||
|
},
|
||||||
|
error: (error) => {
|
||||||
|
console.log('http error: ', error)
|
||||||
|
},
|
||||||
|
complete:() => {
|
||||||
|
console.log('Traitement finie')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
getProducts(){
|
||||||
|
this.listesProduits = this.productService.getProduits();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
0
src/app/product/product-form/product-form.component.css
Normal file
0
src/app/product/product-form/product-form.component.css
Normal file
35
src/app/product/product-form/product-form.component.html
Normal file
35
src/app/product/product-form/product-form.component.html
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<div class="p-3">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<form [formGroup]="productForm" (ngSubmit)="onSubmit()" >
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Name</label>
|
||||||
|
<input class="form-control" formControlName="name">
|
||||||
|
<span *ngIf="productForm.get('name')?.invalid && productForm.get('name')?.touched">
|
||||||
|
<span id="message-error" class="text-danger"> Le nom du produit est obligatoire !</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Price</label>
|
||||||
|
<input class="form-control" formControlName="price">
|
||||||
|
<span *ngIf="productForm.get('price')?.invalid && productForm.get('price')?.touched">
|
||||||
|
<span id="message-error" class="text-danger"> Le prix du produit est obligatoire !</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Quantity</label>
|
||||||
|
<input class="form-control" formControlName="price">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Checked</label>
|
||||||
|
<input type="checkbox" class="form-check-input" formControlName="checked">
|
||||||
|
</div>
|
||||||
|
<button [disabled]="productForm.invalid" class="btn btn-success">Save</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
23
src/app/product/product-form/product-form.component.spec.ts
Normal file
23
src/app/product/product-form/product-form.component.spec.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ProductFormComponent } from './product-form.component';
|
||||||
|
|
||||||
|
describe('ProductFormComponent', () => {
|
||||||
|
let component: ProductFormComponent;
|
||||||
|
let fixture: ComponentFixture<ProductFormComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ProductFormComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ProductFormComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
58
src/app/product/product-form/product-form.component.ts
Normal file
58
src/app/product/product-form/product-form.component.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
|
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { Product } from '../../model/product.model';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-product-form',
|
||||||
|
templateUrl: './product-form.component.html',
|
||||||
|
styleUrl: './product-form.component.css'
|
||||||
|
})
|
||||||
|
export class ProductFormComponent implements OnInit{
|
||||||
|
public productForm!:FormGroup;
|
||||||
|
@Input()
|
||||||
|
product: Product | null = null;
|
||||||
|
|
||||||
|
// <app-product-form [product]="valeurProvenantDuParent de type Product" (productPopulated)="Attend une fonction"></app-product-form>
|
||||||
|
|
||||||
|
/*@Output()
|
||||||
|
productPopulated: EventEmitter<Product> = new EventEmitter<Product>();*/
|
||||||
|
|
||||||
|
@Output() addProduit = new EventEmitter<Product>(); //@output permet de renvoyer les données du formulaire vers le composant parent
|
||||||
|
|
||||||
|
// Le composant parent gère la logique de l'application : il récupère les produits du service, les passe aux composants enfants, et réagit aux événements émis par ces derniers.
|
||||||
|
|
||||||
|
|
||||||
|
constructor(private fb: FormBuilder, private router: Router) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
//Peut être initialisé dans le constructeur
|
||||||
|
this.productForm=this.fb.group({
|
||||||
|
name : this.fb.control('', [Validators.required]),
|
||||||
|
price : this.fb.control('',[Validators.required, Validators.min(5)]),
|
||||||
|
quantity : this.fb.control(0,),
|
||||||
|
checked : this.fb.control(false),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.product) {
|
||||||
|
this.productForm.patchValue(this.product);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*onSubmit(): void {
|
||||||
|
if (this.productForm.valid) {
|
||||||
|
this.productPopulated.emit(this.productForm.value);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
if (this.productForm.valid) {
|
||||||
|
this.addProduit.emit(this.productForm.value);
|
||||||
|
this.productForm.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveProduct(): void {
|
||||||
|
console.log(this.productForm.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
0
src/app/product/product-list/product-list.component.css
Normal file
0
src/app/product/product-list/product-list.component.css
Normal file
46
src/app/product/product-list/product-list.component.html
Normal file
46
src/app/product/product-list/product-list.component.html
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
<div class="p-3">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-body">
|
||||||
|
<div>
|
||||||
|
<input class="p-1" type="text" [(ngModel)]="searchValue" placeholder="Rechercher un produit par nom..." >
|
||||||
|
<button (click)="onSearch()"
|
||||||
|
class="btn btn-outline-success ms-1">
|
||||||
|
<i class="bi bi-search"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <p *ngFor="let user of myUsers">{{user.name}} : {{user.age}}</p>
|
||||||
|
<pre>{{users.length}}</pre>users!!!
|
||||||
|
<pre>{{products.length}}</pre>products!!! -->
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th> <th>Price</th> <th>Quantity</th> <th>Checked</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let product of products ">
|
||||||
|
<td>{{product.name}}</td>
|
||||||
|
<td>{{product.price}}</td>
|
||||||
|
<td>{{product.quantity}}</td>
|
||||||
|
<td>
|
||||||
|
<button (click)="onToggleDisponibilite(product)"
|
||||||
|
class="btn btn-outline-success">
|
||||||
|
<i [class]="product.checked?'bi bi-check':'bi bi-circle'"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button (click)="onDelete(product)" class="btn btn-outline-danger">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr *ngIf="products.length === 0 && searchValue.length > 0">
|
||||||
|
<p>Aucun produit trouvé pour "{{ searchValue }}"</p>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
23
src/app/product/product-list/product-list.component.spec.ts
Normal file
23
src/app/product/product-list/product-list.component.spec.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ProductListComponent } from './product-list.component';
|
||||||
|
|
||||||
|
describe('ProductListComponent', () => {
|
||||||
|
let component: ProductListComponent;
|
||||||
|
let fixture: ComponentFixture<ProductListComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ProductListComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ProductListComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
40
src/app/product/product-list/product-list.component.ts
Normal file
40
src/app/product/product-list/product-list.component.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||||
|
import { Product } from '../../model/product.model';
|
||||||
|
import { ProductService } from '../../services/product.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-product-list',
|
||||||
|
templateUrl: './product-list.component.html',
|
||||||
|
styleUrl: './product-list.component.css'
|
||||||
|
})
|
||||||
|
export class ProductListComponent implements OnInit {
|
||||||
|
|
||||||
|
//Le composant list-produit reçoit une liste de produits via @Input et émet des événements
|
||||||
|
// lorsqu'un produit doit être modifié ou supprimé via @Output
|
||||||
|
|
||||||
|
@Input() products: Product[] = [];
|
||||||
|
@Output() deleteProduit = new EventEmitter<Product>();
|
||||||
|
@Output() toggleDisponibilite = new EventEmitter<Product>();
|
||||||
|
@Output() searchProduct = new EventEmitter<string>()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
searchValue: string = '';
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
onDelete(product: Product) {
|
||||||
|
this.deleteProduit.emit(product);
|
||||||
|
}
|
||||||
|
|
||||||
|
onToggleDisponibilite(product: Product) {
|
||||||
|
this.toggleDisponibilite.emit(product);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearch() {
|
||||||
|
this.searchProduct.emit(this.searchValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {}
|
||||||
|
|
||||||
|
}
|
||||||
0
src/app/product/product.component.css
Normal file
0
src/app/product/product.component.css
Normal file
11
src/app/product/product.component.html
Normal file
11
src/app/product/product.component.html
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<app-product-form
|
||||||
|
[product]="produitSelectionne"
|
||||||
|
(addProduit)="onAddProduit($event)"
|
||||||
|
></app-product-form>
|
||||||
|
<app-product-list
|
||||||
|
[products]="listesProduits"
|
||||||
|
(deleteProduit)="onDeleteProduit($event)"
|
||||||
|
(toggleDisponibilite)="onToggleDisponibilite($event)"
|
||||||
|
(searchProduct)="onSearchProduit($event)"
|
||||||
|
>
|
||||||
|
</app-product-list>
|
||||||
23
src/app/product/product.component.spec.ts
Normal file
23
src/app/product/product.component.spec.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ProductComponent } from './product.component';
|
||||||
|
|
||||||
|
describe('ProductComponent', () => {
|
||||||
|
let component: ProductComponent;
|
||||||
|
let fixture: ComponentFixture<ProductComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ProductComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ProductComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
91
src/app/product/product.component.ts
Normal file
91
src/app/product/product.component.ts
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Product } from '../model/product.model';
|
||||||
|
import { ProductService } from '../services/product.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-product',
|
||||||
|
templateUrl: './product.component.html',
|
||||||
|
styleUrl: './product.component.css'
|
||||||
|
})
|
||||||
|
export class ProductComponent implements OnInit {
|
||||||
|
|
||||||
|
//Le composant parent gère la logique de l'application : il récupère les produits du service, les passe aux composants enfants,
|
||||||
|
// et réagit aux événements émis par ces derniers.
|
||||||
|
|
||||||
|
listesProduits: Product[] = [];
|
||||||
|
produitSelectionne: Product | null = null;
|
||||||
|
|
||||||
|
constructor(private productService:ProductService){}
|
||||||
|
ngOnInit(): void {
|
||||||
|
///this.getProducts();
|
||||||
|
|
||||||
|
this.productService.getProduits2().subscribe(data => {
|
||||||
|
this.listesProduits = data;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
/*this.productService.getProduits2().subscribe({
|
||||||
|
|
||||||
|
next: (productsList) => {
|
||||||
|
this.listesProduits = productsList;
|
||||||
|
},
|
||||||
|
error: (error) => {
|
||||||
|
console.log('http error: ', error)
|
||||||
|
},
|
||||||
|
complete:() => {
|
||||||
|
console.log('Traitement finie')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
);*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**/
|
||||||
|
|
||||||
|
|
||||||
|
//this.productService.recupProduits().subscribe(data => (this.listesProduits = data));
|
||||||
|
|
||||||
|
|
||||||
|
//this.loadProducts();
|
||||||
|
}
|
||||||
|
|
||||||
|
getProducts(){
|
||||||
|
this.listesProduits = this.productService.getProduits();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadProducts(): void {
|
||||||
|
this.productService.recupProduits().subscribe(data => (this.listesProduits = data));
|
||||||
|
}
|
||||||
|
|
||||||
|
onAddProduit(produit: Product) {
|
||||||
|
this.productService.ajouterProduit(produit);
|
||||||
|
}
|
||||||
|
|
||||||
|
onAddProduitAutre(produit: Product): void {
|
||||||
|
this.productService.addProduct(produit).subscribe(() => {
|
||||||
|
// this.productAdded.emit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onDeleteProduit(product: Product) {
|
||||||
|
this.productService.supprimerProduit(product.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
onToggleDisponibilite(product: Product) {
|
||||||
|
this.productService.recupererProduitParId(product.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchProduitInit(name: string) {
|
||||||
|
this.productService.searchProduit(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchProduit(name: string) {
|
||||||
|
this.listesProduits = this.productService.rechercherProduit(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchProduit1(name: string) {
|
||||||
|
this.productService.searchProduit(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
16
src/app/services/mon-service.service.spec.ts
Normal file
16
src/app/services/mon-service.service.spec.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MonServiceService } from './mon-service.service';
|
||||||
|
|
||||||
|
describe('MonServiceService', () => {
|
||||||
|
let service: MonServiceService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(MonServiceService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
9
src/app/services/mon-service.service.ts
Normal file
9
src/app/services/mon-service.service.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class MonServiceService {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
}
|
||||||
16
src/app/services/product.service.spec.ts
Normal file
16
src/app/services/product.service.spec.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ProductService } from './product.service';
|
||||||
|
|
||||||
|
describe('ProductService', () => {
|
||||||
|
let service: ProductService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(ProductService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
132
src/app/services/product.service.ts
Normal file
132
src/app/services/product.service.ts
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Product } from '../model/product.model';
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class ProductService {
|
||||||
|
|
||||||
|
produits: Product[] = [
|
||||||
|
{ id: 1, name: 'Produit 1', price: 100, quantity: 5, checked: true },
|
||||||
|
{ id: 2, name: 'Produit 2', price: 200, quantity: 5, checked: false },
|
||||||
|
{ id: 3, name: 'Produit 3', price: 300, quantity: 5, checked: true },
|
||||||
|
{ id: 4, name: 'Produit 4', price: 400, quantity: 5, checked: false },
|
||||||
|
{ id: 5, name: 'Produit 5', price: 500, quantity: 5, checked: true },
|
||||||
|
{ id: 6, name: 'Produit 6', price: 600, quantity: 5, checked: false },
|
||||||
|
{ id: 7, name: 'Produit 7', price: 700, quantity: 5, checked: true },
|
||||||
|
{ id: 8, name: 'Produit 8', price: 800, quantity: 5, checked: false },
|
||||||
|
{ id: 9, name: 'Produit 9', price: 900, quantity: 5, checked: true },
|
||||||
|
{ id: 10, name: 'Produit 10', price: 1000, quantity: 5, checked: false },
|
||||||
|
];
|
||||||
|
|
||||||
|
private productUrl = 'http://localhost:3600/produits';
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
recupProduits(): Observable<Product[]> {
|
||||||
|
return this.http.get<Product[]>(this.productUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
addProduit(produit: Product): Observable<Product> {
|
||||||
|
return this.http.post<Product>(this.productUrl, produit);
|
||||||
|
}
|
||||||
|
|
||||||
|
addProduct(produit: Product): Observable<Product> {
|
||||||
|
return this.http.post<Product>(this.productUrl, produit);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProduct(produit: Product): Observable<Product> {
|
||||||
|
return this.http.put<Product>(`${this.productUrl}/${produit.id}`, produit);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private produitsSubject = new BehaviorSubject<Product[]>(this.produits);
|
||||||
|
|
||||||
|
//private produitsSubject = new BehaviorSubject<Product[]>(this.productUrl);
|
||||||
|
private productsSubject = new BehaviorSubject<Product[]>([]);
|
||||||
|
public products$ = this.productsSubject.asObservable();
|
||||||
|
|
||||||
|
private loadProducts(): void {
|
||||||
|
this.http.get<Product[]>(this.productUrl)
|
||||||
|
.subscribe((products) => this.productsSubject.next(products));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtenir les produits
|
||||||
|
getProducts(): Observable<Product[]> {
|
||||||
|
return this.products$;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ajouter un produit
|
||||||
|
addProduct2(product: Product): void {
|
||||||
|
const current = this.productsSubject.getValue();
|
||||||
|
const updated = [...current, product];
|
||||||
|
this.productsSubject.next(updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mettre à jour un produit
|
||||||
|
updateProduct2(updatedProduct: Product): void {
|
||||||
|
const current = this.productsSubject.getValue();
|
||||||
|
const updated = current.map(p => p.id === updatedProduct.id ? updatedProduct : p);
|
||||||
|
this.productsSubject.next(updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Récupérer tous les produits
|
||||||
|
getProduits(): Product[] {
|
||||||
|
return this.produits;
|
||||||
|
//return this.produitsSubject.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
getProduits2(): Observable<Product[]> {
|
||||||
|
return this.produitsSubject.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ajouter un produit
|
||||||
|
ajouterProduit(produit: Product): void {
|
||||||
|
produit.id = this.produits.length + 1;
|
||||||
|
this.produits.push(produit);
|
||||||
|
this.produitsSubject.next(this.produits);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supprimer un produit par son id
|
||||||
|
supprimerProduit(id: number): void {
|
||||||
|
this.produits = this.produits.filter((produit) => produit.id !== id);
|
||||||
|
this.produitsSubject.next(this.produits);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rechercher un produit par nom
|
||||||
|
rechercherProduitParNom(nom: string): Product | undefined {
|
||||||
|
return this.produits.find((produit) => produit.name.toLowerCase() === nom.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
rechercherProduit(nom: string): Product[] {
|
||||||
|
return this.produits.filter(produit =>
|
||||||
|
produit.name.toLowerCase().includes(nom.toLowerCase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
searchProduit(name: string) {
|
||||||
|
const filteredProduits = this.produits.filter(p => p.name.toLowerCase().includes(name.toLowerCase()));
|
||||||
|
this.produitsSubject.next(filteredProduits);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProduit(produit: Product): void {
|
||||||
|
const index = this.produits.findIndex(p => p.id === produit.id);
|
||||||
|
if (index !== -1) {
|
||||||
|
this.produits[index] = produit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Récupérer un produit par son id
|
||||||
|
recupererProduitParId(id: number): Product | undefined {
|
||||||
|
//const filteredProduits = this.produits.filter(p => p.name.toLowerCase().includes(name.toLowerCase()));
|
||||||
|
return this.produits.find((produit) => produit.id === id);
|
||||||
|
//this.produitsSubject.next(filteredProduits);
|
||||||
|
}
|
||||||
|
|
||||||
|
searchProduitByName(name: string): Observable<Product[]> {
|
||||||
|
return this.http.get<Product[]>(`${this.productUrl}?name_like=${name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/app/services/product2.service.spec.ts
Normal file
16
src/app/services/product2.service.spec.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { Product2Service } from './product2.service';
|
||||||
|
|
||||||
|
describe('Product2Service', () => {
|
||||||
|
let service: Product2Service;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(Product2Service);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
34
src/app/services/product2.service.ts
Normal file
34
src/app/services/product2.service.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Product } from '../model/product.model';
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class Product2Service {
|
||||||
|
|
||||||
|
private productUrl = 'http://localhost:3000/products'; // URL de l'API ou de JSON Server
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
// Méthode pour récupérer tous les produits
|
||||||
|
getProducts(): Observable<Product[]> {
|
||||||
|
return this.http.get<Product[]>(this.productUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthode pour ajouter un produit
|
||||||
|
addProduct(product: Product): Observable<Product> {
|
||||||
|
return this.http.post<Product>(this.productUrl, product);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthode pour mettre à jour un produit
|
||||||
|
updateProduct(product: Product): Observable<Product> {
|
||||||
|
return this.http.put<Product>(`${this.productUrl}/${product.id}`, product);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Méthode pour supprimer un produit
|
||||||
|
deleteProduct(id: number): Observable<void> {
|
||||||
|
return this.http.delete<void>(`${this.productUrl}/${id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
0
src/app/simpleproduit/simpleproduit.component.css
Normal file
0
src/app/simpleproduit/simpleproduit.component.css
Normal file
43
src/app/simpleproduit/simpleproduit.component.html
Normal file
43
src/app/simpleproduit/simpleproduit.component.html
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
<div class="p-3">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-body">
|
||||||
|
<div>
|
||||||
|
<input class="p-1" type="text" [(ngModel)]="searchValue" placeholder="Rechercher un produit par nom..." >
|
||||||
|
<button (click)="onSearch()"
|
||||||
|
class="btn btn-outline-success ms-1">
|
||||||
|
<i class="bi bi-search"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th> <th>Price</th> <th>Quantity</th> <th>Checked</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr *ngFor="let product of listesProduits ">
|
||||||
|
<td>{{product.name}}</td>
|
||||||
|
<td>{{product.price}}</td>
|
||||||
|
<td>{{product.quantity}}</td>
|
||||||
|
<td>
|
||||||
|
<button (click)="onToggleDisponibilite(product)"
|
||||||
|
class="btn btn-outline-success">
|
||||||
|
<i [class]="product.checked?'bi bi-check':'bi bi-circle'"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button (click)="onDeleteProduit(product)" class="btn btn-outline-danger">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr *ngIf="listesProduits.length === 0 && searchValue.length > 0">
|
||||||
|
<p>Aucun produit trouvé pour "{{ searchValue }}"</p>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
23
src/app/simpleproduit/simpleproduit.component.spec.ts
Normal file
23
src/app/simpleproduit/simpleproduit.component.spec.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SimpleproduitComponent } from './simpleproduit.component';
|
||||||
|
|
||||||
|
describe('SimpleproduitComponent', () => {
|
||||||
|
let component: SimpleproduitComponent;
|
||||||
|
let fixture: ComponentFixture<SimpleproduitComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [SimpleproduitComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(SimpleproduitComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
51
src/app/simpleproduit/simpleproduit.component.ts
Normal file
51
src/app/simpleproduit/simpleproduit.component.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Product } from '../model/product.model';
|
||||||
|
import { ProductService } from '../services/product.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-simpleproduit',
|
||||||
|
templateUrl: './simpleproduit.component.html',
|
||||||
|
styleUrl: './simpleproduit.component.css'
|
||||||
|
})
|
||||||
|
export class SimpleproduitComponent implements OnInit {
|
||||||
|
|
||||||
|
searchValue: string = '';
|
||||||
|
|
||||||
|
listesProduits: Product[] = [];
|
||||||
|
produitSelectionne: Product | null = null;
|
||||||
|
|
||||||
|
constructor(private productService:ProductService){}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.getProducts()
|
||||||
|
}
|
||||||
|
|
||||||
|
getProducts(){
|
||||||
|
this.listesProduits = this.productService.getProduits();
|
||||||
|
}
|
||||||
|
|
||||||
|
onAddProduit(produit: Product) {
|
||||||
|
this.productService.ajouterProduit(produit);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDeleteProduit(product: Product) {
|
||||||
|
this.productService.supprimerProduit(product.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
onToggleDisponibilite(product: Product) {
|
||||||
|
this.productService.recupererProduitParId(product.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchProduitInit(name: string) {
|
||||||
|
this.productService.searchProduit(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearch() {
|
||||||
|
this.listesProduits = this.productService.rechercherProduit(this.searchValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchProduit1(name: string) {
|
||||||
|
this.productService.searchProduit(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
0
src/app/user/user.component.css
Normal file
0
src/app/user/user.component.css
Normal file
1
src/app/user/user.component.html
Normal file
1
src/app/user/user.component.html
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<p>user works!</p>
|
||||||
23
src/app/user/user.component.spec.ts
Normal file
23
src/app/user/user.component.spec.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { UserComponent } from './user.component';
|
||||||
|
|
||||||
|
describe('UserComponent', () => {
|
||||||
|
let component: UserComponent;
|
||||||
|
let fixture: ComponentFixture<UserComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [UserComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(UserComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
10
src/app/user/user.component.ts
Normal file
10
src/app/user/user.component.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-user',
|
||||||
|
templateUrl: './user.component.html',
|
||||||
|
styleUrl: './user.component.css'
|
||||||
|
})
|
||||||
|
export class UserComponent {
|
||||||
|
|
||||||
|
}
|
||||||
13
src/index.html
Normal file
13
src/index.html
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>SecondApp</title>
|
||||||
|
<base href="/">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root></app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
8
src/main.ts
Normal file
8
src/main.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
||||||
|
import { AppModule } from './app/app.module';
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule, {
|
||||||
|
ngZoneEventCoalescing: true
|
||||||
|
})
|
||||||
|
.catch(err => console.error(err));
|
||||||
9
src/produit.json
Normal file
9
src/produit.json
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"produits": [
|
||||||
|
{ "id": 1, "nom": "Produit 1", "quantite": 10, "disponibilite": true },
|
||||||
|
{ "id": 2, "nom": "Produit 2", "quantite": 15, "disponibilite": false },
|
||||||
|
{ "id": 3, "nom": "Produit 3", "quantite": 20, "disponibilite": true },
|
||||||
|
{ "id": 4, "nom": "Produit 4", "quantite": 5, "disponibilite": true },
|
||||||
|
{ "id": 5, "nom": "Produit 5", "quantite": 12, "disponibilite": false }
|
||||||
|
]
|
||||||
|
}
|
||||||
7
src/styles.css
Normal file
7
src/styles.css
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
/* You can add global styles to this file, and also import other style files */
|
||||||
|
|
||||||
|
/*@import 'bootstrap/dist/css/bootstrap.min.css';*/
|
||||||
|
|
||||||
|
@import "bootstrap-icons/font/bootstrap-icons.css";
|
||||||
|
|
||||||
|
|
||||||
15
tsconfig.app.json
Normal file
15
tsconfig.app.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||||
|
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./out-tsc/app",
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/main.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"src/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
33
tsconfig.json
Normal file
33
tsconfig.json
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||||
|
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./dist/out-tsc",
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"declaration": false,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"importHelpers": true,
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "ES2022",
|
||||||
|
"lib": [
|
||||||
|
"ES2022",
|
||||||
|
"dom"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"enableI18nLegacyMessageIdFormat": false,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"strictInputAccessModifiers": true,
|
||||||
|
"strictTemplates": true
|
||||||
|
}
|
||||||
|
}
|
||||||
15
tsconfig.spec.json
Normal file
15
tsconfig.spec.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
|
||||||
|
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
|
||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./out-tsc/spec",
|
||||||
|
"types": [
|
||||||
|
"jasmine"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue