11 KiB
Executable File
Session 2025-12-31 : Implémentation du bouton "Modifier"
🎯 Objectif
Implémenter le bouton "Modifier" dans la page de détail du périphérique pour permettre l'édition complète des informations.
📊 État initial
Avant :
- ✅ Bouton "Modifier" présent dans l'interface
- ❌ Fonction
toggleEditMode()affichait juste "Mode édition à venir" - ❌ Pas de modale d'édition
- ❌ Pas de fonction de sauvegarde
✅ Implémentation
1. Modale d'édition HTML
Fichier : frontend/peripheral-detail.html (lignes 305-453)
Structure :
<div id="modal-edit" class="modal">
<div class="modal-content modal-large">
<form id="form-edit-peripheral" onsubmit="savePeripheral(event)">
<!-- 3 sections principales -->
<div class="form-section">Identification</div>
<div class="form-section">Achat</div>
<div class="form-section">État et localisation</div>
<div class="form-section full-width">Documentation technique</div>
</form>
</div>
</div>
Champs disponibles :
Section Identification
nom* (requis)type_principal* (requis)sous_typemarquemodelenumero_serie
Section Achat
boutiquedate_achat(type date)prix(number)devise(3 caractères, défaut: EUR)garantie_duree_mois(number)
Section État et localisation
etat(select: Neuf, Bon, Usagé, Défectueux, Retiré)rating(0-5 étoiles cliquables)quantite_totale(number)quantite_disponible(number)
Section Documentation technique
synthese(textarea Markdown)cli_yaml(textarea YAML)cli_raw(textarea Markdown)specifications(textarea Markdown)notes(textarea Markdown)
2. Fonction JavaScript : toggleEditMode()
Fichier : frontend/js/peripheral-detail.js (lignes 461-494)
function toggleEditMode() {
if (!peripheral) {
showError('Aucun périphérique chargé');
return;
}
// Populate form with peripheral data
document.getElementById('edit-nom').value = peripheral.nom || '';
document.getElementById('edit-type_principal').value = peripheral.type_principal || '';
// ... (tous les champs)
// Special handling for rating (star system)
setEditRating(peripheral.rating || 0);
// Show modal
document.getElementById('modal-edit').style.display = 'block';
}
Fonctionnement :
- Vérifie que le périphérique est chargé
- Remplit tous les champs du formulaire avec les données actuelles
- Applique la note avec le système d'étoiles
- Affiche la modale
3. Fonction : setEditRating()
Fichier : frontend/js/peripheral-detail.js (lignes 500-513)
function setEditRating(rating) {
const stars = document.querySelectorAll('#edit-star-rating .fa-star');
const ratingInput = document.getElementById('edit-rating');
ratingInput.value = rating;
stars.forEach((star, index) => {
if (index < rating) {
star.classList.add('active');
} else {
star.classList.remove('active');
}
});
}
Fonctionnement :
- Active les étoiles jusqu'à la note donnée
- Stocke la valeur dans le champ hidden
- Utilisé à la fois lors du chargement et lors du clic
4. Event listeners pour les étoiles
Fichier : frontend/js/peripheral-detail.js (lignes 515-525)
document.addEventListener('DOMContentLoaded', () => {
const editStars = document.querySelectorAll('#edit-star-rating .fa-star');
editStars.forEach(star => {
star.addEventListener('click', () => {
const rating = parseInt(star.getAttribute('data-rating'));
setEditRating(rating);
});
});
});
Fonctionnement :
- Attache un event listener à chaque étoile
- Au clic, récupère la note (1-5)
- Appelle
setEditRating()pour mettre à jour visuellement
5. Fonction : savePeripheral()
Fichier : frontend/js/peripheral-detail.js (lignes 527-559)
async function savePeripheral(event) {
event.preventDefault();
const form = event.target;
const formData = new FormData(form);
const data = {};
// Convert FormData to object
for (let [key, value] of formData.entries()) {
// Convert numeric fields
if (['prix', 'garantie_duree_mois', 'quantite_totale', 'quantite_disponible', 'rating'].includes(key)) {
data[key] = value ? parseFloat(value) : null;
} else {
data[key] = value || null;
}
}
try {
const response = await apiRequest(`/peripherals/${peripheralId}`, {
method: 'PUT',
body: JSON.stringify(data)
});
showSuccess('Périphérique mis à jour avec succès');
closeEditModal();
// Reload peripheral data
await loadPeripheral();
} catch (error) {
console.error('Error updating peripheral:', error);
showError('Erreur lors de la mise à jour du périphérique');
}
}
Fonctionnement :
- Empêche le submit par défaut
- Récupère toutes les données du formulaire
- Convertit les champs numériques en
float - Envoie une requête
PUTà l'API - Affiche un message de succès/erreur
- Ferme la modale
- Recharge les données du périphérique pour afficher les changements
6. Fonction : closeEditModal()
Fichier : frontend/js/peripheral-detail.js (lignes 496-498)
function closeEditModal() {
document.getElementById('modal-edit').style.display = 'none';
}
Utilisation :
- Bouton "Annuler" dans la modale
- Croix de fermeture (×)
- Clic en dehors de la modale (via
window.onclick)
7. Style CSS pour grande modale
Fichier : frontend/css/peripherals.css (lignes 284-287)
.modal-content.modal-large {
max-width: 1400px;
width: 95%;
}
Usage : Classe .modal-large appliquée à la modale d'édition pour afficher tous les champs confortablement.
🔄 Flux complet
1. User clique "Modifier"
↓
2. toggleEditMode()
├─> Vérifie que peripheral est chargé
├─> Remplit tous les champs du formulaire
├─> Applique la note (étoiles)
└─> Affiche la modale
↓
3. User modifie les champs
├─> Clic sur étoiles → setEditRating()
└─> Saisie texte, nombres, dates
↓
4. User clique "Enregistrer"
↓
5. savePeripheral()
├─> Prévient le submit par défaut
├─> Récupère FormData
├─> Convertit types (string → number)
├─> PUT /api/peripherals/{id}
├─> Succès → showSuccess() + closeEditModal()
├─> Erreur → showError()
└─> Recharge → loadPeripheral()
↓
6. Page mise à jour avec nouvelles données
📋 Requête API
Endpoint
PUT /api/peripherals/{id}
Headers
{
"Content-Type": "application/json",
"X-API-Token": "YOUR_TOKEN"
}
Body (exemple)
{
"nom": "Logitech MX Master 3S",
"type_principal": "Souris",
"sous_type": "Sans fil",
"marque": "Logitech",
"modele": "MX Master 3S",
"numero_serie": "LGI-2024-001",
"boutique": "Amazon",
"date_achat": "2024-12-01",
"prix": 99.99,
"devise": "EUR",
"garantie_duree_mois": 24,
"etat": "Neuf",
"rating": 5,
"quantite_totale": 1,
"quantite_disponible": 1,
"synthese": "# Souris ergonomique\n\nExcellente souris pour le travail.",
"cli_yaml": "identification:\n vendor_id: 046d\n product_id: 4082",
"cli_raw": "```\nBus 001 Device 005: ID 046d:4082 Logitech, Inc.\n```",
"specifications": "## Caractéristiques\n- DPI : 8000\n- Bluetooth 5.0",
"notes": "Achetée en promotion"
}
Réponse (200 OK)
{
"id": 3,
"nom": "Logitech MX Master 3S",
"type_principal": "Souris",
// ... tous les champs mis à jour
"updated_at": "2025-12-31T12:00:00"
}
🧪 Test de validation
1. Ouvrir la page de détail
http://10.0.0.50:8087/peripheral-detail.html?id=3
2. Cliquer sur "Modifier"
Vérifications :
- ✅ La modale s'affiche
- ✅ Tous les champs sont pré-remplis avec les données actuelles
- ✅ Les étoiles correspondent à la note actuelle
3. Modifier des champs
Test :
- Modifier le nom
- Changer la note (clic sur étoiles)
- Modifier le prix
- Ajouter des notes
Vérifications :
- ✅ Les étoiles s'activent au clic
- ✅ Les champs acceptent la saisie
- ✅ La validation fonctionne (champs requis)
4. Enregistrer
Vérifications :
- ✅ Message "Périphérique mis à jour avec succès"
- ✅ Modale se ferme
- ✅ Données affichées sont mises à jour
- ✅ Pas d'erreur console
5. Vérifier la persistance
Test :
- Rafraîchir la page (F5)
- Vérifier que les modifications sont conservées
Vérifications :
- ✅ Les données modifiées sont affichées
- ✅ La base de données a bien été mise à jour
🎨 Interface utilisateur
Bouton "Modifier"
Position : En haut à droite de la carte "Informations générales"
<button class="btn btn-primary" onclick="toggleEditMode()" id="btn-edit">
<i class="fas fa-edit"></i> Modifier
</button>
Modale d'édition
Largeur : 95% (max 1400px) grâce à .modal-large
Layout : Grid responsive avec 3 colonnes sur desktop
Sections :
- Identification (colonne 1)
- Achat (colonne 2)
- État et localisation (colonne 3)
- Documentation technique (pleine largeur)
Boutons d'action
<div class="form-actions">
<button type="button" class="btn btn-secondary" onclick="closeEditModal()">
Annuler
</button>
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> Enregistrer
</button>
</div>
📝 Notes techniques
Gestion des types de données
String vers Number :
if (['prix', 'garantie_duree_mois', 'quantite_totale', 'quantite_disponible', 'rating'].includes(key)) {
data[key] = value ? parseFloat(value) : null;
}
Date : Format YYYY-MM-DD (HTML5 input type="date")
Null values : Les champs vides sont envoyés comme null au lieu de chaînes vides
Validation
Côté client :
- Champs requis :
nom,type_principal - Type number : min="0" pour prix et quantités
- Type date : format ISO 8601
Côté serveur : Validation Pydantic dans le backend FastAPI
Système d'étoiles
État actif : Classe CSS .active ajoutée aux étoiles
HTML structure :
<div class="star-rating" id="edit-star-rating">
<input type="hidden" id="edit-rating" name="rating" value="0">
<i class="fas fa-star" data-rating="1"></i>
<i class="fas fa-star" data-rating="2"></i>
<!-- ... -->
</div>
CSS :
.star-rating .fa-star.active {
color: #f1c40f;
text-shadow: 0 0 3px rgba(241, 196, 15, 0.5);
}
🔧 Améliorations futures possibles
- Validation en temps réel des champs
- Preview Markdown pour les textareas
- Auto-save (brouillon local)
- Historique des modifications (qui/quand)
- Undo/Redo
- Dropdowns pour type_principal/sous_type (au lieu de input text)
- Upload photo directement depuis la modale d'édition
- Confirmation avant fermeture si modifications non sauvegardées
Date : 31 décembre 2025 Statut : ✅ Implémenté et testé Impact : Édition complète des périphériques depuis la page de détail