# Fonctionnalité : Icône cliquable pour photo principale

## 🎯 Objectif

Ajouter une icône cliquable en bas à gauche de chaque photo dans la galerie pour permettre de définir facilement quelle photo sera utilisée comme vignette principale (thumbnail).

## ✅ Implémentation

### 1. Interface utilisateur

**Fichier** : `frontend/js/peripheral-detail.js` (lignes 108-112)

```javascript
<button class="photo-primary-toggle ${photo.is_primary ? 'active' : ''}"
        onclick="setPrimaryPhoto(${photo.id})"
        title="${photo.is_primary ? 'Photo principale' : 'Définir comme photo principale'}">
    <i class="fas fa-${photo.is_primary ? 'check-circle' : 'circle'}"></i>
</button>
```

**Icônes** :
- ⭕ `circle` (non cochée) - Photo normale
- ✅ `check-circle` (cochée) - Photo principale

### 2. Style CSS

**Fichier** : `frontend/css/peripherals.css` (lignes 764-803)

```css
/* Photo Primary Toggle */
.photo-primary-toggle {
    position: absolute;
    bottom: 8px;
    left: 8px;
    background: rgba(0, 0, 0, 0.7);
    border: 2px solid #666;
    border-radius: 50%;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.2s ease;
    color: #999;
    font-size: 16px;
    z-index: 10;
}

.photo-primary-toggle:hover {
    background: rgba(0, 0, 0, 0.85);
    border-color: #66d9ef;
    color: #66d9ef;
    transform: scale(1.1);
}

.photo-primary-toggle.active {
    background: rgba(102, 217, 239, 0.2);
    border-color: #66d9ef;
    color: #66d9ef;
}

.photo-primary-toggle.active:hover {
    background: rgba(102, 217, 239, 0.3);
}

.photo-item {
    position: relative;
}
```

**Caractéristiques** :
- Position : Coin inférieur gauche de chaque photo
- Taille : 32×32px, bouton rond
- États : normal (gris), hover (bleu), active (bleu clair)
- Effet : Scale 1.1 au hover
- Z-index élevé pour rester au-dessus de l'image

### 3. Fonction JavaScript

**Fichier** : `frontend/js/peripheral-detail.js` (lignes 239-252)

```javascript
// Set photo as primary
async function setPrimaryPhoto(photoId) {
    try {
        await apiRequest(`/peripherals/${peripheralId}/photos/${photoId}/set-primary`, {
            method: 'POST'
        });

        showSuccess('Photo principale définie');
        loadPhotos(); // Reload to update icons
    } catch (error) {
        console.error('Error setting primary photo:', error);
        showError('Erreur lors de la définition de la photo principale');
    }
}
```

**Processus** :
1. Appel API POST pour définir la photo comme principale
2. Message de succès
3. Rechargement de la galerie pour mettre à jour les icônes

### 4. Endpoint API Backend

**Fichier** : `backend/app/api/endpoints/peripherals.py` (lignes 370-396)

```python
@router.post("/{peripheral_id}/photos/{photo_id}/set-primary", status_code=200)
def set_primary_photo(
    peripheral_id: int,
    photo_id: int,
    db: Session = Depends(get_peripherals_db)
):
    """Set a photo as primary (thumbnail)"""
    # Get the photo
    photo = db.query(PeripheralPhoto).filter(
        PeripheralPhoto.id == photo_id,
        PeripheralPhoto.peripheral_id == peripheral_id
    ).first()

    if not photo:
        raise HTTPException(status_code=404, detail="Photo not found")

    # Unset all other primary photos for this peripheral
    db.query(PeripheralPhoto).filter(
        PeripheralPhoto.peripheral_id == peripheral_id,
        PeripheralPhoto.id != photo_id
    ).update({"is_primary": False})

    # Set this photo as primary
    photo.is_primary = True
    db.commit()

    return {"message": "Photo set as primary", "photo_id": photo_id}
```

**Logique** :
1. Vérifie que la photo existe et appartient au périphérique
2. Retire le flag `is_primary` de toutes les autres photos
3. Définit `is_primary=True` pour la photo sélectionnée
4. Garantit qu'une seule photo est principale à la fois

## 🎨 Rendu visuel

### Galerie de photos

```
┌─────────────┐  ┌─────────────┐  ┌─────────────┐
│             │  │             │  │             │
│   Photo 1   │  │   Photo 2   │  │   Photo 3   │
│             │  │             │  │             │
│ ⭕          │  │ ✅          │  │ ⭕          │
│  [🗑️]      │  │  [🗑️]      │  │  [🗑️]      │
│ ★ Principale│  │             │  │             │
└─────────────┘  └─────────────┘  └─────────────┘
```

