# Fonctionnalité : Modifier un périphérique ## 🎯 Objectif Implémenter le bouton "Modifier" dans la page de détail d'un périphérique pour permettre l'édition complète des informations. ## ✅ Implémentation ### 1. Interface HTML **Fichier** : `frontend/peripheral-detail.html` #### Modale d'édition (lignes 305-453) ```html ``` #### Sections du formulaire 1. **Identification** - Nom (requis) - Type principal (requis) - Sous-type - Marque - Modèle - Numéro de série 2. **Achat** - Boutique - Date d'achat - Prix - Devise - Garantie (mois) 3. **État et localisation** - État (Neuf, Bon, Usagé, Défectueux, Retiré) - Note (système d'étoiles cliquables) - Quantité totale - Quantité disponible 4. **Documentation technique** - Synthèse (Markdown) - CLI / Données structurées (YAML) - CLI / Rapport système (Markdown) - Spécifications (Markdown) - Notes (Markdown) ### 2. Style CSS **Fichier** : `frontend/css/peripherals.css` (lignes 284-287) ```css .modal-content.modal-large { max-width: 1400px; width: 95%; } ``` **Caractéristiques** : - Modale plus large pour afficher tous les champs - Responsive (95% de la largeur sur petit écran) - Max 1400px sur grand écran ### 3. JavaScript - Fonctions **Fichier** : `frontend/js/peripheral-detail.js` #### `toggleEditMode()` (ligne 461-494) **Rôle** : Ouvrir la modale et pré-remplir le formulaire avec les données actuelles ```javascript 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 autres champs ... // Show modal document.getElementById('modal-edit').style.display = 'block'; } ``` **Gère** : - Vérification que le périphérique est chargé - Pré-remplissage de tous les champs du formulaire - Gestion des valeurs nulles avec fallback - Appel `setEditRating()` pour les étoiles #### `closeEditModal()` (ligne 496-498) **Rôle** : Fermer la modale d'édition ```javascript function closeEditModal() { document.getElementById('modal-edit').style.display = 'none'; } ``` #### `setEditRating(rating)` (ligne 500-513) **Rôle** : Mettre à jour l'affichage des étoiles dans le formulaire d'édition ```javascript 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'); } }); } ``` **Fonctionnalités** : - Met à jour le champ hidden `edit-rating` - Ajoute/retire la classe `active` sur les étoiles - Permet sélection visuelle interactive #### Event listener étoiles (ligne 516-525) ```javascript 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); }); }); }); ``` **Rôle** : Rendre les étoiles cliquables pour modifier la note #### `savePeripheral(event)` (ligne 527-559) **Rôle** : Sauvegarder les modifications via l'API ```javascript 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'); } } ``` **Processus** : 1. Empêche soumission formulaire par défaut 2. Récupère les données du formulaire 3. Convertit FormData en objet JavaScript 4. Convertit champs numériques en nombres 5. Envoie requête PUT à l'API 6. Affiche message succès/erreur 7. Ferme la modale 8. Recharge les données pour rafraîchir l'affichage ### 4. API Backend **Endpoint** : `PUT /api/peripherals/{peripheral_id}` **Fichier** : `backend/app/api/endpoints/peripherals.py` (ligne 177-187) ```python @router.put("/{peripheral_id}", response_model=PeripheralDetail) def update_peripheral( peripheral_id: int, peripheral_data: PeripheralUpdate, db: Session = Depends(get_peripherals_db) ): """Update a peripheral""" peripheral = PeripheralService.update_peripheral(db, peripheral_id, peripheral_data) if not peripheral: raise HTTPException(status_code=404, detail="Peripheral not found") return peripheral ``` **Schéma attendu** : `PeripheralUpdate` (Pydantic) **Retour** : `PeripheralDetail` (données complètes du périphérique) ## 🔄 Flux d'utilisation ``` 1. User clique "Modifier" dans page détail ↓ 2. toggleEditMode() appelé │ ├─> Vérifie que peripheral est chargé │ ├─> Pré-remplit tous les champs du formulaire │ ├─> Configure les étoiles de notation │ └─> Affiche la modale ↓ 3. User modifie les champs souhaités │ └─> Peut cliquer sur les étoiles pour changer la note ↓ 4. User clique "Enregistrer" ↓ 5. savePeripheral() appelé │ ├─> Récupère données du formulaire │ ├─> Convertit types numériques │ ├─> PUT /api/peripherals/{id} │ └─> Backend met à jour en BDD ↓ 6. Success │ ├─> Message "Périphérique mis à jour avec succès" │ ├─> Ferme modale │ └─> Recharge peripheral pour afficher nouvelles données ``` ## 📊 Champs éditables | Catégorie | Champ | Type | Requis | |-----------|-------|------|--------| | **Identification** | nom | text | ✅ | | | type_principal | text | ✅ | | | sous_type | text | | | | marque | text | | | | modele | text | | | | numero_serie | text | | | **Achat** | boutique | text | | | | date_achat | date | | | | prix | number | | | | devise | text(3) | | | | garantie_duree_mois | number | | | **État** | etat | select | | | | rating | number(0-5) | | | | quantite_totale | number | | | | quantite_disponible | number | | | **Documentation** | synthese | textarea | | | | cli_yaml | textarea | | | | cli_raw | textarea | | | | specifications | textarea | | | | notes | textarea | | **Total** : 22 champs éditables ## 🎨 Interface utilisateur ### Bouton "Modifier" **Position** : Dans le header de la carte "Informations générales" ```html ``` **Style** : - Bouton bleu primaire - Icône crayon Font Awesome - Positionné à droite du header ### Modale d'édition **Dimensions** : - Largeur : 95% (mobile) → max 1400px (desktop) - Layout : Grille responsive 3 colonnes **Sections** : - 3 colonnes pour les champs principaux - Pleine largeur pour documentation technique - Actions (Annuler / Enregistrer) en bas ### Retour utilisateur **Messages** : - ✅ Succès : "Périphérique mis à jour avec succès" (vert) - ❌ Erreur : "Erreur lors de la mise à jour du périphérique" (rouge) - ⚠️ Validation : "Aucun périphérique chargé" (orange) ## 🧪 Tests ### Test manuel 1. **Ouvrir page détail** : `/peripheral-detail.html?id=3` 2. **Cliquer "Modifier"** : Modale s'ouvre avec données pré-remplies 3. **Modifier champs** : Ex: changer nom, prix, note 4. **Cliquer étoiles** : Note change visuellement 5. **Cliquer "Enregistrer"** : Message succès + modale se ferme 6. **Vérifier affichage** : Nouvelles valeurs affichées ### Test API ```bash # Mettre à jour un périphérique curl -X PUT "http://10.0.0.50:8007/api/peripherals/3" \ -H "Content-Type: application/json" \ -H "X-API-Token: YOUR_TOKEN" \ -d '{ "nom": "Logitech MX Master 3 (Updated)", "prix": 99.99, "rating": 5 }' ``` **Résultat attendu** : ```json { "id": 3, "nom": "Logitech MX Master 3 (Updated)", "prix": 99.99, "rating": 5, ... } ``` ## 📝 Fichiers modifiés ### Créés - ✅ `docs/FEATURE_EDIT_PERIPHERAL.md` - Cette documentation ### Modifiés - ✅ `frontend/peripheral-detail.html` - Ajout modale d'édition - ✅ `frontend/js/peripheral-detail.js` - Fonctions édition complètes - ✅ `frontend/css/peripherals.css` - Style `.modal-large` ### Backend (déjà existant) - ✅ `backend/app/api/endpoints/peripherals.py` - Endpoint PUT - ✅ `backend/app/services/peripheral_service.py` - Service update - ✅ `backend/app/schemas/peripheral.py` - Schema PeripheralUpdate ## 🚀 Améliorations futures possibles - [ ] Validation côté client (longueurs, formats) - [ ] Champs device_id et location_id (dropdowns) - [ ] Confirmation avant fermeture si modifications non sauvegardées - [ ] Historique des modifications (audit trail) - [ ] Mode "édition rapide" (inline editing) - [ ] Raccourci clavier (Ctrl+E) --- **Date** : 31 décembre 2025 **Statut** : ✅ Implémenté et fonctionnel **Impact** : Permet l'édition complète des périphériques depuis la page de détail