# 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
<!-- Edit Peripheral Modal -->
<div id="modal-edit" class="modal">
    <div class="modal-content modal-large">
        <div class="modal-header">
            <h2><i class="fas fa-edit"></i> Modifier le périphérique</h2>
            <span class="close" onclick="closeEditModal()">&times;</span>
        </div>
        <div class="modal-body">
            <form id="form-edit-peripheral" onsubmit="savePeripheral(event)">
                <!-- Formulaire complet avec tous les champs -->
            </form>
        </div>
    </div>
</div>
```

#### 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
<button class="btn btn-primary" onclick="toggleEditMode()" id="btn-edit">
    <i class="fas fa-edit"></i> Modifier
</button>
```

**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