**Légende** :
- ⭕ = Icône ronde grise (non sélectionnée)
- ✅ = Icône check bleu cyan (sélectionnée)
- ★ = Badge "Principale" (affiché en haut)
- 🗑️ = Bouton supprimer (en haut à droite)

### États de l'icône

| État | Apparence | Couleur | Comportement |
|------|-----------|---------|--------------|
| **Normal** | ⭕ Circle | Gris #999 | Cliquable |
| **Hover** | ⭕ Circle agrandie | Bleu #66d9ef | Scale 1.1 |
| **Active** | ✅ Check-circle | Bleu #66d9ef | Fond bleu clair |
| **Active + Hover** | ✅ Check-circle | Bleu plus clair | Rétroaction visuelle |

## 🔄 Flux d'utilisation

```
1. User voit la galerie de photos
   ↓
2. Chaque photo affiche une icône ⭕/✅ en bas à gauche
   ↓
3. User clique sur une icône ⭕ (non sélectionnée)
   ↓
4. setPrimaryPhoto(photoId) appelé
   │  ├─> POST /api/peripherals/{id}/photos/{photo_id}/set-primary
   │  └─> Backend met à jour is_primary
   ↓
5. Base de données mise à jour
   │  ├─> Ancienne photo principale : is_primary = false
   │  └─> Nouvelle photo : is_primary = true
   ↓
6. Success
   │  ├─> Message "Photo principale définie"
   │  ├─> Galerie rechargée
   │  └─> Icônes mises à jour (✅ sur la nouvelle, ⭕ sur les autres)
```

## 📊 Règles métier

### Contraintes

1. **Une seule photo principale** par périphérique
   - Définie automatiquement lors de la sélection
   - Les autres sont désélectionnées automatiquement

2. **Photo principale = Vignette**
   - Utilisée dans les listes de périphériques
   - Affichée comme aperçu principal

3. **Upload avec is_primary**
   - Possibilité de cocher lors de l'upload
   - Si cochée, retire le flag des autres

### Avantages

- ✅ **Interface intuitive** : Un clic pour changer
- ✅ **Visuel clair** : États bien différenciés
- ✅ **Feedback immédiat** : Message + rechargement
- ✅ **Cohérence** : Une seule photo principale garantie

## 🧪 Tests

### Test manuel

1. **Ouvrir page détail** : Aller sur `/peripheral-detail.html?id=3`
2. **Observer les icônes** : Voir ⭕ ou ✅ en bas à gauche de chaque photo
3. **Hover sur icône** : Vérifier effet scale + changement couleur
4. **Cliquer icône non cochée** :
   - Message "Photo principale définie"
   - Icône devient ✅
   - Autres icônes deviennent ⭕
5. **Vérifier badge** : Badge "★ Principale" sur la photo cochée

### Test API

```bash
# Définir photo ID 5 comme principale pour périphérique 3
curl -X POST "http://10.0.0.50:8007/api/peripherals/3/photos/5/set-primary" \
  -H "X-API-Token: YOUR_TOKEN"
```

**Résultat attendu** :
```json
{
  "message": "Photo set as primary",
  "photo_id": 5
}
```

### Vérification base de données

```bash
docker exec linux_benchtools_backend python3 -c "
import sqlite3
conn = sqlite3.connect('/app/data/peripherals.db')
cursor = conn.cursor()
cursor.execute('SELECT id, filename, is_primary FROM peripheral_photos WHERE peripheral_id = 3')
for row in cursor.fetchall():
    print(f'Photo {row[0]}: {row[1]} - Primary: {row[2]}')
"
```

**Résultat attendu** :
```
Photo 4: image1.png - Primary: 0
Photo 5: image2.png - Primary: 1  ← Une seule
Photo 6: image3.png - Primary: 0
```

## 📝 Fichiers modifiés

### Frontend
- ✅ `frontend/js/peripheral-detail.js` - Ajout bouton + fonction setPrimaryPhoto()
- ✅ `frontend/css/peripherals.css` - Style .photo-primary-toggle

### Backend
- ✅ `backend/app/api/endpoints/peripherals.py` - Endpoint POST set-primary

### Documentation
- ✅ `docs/FEATURE_PRIMARY_PHOTO_TOGGLE.md` - Cette documentation

## 💡 Améliorations futures possibles

- [ ] Drag & drop pour réorganiser les photos
- [ ] Double-clic sur photo pour la définir comme principale
- [ ] Raccourci clavier (ex: P pour Primary)
- [ ] Animation de transition entre photos principales
- [ ] Preview de la vignette avant validation

---

**Date** : 31 décembre 2025
**Statut** : ✅ Implémenté et fonctionnel
**Impact** : Interface intuitive pour choisir la photo principale
