refactor(transport) : onglet Qualimat en MalioDataTable paginé, recherche branchée sur le nom (ERP-166)
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 3m1s
Pull Request — Quality gate / Frontend (lint + Vitest + build) (pull_request) Successful in 1m44s

This commit is contained in:
2026-06-16 18:02:16 +02:00
parent d6d2144cc1
commit 388d39a379
4 changed files with 144 additions and 150 deletions
@@ -1,6 +1,4 @@
import { ref } from 'vue'
import { debounce } from '~/shared/utils/debounce'
import type { HydraCollection } from '~/shared/utils/api'
import { usePaginatedList } from '~/shared/composables/usePaginatedList'
/**
* Ligne du référentiel QUALIMAT renvoyée par la saisie assistée (groupe
@@ -20,57 +18,23 @@ export interface QualimatCarrierRow {
status: string | null
}
/** Délai de debounce de la recherche (ms) — une requête après la dernière frappe. */
const SEARCH_DEBOUNCE_MS = 300
/** Filtre de la recherche QUALIMAT (branché sur le nom du transporteur). */
export interface QualimatSearchFilters {
search?: string
}
/**
* Saisie assistée QUALIMAT (M4 Transport, ERP-166 — RG-4.01 / spec-back § 4.7).
*
* `GET /api/qualimat_carriers?search=` : référentiel en LECTURE SEULE, lignes
* actives uniquement (filtré côté serveur), recherche fuzzy nom + siret. Alimente
* le tableau de sélection de l'onglet Qualimat ; la ligne choisie est copiée dans
* le formulaire principal (cf. `useCarrierForm.applyQualimatSelection`).
* actives uniquement (filtré côté serveur), recherche fuzzy nom + siret. Simple
* enveloppe de `usePaginatedList` (règle frontend : toute GetCollection passe par
* ce composable — pagination Hydra, état 100 % local) consommée par le
* `MalioDataTable` de l'onglet Qualimat. Le filtre `search` est piloté par le nom
* saisi dans le formulaire principal (pas de champ de recherche dédié).
*
* Volontairement PAR INSTANCE (état local à l'écran d'ajout). `search()` est
* debouncé (anti-spam réseau) ; `fetchNow()` expose l'appel immédiat (montage /
* tests).
* Volontairement PAR INSTANCE (état local à l'écran d'ajout).
*/
export function useQualimatSearch() {
const api = useApi()
const results = ref<QualimatCarrierRow[]>([])
const loading = ref(false)
/** Lance immédiatement la recherche (sans debounce). */
async function fetchNow(term: string): Promise<void> {
loading.value = true
try {
const data = await api.get<HydraCollection<QualimatCarrierRow>>(
'/qualimat_carriers',
{ search: term.trim() },
{ headers: { Accept: 'application/ld+json' }, toast: false },
)
results.value = data.member ?? []
}
catch {
// Échec réseau / 403 : on vide les résultats, pas de toast (la recherche
// assistée est non bloquante — l'utilisateur peut saisir manuellement).
results.value = []
}
finally {
loading.value = false
}
}
// Recherche debouncée branchée sur le champ de recherche de l'onglet Qualimat.
const search = debounce((term: string) => {
void fetchNow(term)
}, SEARCH_DEBOUNCE_MS)
return {
results,
loading,
search,
fetchNow,
}
return usePaginatedList<QualimatCarrierRow, QualimatSearchFilters>({ url: '/qualimat_carriers' })
}