Compare commits

...

13 Commits

Author SHA1 Message Date
Guillaume-Sanchez 1abcfc9c4c UE2.24 TP5 fini 2026-07-02 16:09:23 +02:00
Guillaume-Sanchez d052ad4b52 UE2.24 - Mise a jour TP4 et TP3 2026-06-30 09:45:18 +02:00
Guillaume-Sanchez 5d81b0dbb0 UE2.24 - TP3 Fini, TP4 Fini, TP5 en cours 2026-06-29 15:22:32 +02:00
Guillaume-Sanchez 6e5f833d57 UE2.24 - Ajout du TP2 2026-06-22 16:17:29 +02:00
Guillaume-Sanchez f36f645e8c UE2.24 TP1 final 2026-06-22 12:20:43 +02:00
Guillaume-Sanchez ace040a012 UE2.24 TP1 2026-06-22 10:58:11 +02:00
Guillaume-Sanchez f56a2e7fb6 UE2.24 TP1 2026-06-22 10:57:41 +02:00
Guillaume-Sanchez 5228365299 UE2.18 du 04 06 2026 2026-06-04 16:30:50 +02:00
Guillaume-Sanchez d79cf4c160 UE2.34 du 03/06/26 2026-06-04 13:57:00 +02:00
Guillaume-Sanchez 608508a155 UE2.35 Atelier 5 2026-06-02 16:26:09 +02:00
Guillaume-Sanchez e8610c0033 Mise à jour du cahier d'apprentissage et ajout de l'adresse proxmox 2026-06-02 16:25:30 +02:00
Guillaume-Sanchez b47b173b94 Mois de mai du Cahier d'apprentissage 2026-05-28 16:35:13 +02:00
Guillaume-Sanchez c41a9289c7 UE2.16 du 28 05 2026 2026-05-28 16:33:52 +02:00
48 changed files with 789 additions and 9 deletions
+14 -2
View File
@@ -90,5 +90,17 @@ Soutenange-creation-entreprise : Mise en place des groupe et création des compt
- UE2.33 - Analyse des vulnérabilités, menaces logicielles et sécurisation : Préparation oral et présentation oral de projet
- UE2.11 - Mathématiques : Présentation projet R
- UE2.34 - Analyse de la securite des reseaux : Webinaire et continuité du cours
- UE2.12 - Managements_des_projets_risque : Initiation a Google console pour la gestion des lab DevOps
- UE2.35 - Analyse_de_la_securite_des_accès : 2 Examens sur le lab de l'AD Windows server 2022
- UE2.12 - Managements_des_projets_risque : Initiation a Google console pour la gestion des lab DevOps, Mise en place du repo GitHub build d'une image docker et push sur docker hub, Mise en place des branch et pull request qui declanche un CI (action.yml).
- UE2.35 - Analyse_de_la_securite_des_accès : 2 Examens sur le lab de l'AD Windows server 2022, TP Sécurisation Avancée AD DS
- UE2.16 - Droit, Propriété industrielle : Droit et propriété industrielle, brevet etc cas pratique AutoTech, Controle de fin de module.
# Juin
- UE2.14_Management_interculturel : Cours Magitral Notions clés, Enjeux, Prise en compte du MI dans les pratiques manageriales de lentreprise. Exercice pratique de groupe poir deja appréhender lexamen qui est deja en approche.
- UE2.35 - Suite et fin TP Sécurisation Avancée AD DS, Les protocole RADIUS.
- UE2.34 - Analyse de la securite des reseaux : TP SNORT, installation, utilisation envoie de paquet avec scapy.
- UE2.10 - Anglais : Exercice sur le travail en groupe et cas pratique sur la gestion d'équipe.
- UE2.18 - Communication Marketing : Etude de marché, offre et demande.
- UE2.6 - Activités Professionnelles : HACHATON.
- UE2.24 - Systèmes distribués et applications sous Windows et Linux : TP1 Mise en place d'un systeme distribués simple pour trouver un hash md5. TP2 Mise en place dun Load Balancer avec Nginx
+12
View File
@@ -22,6 +22,18 @@ Sept 2025 Setp 2026 -> Contrôle continu, pas de partiel
- Juillet : entrepreneuriat (en Groupe, orienté technique en français)
- Septembre : activité Pro (individuelle en français)
## Accès proxmox :
[https://10.25.32.74:8006](https://10.25.32.74:8006)
## Organisation Année pro :
- 21 Septembre 2026 reprise des cours
- 24 ou 25 septembre 2026 soutenance
- Partiel semaine du 1er février 2027
- Semaine du 28 juin 2027 toeic partiel soutenance
- Septembre 16 et 17 septembre 2027 2 soutenances
## Connexion à Pedagogie CCI sur Linux Récent
Pour ce connecter avec un linux à la Wifi Pedagogie CCI
+75
View File
@@ -0,0 +1,75 @@
# UE2.14_Management_interculturel
## Introdcution
- Le management culturel :
C'est parce que l'homme se déplace, et il se déplace mtn vite.
La mondialisation / globalisation -> c'est le procéssus qui consiste grace à **l'accélération des echanges**, du à **la modernisation des moyens de transport et de communication** de rendre intéligents les economies.
L'entreprise avait des habitudes de fonctionnement, des habitudes de management et désormais, il faut prendre en compte les cultures multiples dans le management qui est executé en entreprise.
- Notions clé :
-> Management
-> Management interculturel
-> culture / cultures
-> Mondiaisation
-> Captiliste
-> Civilisation
### I - Le concepte management culturel (MI)
C'est la manière dont on va gérer, diriger, accompagner des colaborateurs, des équipes en tenant compte de leur différences d'origine, de leur echelles de valeur, de manière général de leur culture afin d'en faire une force pour bien former l'entreprise.
#### A - L'appréention de la notion
Qu'est ce qui fait de nous un être culturel :
- les origines
- la position
- Faculté d'adaptation
- Je pense donc je suis
- Le contact avec les autres
- l'éduction
- L'inteligence
- Aquerir des compétences
- La langue
- l'age
Une entreprise multiculturel l'est car elle à pour vocation de souvrir à l'internationnal.
Le management interculturel trouve son encrage des les entreprise à vocation international.
Qu'est ce qui fait faire qu'une entreprise pratique un MI
-
-
-
-
#### B - Les enjeux du management interculturel
| Enjeux | Crarctéristiques | Illustrations |
|:---:|:---|:---|
| Organisation | Le fait que l'on puisse devoir s'adapter à des différents et aux quel les salariés sur place pratiquent et qui peuvent "choquer" des salariés étrangés.| Les horraires |
| Performance | Les attentes peuvent être beaucoup plus élevés dans certains pays. | La chine |
| D'innovation | Avec le MI la course à l'innovation est un aspect prononcé car le groupe interculturel doit tiers vers l'augmentation en matière de R&D | Département d'inovation des entreprise des jeux vidéos |
| Communication | 1. Savoir adapter sa communication idividuelle et collective. 2. Savoir prévenir et gérer les conflit interculturels. 3. Une communication inadapter peut etre source de conflit et de tention au sein des équipes entre des membres des équipes | Le fait de ne pas manier une langue commune (Notamment l'anglais) donc de ne pas transmettre les informations correctement pour tous les menbres de l'équipe. Autre exemple les dommes de chaleur ou de froid (srilanca ou alasca)|
| Managearial des ressources humaines | 1. Optimisation des compétences avec des collaborateurs / équipe multiculturelles 2. Savoir faire de la bonne écoute 3. Anticiper d'éventelle malaises. 4. Assurer la bonne cohésion d'équipe | Team bulding, |
Définition de l'Arousée
Enjeux gains et que l'on connait l'art d'une
#### étude de cas : A faire :
- Une étude analytique du management dans le pays, la region retenu.
- Faire un comparatif avec le management Français.
- Combienez les 2 et proposer des améliorations en vue d'un MI Pour cela -> création d'une multinational sous banière française, lesp oint négatifs et les difficultés, les solutions managearial faire du multiculturaliseme un ett pour la société.
Pays retenu, la Turiquie :
https://www.inter-ligere.fr/reseaux-humains-interculturel-la-turquie/
https://cadran.pro/management-interculturel-turquie/
@@ -0,0 +1,25 @@
# 1)
Pour bénéficier de cette protection des droits d'auteur DataStream doit remplir 2 conditions :
Originalité grâce à son architecture modulaire originale
Mise en forme il faut que l'oeuvre soit concrétisée fixer sur un support (code source écrit par les devs)
# 2)
Dans le cas de TechCloud les développeurs de datastream ne possèdent pas les droits patrimoniaux sur le logiciel techcloud détient automatiquement tous les droits patrimoniaux sur datastream
# 3)
Les dev conservent 4 prérogatives essentielles
Le droit à la paternité
Le droit à la divulgation
Le droit au respect de l'œuvre
Le droit de retrait ou de repentir
# 4)
TechCloud peut commercialiser sans l'accord des dev car il possède les droits patrimoniaux, Techcloud devrait faire signer une clause de confidentialité et de préciser que toute création intellectuelle réalisée dans le cadre de leur fonction appartient à l'entreprise
# 5)
TechCloud devrait déposer le nom de domaine ou la marque de datastream à l'INPI
@@ -0,0 +1,17 @@
# étude de cas section 5 autoTech
## 1)
L'invention de Sophie doit être qualifié d'invention or mission attribuable à l'entreprise, en raison du lien mnifeste avec le dommaine d'activité d'AutoTech et de l'utilisation problable des connaissance technique aquise dans le cadre de son emploie.
Sophie à conçu et développé son invention or de sa mission.
## 2)
Sophie est la titulaire initiale de l'invention mais son employeur autotech peut exercer son droit d'attribution des droits d'exploitation, autotech devra verser à Sophie une contrepartie d'un montant équivalent à 2 à 6 mois du salaire brut
## 3)
Si Sophie dépose un brevet à son nom sans avoir préalablement déclaré cela autotech cela mènera à plusieurs fautes la première étant la violation de l'obligation légale de déclaration, seconde faute étant le risque d'usurpation du titre c'est à dire que l'employeur peut revendiquer le brevet et contester la titularité du titre
## 4)
Il y a 3 forme de rémunération potentielles, il y a la forme forfaitaire unique (prime), un pourcentage sur le chiffre d'affaire généré (royalties), la combinaison des payements échelonnés scénario 2 si autotech ne manifeste pas son droit d'attribution dans un délai de 4 mois Sophie conserve la pleine titularité de l'invention.
@@ -1,7 +0,0 @@
# 03 04 2026
<details><summary>Info prof</summary>
<pre>
Mr Kalonji Jean.Claude - jean-claude.Kalonji@seineetmarne.cci.fr</pre>
</details>
+14
View File
@@ -0,0 +1,14 @@
# UE2.18 Communication Marketing
## 03 04 2026
<details><summary>Info prof</summary>
<pre>
Mr Kalonji Jean.Claude - jean-claude.kalonji@seineetmarne.cci.fr</pre>
</details>
## 04 06 2026
> Etude de marché, offre et demande
## 24 06 2026
@@ -0,0 +1,4 @@
import xmlrpc.client
proxy = xmlrpc.client.ServerProxy("http://192.168.1.210:9000/")
num = int(input("Entrez un nombre : "))
print("Résultat : ", proxy.square(num))
@@ -0,0 +1,7 @@
from xmlrpc.server import SimpleXMLRPCServer
def square(x):
return x * x
server = SimpleXMLRPCServer(("0.0.0.0", 9000))
print("Server listening on port 9000...")
server.register_function(square, "square")
server.serve_forever()
@@ -0,0 +1,64 @@
from xmlrpc.server import SimpleXMLRPCServer
import itertools
import string
class HashCrackerServer:
def __init__(self, target_hash, algo):
self.target_hash = target_hash
self.algo = algo
self.workers = []
self.password_found = False
print("Génération de l'espace de recherche (1 à 4 lettres)...")
self.blocks = self._generate_blocks()
print(f"Espace divisé en {len(self.blocks)} blocs de travail.")
def _generate_blocks(self, block_size=5000):
chars = string.ascii_lowercase
all_combinations = []
# Génère les mots de 1 à 4 lettres
for length in range(1, 5):
for p in itertools.product(chars, repeat=length):
all_combinations.append("".join(p))
# Découpage de la liste globale en sous-listes (blocs)
return [all_combinations[i:i + block_size] for i in range(0, len(all_combinations), block_size)]
def register_worker(self, worker_name):
if worker_name not in self.workers:
self.workers.append(worker_name)
print(f"[INFO] Nouveau Worker enregistré : {worker_name}")
return True
def get_work_block(self):
if self.password_found:
return {"status": "STOP"} # Quelqu'un a déjà trouvé
if not self.blocks:
return {"status": "DONE"} # Plus de travail disponible
# On retire le premier bloc de la liste et on l'envoie
return {
"status": "WORK",
"algo": self.algo,
"target": self.target_hash,
"words": self.blocks.pop(0)
}
def submit_result(self, worker_name, password):
if password:
self.password_found = True
print(f"\n[SUCCÈS] Le worker '{worker_name}' a cracké le hash ! Mot de passe : {password}")
return True
# Hash MD5 pour le mot "chat"
TARGET_HASH = "aa8af3ebe14831a7cd1b6d1383a03755"
ALGO = "md5"
server = SimpleXMLRPCServer(("0.0.0.0", 9000), allow_none=True)
cracker_instance = HashCrackerServer(TARGET_HASH, ALGO)
# Enregistrement de l'instance entière (expose toutes ses méthodes publiques)
server.register_instance(cracker_instance)
print("Serveur Maître RPC en écoute sur le port 9000...")
server.serve_forever()
@@ -0,0 +1,54 @@
import xmlrpc.client
import hashlib
import sys
# Pense à remplacer par l'IP de ta VM1
PROXY_URL = "http://192.168.1.210:9000/"
WORKER_NAME = "UE2-24-worker1"
#WORKER_NAME = "UE2-24-worker2"
try:
proxy = xmlrpc.client.ServerProxy(PROXY_URL, allow_none=True)
proxy.register_worker(WORKER_NAME)
print(f"Connecté au serveur en tant que {WORKER_NAME}")
except Exception as e:
print(f"Impossible de se connecter au serveur : {e}")
sys.exit(1)
while True:
try:
job = proxy.get_work_block()
except Exception as e:
print(f"Erreur de communication avec le serveur : {e}")
break
if job["status"] == "STOP":
print("Un autre worker a trouvé le mot de passe. Fin du programme.")
break
elif job["status"] == "DONE":
print("L'espace de recherche est épuisé. Le mot de passe n'a pas été trouvé.")
break
words = job["words"]
target = job["target"]
algo = job["algo"]
print(f"Réception d'un bloc de {len(words)} mots à tester...")
found_password = None
# Boucle de force brute sur le bloc
for word in words:
h = hashlib.new(algo)
h.update(word.encode('utf-8'))
if h.hexdigest() == target:
found_password = word
break
# Soumission du résultat (mot de passe ou None si échec sur ce bloc)
if found_password:
proxy.submit_result(WORKER_NAME, found_password)
print(f">>> MOT DE PASSE TROUVÉ : {found_password} <<<")
break
else:
proxy.submit_result(WORKER_NAME, None)
@@ -0,0 +1,58 @@
services:
db:
image: mariadb:latest
container_name: db_container
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=rootpassword
- MYSQL_DATABASE=mydb
- MYSQL_USER=user
- MYSQL_PASSWORD=userpassword
volumes:
- db_data:/var/lib/mysql
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "mariadb -uroot -prootpassword -e 'SELECT 1' || exit 1"]
interval: 5s
timeout: 5s
retries: 3
web:
image: nginx:alpine
container_name: web_container
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost || exit 1"]
interval: 10s
timeout: 5s
retries: 3
phpmyadmin:
image: phpmyadmin:latest
container_name: phpmyadmin_container
restart: unless-stopped
environment:
- PMA_HOST=db
ports:
- "8081:80"
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost || exit 1"]
interval: 10s
timeout: 5s
retries: 3
volumes:
db_data:
networks:
app-network:
driver: bridge
@@ -0,0 +1,7 @@
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
@@ -0,0 +1,10 @@
{
"name": "api-stock-it",
"version": "1.0.0",
"main": "server.js",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2",
"mysql2": "^3.6.0"
}
}
@@ -0,0 +1,63 @@
const express = require('express');
const mysql = require('mysql2');
const cors = require('cors');
const app = express();
app.use(cors());
app.use(express.json());
// Connexion à la base de données via variables d'environnement
const db = mysql.createPool({
host: process.env.DB_HOST || 'localhost',
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || 'password',
database: process.env.DB_NAME || 'stock_it'
});
// Route GET à la racine : Health Check
app.get('/', (req, res) => {
res.json({
status: 'OK',
message: 'L\'API de gestion de stock est bien en ligne et fonctionnelle !',
timestamp: new Date().toISOString()
});
});
// Route GET : Récupérer tout le stock
app.get('/api/materiel', (req, res) => {
db.query('SELECT * FROM materiel', (err, results) => {
if (err) return res.status(500).json({ error: err.message });
res.json(results);
});
});
// Route POST : Ajouter un nouvel équipement
app.post('/api/materiel', (req, res) => {
const { nom, quantite } = req.body;
db.query('INSERT INTO materiel (nom, quantite) VALUES (?, ?)', [nom, quantite], (err, results) => {
if (err) return res.status(500).json({ error: err.message });
res.status(201).json({ id: results.insertId, nom, quantite });
});
});
// Route PUT : Mettre à jour la quantité d'un équipement
app.put('/api/materiel/:id', (req, res) => {
const { quantite } = req.body;
db.query('UPDATE materiel SET quantite = ? WHERE id = ?', [quantite, req.params.id], (err, results) => {
if (err) return res.status(500).json({ error: err.message });
res.json({ message: 'Quantité mise à jour avec succès' });
});
});
// Route DELETE : Supprimer un équipement
app.delete('/api/materiel/:id', (req, res) => {
db.query('DELETE FROM materiel WHERE id = ?', [req.params.id], (err, results) => {
if (err) return res.status(500).json({ error: err.message });
res.json({ message: 'Équipement supprimé avec succès' });
});
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`API Backend démarrée sur le port ${PORT}`);
});
@@ -0,0 +1,94 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mariadb-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: ConfigMap
metadata:
name: db-init-script
data:
init.sql: |
CREATE DATABASE IF NOT EXISTS stock_it;
USE stock_it;
CREATE TABLE IF NOT EXISTS materiel (
id INT AUTO_INCREMENT PRIMARY KEY,
nom VARCHAR(255) NOT NULL,
quantite INT NOT NULL
);
INSERT INTO materiel (nom, quantite) VALUES
('Serveur Dell PowerEdge', 3),
('Switch Cisco 24 ports', 5),
('Baie de brassage', 2);
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: db-backend
spec:
replicas: 1
selector:
matchLabels:
app: mariadb
template:
metadata:
labels:
app: mariadb
spec:
containers:
- name: mariadb
image: mariadb:10.11
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "250m"
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: root-password
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: app-config
key: db-name
ports:
- containerPort: 3306
volumeMounts:
- name: init-script-volume
mountPath: /docker-entrypoint-initdb.d/init.sql
subPath: init.sql
- name: mariadb-storage
mountPath: /var/lib/mysql
volumes:
- name: init-script-volume
configMap:
name: db-init-script
- name: mariadb-storage
persistentVolumeClaim:
claimName: mariadb-pvc
---
apiVersion: v1
kind: Service
metadata:
name: db-service
spec:
type: ClusterIP
selector:
app: mariadb
ports:
- port: 3306
targetPort: 3306
@@ -0,0 +1,68 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-backend
spec:
replicas: 2
selector:
matchLabels:
app: node-api
template:
metadata:
labels:
app: node-api
spec:
containers:
- name: node-api
image: gsz116/api-stock:v2
imagePullPolicy: Always
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: db-host
- name: DB_USER
valueFrom:
configMapKeyRef:
name: app-config
key: db-user
- name: DB_NAME
valueFrom:
configMapKeyRef:
name: app-config
key: db-name
- name: PORT
valueFrom:
configMapKeyRef:
name: app-config
key: backend-port
# Variable issue du Secret
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: root-password
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
type: NodePort
selector:
app: node-api
ports:
- port: 3000
targetPort: 3000
nodePort: 30001
@@ -0,0 +1,47 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-frontend
spec:
replicas: 2
selector:
matchLabels:
app: nginx-front
template:
metadata:
labels:
app: nginx-front
spec:
containers:
- name: nginx-front
image: gsz116/front-stock:v2
imagePullPolicy: Always
resources:
requests:
memory: "32Mi"
cpu: "50m"
limits:
memory: "64Mi"
cpu: "100m"
env:
- name: API_URL
valueFrom:
configMapKeyRef:
name: app-config
key: api-url
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
type: NodePort
selector:
app: nginx-front
ports:
- port: 80
targetPort: 80
nodePort: 30002
@@ -0,0 +1,3 @@
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80
@@ -0,0 +1,153 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gestion de Stock IT</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 40px;
background-color: #f4f4f9;
}
h1 {
color: #333;
}
.container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
max-width: 600px;
margin-bottom: 20px;
}
input,
button {
padding: 10px;
margin: 5px 0;
width: 100%;
box-sizing: border-box;
}
button {
background-color: #007bff;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
ul {
list-style-type: none;
padding: 0;
}
li {
background: #eee;
margin: 5px 0;
padding: 10px;
border-radius: 4px;
display: flex;
justify-content: space-between;
}
</style>
</head>
<body>
<h1>Gestion de Stock Informatique</h1>
<div class="container">
<h2>Ajouter un équipement</h2>
<form id="addForm">
<input type="text" id="nom" placeholder="Nom du matériel (ex: Routeur MicroTik)" required>
<input type="number" id="quantite" placeholder="Quantité" required min="1">
<button type="submit">Ajouter au stock</button>
</form>
</div>
<div class="container">
<h2>Inventaire actuel</h2>
<ul id="stockList">Chargement du stock...</ul>
</div>
<script>
const API_URL = 'http://192.168.1.15:30001/api/materiel';
async function fetchStock() {
try {
const response = await fetch(API_URL);
const data = await response.json();
const list = document.getElementById('stockList');
list.innerHTML = '';
data.forEach(item => {
const li = document.createElement('li');
li.innerHTML = `
<span><strong>${item.nom}</strong></span>
<span>Quantité: ${item.quantite}</span>
<div>
<button onclick="modifierQuantite(${item.id}, ${item.quantite})" style="background-color: #ffc107; color: black; margin-right: 5px; width: auto;">Modifier</button>
<button onclick="supprimerMateriel(${item.id})" style="background-color: #dc3545; width: auto;">Supprimer</button>
</div>
`;
list.appendChild(li);
});
} catch (error) {
document.getElementById('stockList').innerHTML = '<li style="color:red;">Erreur de connexion à l\'API</li>';
}
}
document.getElementById('addForm').addEventListener('submit', async (e) => {
e.preventDefault();
const nom = document.getElementById('nom').value;
const quantite = document.getElementById('quantite').value;
await fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nom, quantite })
});
document.getElementById('nom').value = '';
document.getElementById('quantite').value = '';
fetchStock();
});
// Nouvelle fonction : Modifier la quantité
window.modifierQuantite = async (id, ancienneQuantite) => {
const nouvelleQuantite = prompt("Entrez la nouvelle quantité :", ancienneQuantite);
// Si l'utilisateur n'a pas annulé et a entré un nombre valide
if (nouvelleQuantite !== null && nouvelleQuantite !== "" && !isNaN(nouvelleQuantite)) {
await fetch(`${API_URL}/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ quantite: nouvelleQuantite })
});
fetchStock(); // Rafraîchit la liste
}
};
// Nouvelle fonction : Supprimer un matériel
window.supprimerMateriel = async (id) => {
if (confirm("Êtes-vous sûr de vouloir supprimer ce matériel de l'inventaire ?")) {
await fetch(`${API_URL}/${id}`, {
method: 'DELETE'
});
fetchStock(); // Rafraîchit la liste
}
};
// Charger le stock au démarrage
fetchStock();
</script>
</body>
</html>