391 lines
10 KiB
Markdown
Executable File
391 lines
10 KiB
Markdown
Executable File
# 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()">×</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
|