Files
serv_benchmark/docs/SESSION_2025-12-31_EDIT_PERIPHERAL.md
Gilles Soulier c67befc549 addon
2026-01-05 16:08:01 +01:00

11 KiB
Executable File
Raw Blame History

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_type
  • marque
  • modele
  • numero_serie

Section Achat

  • boutique
  • date_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 :

  1. Vérifie que le périphérique est chargé
  2. Remplit tous les champs du formulaire avec les données actuelles
  3. Applique la note avec le système d'étoiles
  4. 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 :

  1. Empêche le submit par défaut
  2. Récupère toutes les données du formulaire
  3. Convertit les champs numériques en float
  4. Envoie une requête PUT à l'API
  5. Affiche un message de succès/erreur
  6. Ferme la modale
  7. 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 :

  1. Identification (colonne 1)
  2. Achat (colonne 2)
  3. État et localisation (colonne 3)
  4. 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