89 lines
4.5 KiB
Markdown
89 lines
4.5 KiB
Markdown
# Parc Machines — Améliorations UX
|
|
|
|
**Date** : 2026-03-23
|
|
**Scope** : 3 changements sur le frontend + 1 extension backend
|
|
|
|
---
|
|
|
|
## 1. Filtre sites multi-sélection par checkboxes
|
|
|
|
### Contexte
|
|
Le filtre site actuel est un `<select>` mono-sélection dans `machines/index.vue`.
|
|
L'utilisateur veut pouvoir sélectionner plusieurs sites simultanément.
|
|
|
|
### Design
|
|
- Remplacer le `<select>` par une rangée de checkboxes DaisyUI directement visibles dans la barre de filtre.
|
|
- Chaque site = une checkbox avec le nom du site.
|
|
- Quand **aucune** checkbox n'est cochée → toutes les machines s'affichent (équivalent "Tous les sites").
|
|
- Quand **une ou plusieurs** sont cochées → filtre sur ces sites uniquement.
|
|
|
|
### Changements techniques
|
|
**Fichier** : `frontend/app/pages/machines/index.vue`
|
|
|
|
- **Réactivité** : utiliser `reactive(new Set())` (Vue 3.4+ supporte nativement les mutations `add`/`delete`/`has` sur un Set réactif). Pas de `.value` nécessaire.
|
|
- **Note** : le fichier utilise `<script setup>` sans `lang="ts"` — ne pas utiliser d'annotations TypeScript comme `Set<string>`.
|
|
- Template : remplacer le `<select>` par un `div` flex-wrap avec des checkboxes DaisyUI (`checkbox checkbox-sm`) + label pour chaque site.
|
|
- Computed `filteredMachines` : remplacer `machine.siteId === selectedSite` par `selectedSites.size === 0 || selectedSites.has(machine.siteId)`.
|
|
|
|
---
|
|
|
|
## 2. Tri alphabétique croissant
|
|
|
|
### Contexte
|
|
Les machines s'affichent dans l'ordre retourné par l'API, sans tri. L'utilisateur veut un tri alphabétique croissant par nom.
|
|
|
|
### Design
|
|
Ajouter un `.sort()` avec `localeCompare('fr')` à la fin du computed `filteredMachines`.
|
|
|
|
### Changements techniques
|
|
**Fichier** : `frontend/app/pages/machines/index.vue`
|
|
|
|
- Dans le computed `filteredMachines`, ajouter avant le `return` :
|
|
```js
|
|
filtered = [...filtered].sort((a, b) =>
|
|
(a.name || '').localeCompare(b.name || '', 'fr')
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Recherche par référence dans les catalogues (Pièces, Composants, Produits)
|
|
|
|
### Contexte
|
|
Les placeholders des champs de recherche promettent "Nom ou référence…" mais le frontend n'envoie que `?name=xxx` à l'API. Le backend (API Platform SearchFilter) supporte `name` et `reference` en `ipartial`, mais combiner `?name=xxx&reference=xxx` produit un AND (les deux doivent matcher), pas un OR.
|
|
|
|
### Design
|
|
Créer une **Extension Doctrine** (`SearchByNameOrReferenceExtension`) qui intercepte un paramètre `?q=xxx` et ajoute une clause `WHERE name ILIKE %xxx% OR reference ILIKE %xxx%` à la requête. Côté frontend, remplacer `params.set('name', search)` par `params.set('q', search)`.
|
|
|
|
### Changements techniques
|
|
|
|
**Backend — Nouveau fichier** : `src/Doctrine/SearchByNameOrReferenceExtension.php`
|
|
- Implémente `QueryCollectionExtensionInterface`
|
|
- S'applique aux entités `Piece`, `Composant`, `Product`
|
|
- Lit le paramètre `q` depuis la requête HTTP
|
|
- Ajoute `LOWER(o.name) LIKE :searchQ OR LOWER(o.reference) LIKE :searchQ` avec paramètre `%{strtolower(q)}%`
|
|
- **Échappement LIKE** : les caractères `%` et `_` dans l'input utilisateur sont échappés via `addcslashes($q, '%_')` pour éviter des matchs trop larges
|
|
- **`reference` nullable** : les lignes avec `reference = NULL` ne matcheront pas (comportement SQL standard : `NULL LIKE x` = NULL = false), ce qui est le comportement attendu
|
|
- **Pas de conflit** avec le `SearchFilter` existant : le paramètre `q` n'est pas enregistré comme propriété de `SearchFilter`, donc il sera ignoré par celui-ci. Les filtres `name` et `reference` restent disponibles pour d'autres usages.
|
|
|
|
**Frontend — 3 fichiers** (dans la fonction `loadXxx`, remplacer l'appel `params.set('name', search.trim())`) :
|
|
- `frontend/app/composables/usePieces.ts` → `params.set('q', search.trim())`
|
|
- `frontend/app/composables/useComposants.ts` → idem
|
|
- `frontend/app/composables/useProducts.ts` → idem
|
|
|
|
---
|
|
|
|
## Fichiers impactés (résumé)
|
|
|
|
| Fichier | Changement |
|
|
|---------|-----------|
|
|
| `frontend/app/pages/machines/index.vue` | Checkboxes sites + tri alphabétique |
|
|
| `src/Doctrine/SearchByNameOrReferenceExtension.php` | **Nouveau** — Extension Doctrine OR search |
|
|
| `frontend/app/composables/usePieces.ts` | `name` → `q` |
|
|
| `frontend/app/composables/useComposants.ts` | `name` → `q` |
|
|
| `frontend/app/composables/useProducts.ts` | `name` → `q` |
|
|
|
|
## Hors scope
|
|
- La page Parc Machines cherche **déjà** sur nom ET référence côté frontend (filtrage client-side). Pas de changement nécessaire.
|
|
- Aucun changement de placeholder — ils affichent déjà "Nom ou référence…".
|