fix(front) : aligner le filtre archives des répertoires fournisseurs et prestataires sur client (ERP-173)
This commit is contained in:
@@ -70,7 +70,7 @@
|
||||
"categories": "Catégories",
|
||||
"sites": "Sites",
|
||||
"status": "Statut",
|
||||
"includeArchived": "Inclure les archivés",
|
||||
"archivedOnly": "Voir les archivés",
|
||||
"apply": "Voir les résultats",
|
||||
"reset": "Réinitialiser"
|
||||
},
|
||||
@@ -384,7 +384,7 @@
|
||||
"categories": "Catégories",
|
||||
"sites": "Sites",
|
||||
"status": "Statut",
|
||||
"includeArchived": "Inclure les archivés",
|
||||
"archivedOnly": "Voir les archivés",
|
||||
"apply": "Voir les résultats",
|
||||
"reset": "Réinitialiser"
|
||||
},
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('useSuppliersRepository', () => {
|
||||
search: 'acme',
|
||||
'categoryCode[]': ['NEGOCIANT', 'TRANSPORTEUR'],
|
||||
'siteId[]': ['86', '17'],
|
||||
includeArchived: true,
|
||||
archivedOnly: true,
|
||||
},
|
||||
{ replace: true },
|
||||
)
|
||||
@@ -63,7 +63,7 @@ describe('useSuppliersRepository', () => {
|
||||
search: 'acme',
|
||||
'categoryCode[]': ['NEGOCIANT', 'TRANSPORTEUR'],
|
||||
'siteId[]': ['86', '17'],
|
||||
includeArchived: true,
|
||||
archivedOnly: true,
|
||||
page: 1,
|
||||
itemsPerPage: 10,
|
||||
},
|
||||
@@ -73,7 +73,7 @@ describe('useSuppliersRepository', () => {
|
||||
|
||||
it('repasse a une query propre apres reinitialisation des filtres', async () => {
|
||||
const repo = useSuppliersRepository()
|
||||
await repo.setFilters({ search: 'acme', includeArchived: true }, { replace: true })
|
||||
await repo.setFilters({ search: 'acme', archivedOnly: true }, { replace: true })
|
||||
await repo.setFilters({}, { replace: true })
|
||||
|
||||
expect(mockGet).toHaveBeenLastCalledWith(
|
||||
|
||||
@@ -172,16 +172,16 @@ describe('Répertoire fournisseurs (page /suppliers)', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('repercute le filtre « Inclure les archivés » dans setFilters sans toucher l\'URL', async () => {
|
||||
it('repercute le filtre « Voir les archivés » dans setFilters sans toucher l\'URL', async () => {
|
||||
const wrapper = mountPage()
|
||||
await flushPromises()
|
||||
|
||||
// Coche « Inclure les archivés » puis applique les filtres.
|
||||
await wrapper.find('input[data-id="filter-include-archived"]').setValue(true)
|
||||
// Coche « Voir les archivés » puis applique les filtres.
|
||||
await wrapper.find('input[data-id="filter-archived-only"]').setValue(true)
|
||||
await wrapper.find('[data-label="commercial.suppliers.filters.apply"]').trigger('click')
|
||||
|
||||
expect(mockSetFilters).toHaveBeenLastCalledWith(
|
||||
{ includeArchived: true },
|
||||
{ archivedOnly: true },
|
||||
{ replace: true },
|
||||
)
|
||||
// Etat 100 % local (regle n°6) : aucune navigation/query string declenchee.
|
||||
@@ -192,7 +192,7 @@ describe('Répertoire fournisseurs (page /suppliers)', () => {
|
||||
const wrapper = mountPage()
|
||||
await flushPromises()
|
||||
|
||||
await wrapper.find('input[data-id="filter-include-archived"]').setValue(true)
|
||||
await wrapper.find('input[data-id="filter-archived-only"]').setValue(true)
|
||||
await wrapper.find('[data-label="commercial.suppliers.filters.apply"]').trigger('click')
|
||||
|
||||
// Le libelle du bouton Filtrer porte le compteur (1 filtre actif).
|
||||
|
||||
@@ -128,13 +128,13 @@
|
||||
</div>
|
||||
</MalioAccordionItem>
|
||||
|
||||
<!-- Statut : bool unique. Coche = inclut aussi les archives (sinon actifs seuls). -->
|
||||
<!-- Statut : bool unique. Coche = archives uniquement, sinon actifs. -->
|
||||
<MalioAccordionItem :title="t('commercial.suppliers.filters.status')" value="status">
|
||||
<MalioCheckbox
|
||||
id="filter-include-archived"
|
||||
:label="t('commercial.suppliers.filters.includeArchived')"
|
||||
:model-value="draftIncludeArchived"
|
||||
@update:model-value="(val: boolean) => draftIncludeArchived = val"
|
||||
id="filter-archived-only"
|
||||
:label="t('commercial.suppliers.filters.archivedOnly')"
|
||||
:model-value="draftArchivedOnly"
|
||||
@update:model-value="(val: boolean) => draftArchivedOnly = val"
|
||||
/>
|
||||
</MalioAccordionItem>
|
||||
</MalioAccordion>
|
||||
@@ -254,12 +254,12 @@ const filterDrawerOpen = ref(false)
|
||||
const draftSearch = ref('')
|
||||
const draftCategoryCodes = ref<string[]>([])
|
||||
const draftSiteIds = ref<string[]>([])
|
||||
const draftIncludeArchived = ref(false)
|
||||
const draftArchivedOnly = ref(false)
|
||||
|
||||
const appliedSearch = ref('')
|
||||
const appliedCategoryCodes = ref<string[]>([])
|
||||
const appliedSiteIds = ref<string[]>([])
|
||||
const appliedIncludeArchived = ref(false)
|
||||
const appliedArchivedOnly = ref(false)
|
||||
|
||||
// Options des selects multi, chargees une fois (referentiels courts).
|
||||
const categoryOptions = ref<FilterOption[]>([])
|
||||
@@ -270,7 +270,7 @@ const activeFilterCount = computed(() => {
|
||||
if (appliedSearch.value.trim() !== '') count++
|
||||
if (appliedCategoryCodes.value.length > 0) count++
|
||||
if (appliedSiteIds.value.length > 0) count++
|
||||
if (appliedIncludeArchived.value) count++
|
||||
if (appliedArchivedOnly.value) count++
|
||||
return count
|
||||
})
|
||||
|
||||
@@ -285,7 +285,7 @@ function openFilters(): void {
|
||||
draftSearch.value = appliedSearch.value
|
||||
draftCategoryCodes.value = [...appliedCategoryCodes.value]
|
||||
draftSiteIds.value = [...appliedSiteIds.value]
|
||||
draftIncludeArchived.value = appliedIncludeArchived.value
|
||||
draftArchivedOnly.value = appliedArchivedOnly.value
|
||||
filterDrawerOpen.value = true
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ function buildFilterPayload(): Record<string, string | string[] | boolean> {
|
||||
if (appliedSearch.value.trim() !== '') payload.search = appliedSearch.value.trim()
|
||||
if (appliedCategoryCodes.value.length > 0) payload['categoryCode[]'] = [...appliedCategoryCodes.value]
|
||||
if (appliedSiteIds.value.length > 0) payload['siteId[]'] = [...appliedSiteIds.value]
|
||||
if (appliedIncludeArchived.value) payload.includeArchived = true
|
||||
if (appliedArchivedOnly.value) payload.archivedOnly = true
|
||||
return payload
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@ function applyFilters(): void {
|
||||
appliedSearch.value = draftSearch.value.trim()
|
||||
appliedCategoryCodes.value = [...draftCategoryCodes.value]
|
||||
appliedSiteIds.value = [...draftSiteIds.value]
|
||||
appliedIncludeArchived.value = draftIncludeArchived.value
|
||||
appliedArchivedOnly.value = draftArchivedOnly.value
|
||||
|
||||
setFilters(buildFilterPayload(), { replace: true })
|
||||
filterDrawerOpen.value = false
|
||||
@@ -333,12 +333,12 @@ function resetFilters(): void {
|
||||
draftSearch.value = ''
|
||||
draftCategoryCodes.value = []
|
||||
draftSiteIds.value = []
|
||||
draftIncludeArchived.value = false
|
||||
draftArchivedOnly.value = false
|
||||
|
||||
appliedSearch.value = ''
|
||||
appliedCategoryCodes.value = []
|
||||
appliedSiteIds.value = []
|
||||
appliedIncludeArchived.value = false
|
||||
appliedArchivedOnly.value = false
|
||||
|
||||
setFilters({}, { replace: true })
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ vi.stubGlobal('useApi', () => ({ get: mockApiGet }))
|
||||
* - l'enveloppe Hydra (member / totalItems) est consommee
|
||||
* - le header `Accept: application/ld+json` est envoye (sinon API Platform 4
|
||||
* renvoie un tableau plat sans pagination)
|
||||
* - EXCLUSION DES ARCHIVES PAR DEFAUT : aucun `includeArchived` n'est envoye
|
||||
* - EXCLUSION DES ARCHIVES PAR DEFAUT : aucun `archivedOnly` n'est envoye
|
||||
* tant que l'utilisateur ne coche pas le filtre (le back masque alors les
|
||||
* archives) ; le filtre `includeArchived` est bien transmis une fois applique.
|
||||
* archives) ; le filtre `archivedOnly` est bien transmis une fois applique.
|
||||
*/
|
||||
describe('useProvidersRepository', () => {
|
||||
beforeEach(() => {
|
||||
@@ -53,26 +53,26 @@ describe('useProvidersRepository', () => {
|
||||
expect(repo.totalItems.value).toBe(1)
|
||||
})
|
||||
|
||||
it('exclut les archives par defaut : aucun includeArchived au premier fetch', async () => {
|
||||
it('exclut les archives par defaut : aucun archivedOnly au premier fetch', async () => {
|
||||
mockApiGet.mockResolvedValueOnce({ member: PAGE, totalItems: 1 })
|
||||
const repo = useProvidersRepository()
|
||||
|
||||
await repo.fetch()
|
||||
|
||||
const query = mockApiGet.mock.calls[0][1] as Record<string, unknown>
|
||||
expect(query.includeArchived).toBeUndefined()
|
||||
expect(query.archivedOnly).toBeUndefined()
|
||||
})
|
||||
|
||||
it('transmet includeArchived une fois le filtre applique (retour page 1)', async () => {
|
||||
it('transmet archivedOnly une fois le filtre applique (retour page 1)', async () => {
|
||||
mockApiGet.mockResolvedValueOnce({ member: PAGE, totalItems: 1 })
|
||||
const repo = useProvidersRepository()
|
||||
await repo.fetch()
|
||||
|
||||
mockApiGet.mockResolvedValueOnce({ member: PAGE, totalItems: 1 })
|
||||
await repo.setFilters({ includeArchived: true })
|
||||
await repo.setFilters({ archivedOnly: true })
|
||||
|
||||
expect(repo.currentPage.value).toBe(1)
|
||||
const query = mockApiGet.mock.calls.at(-1)?.[1] as Record<string, unknown>
|
||||
expect(query.includeArchived).toBe(true)
|
||||
expect(query.archivedOnly).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -45,10 +45,11 @@ export interface Provider {
|
||||
* sur la ressource `/providers` (pagination serveur obligatoire ; jamais de
|
||||
* chargement integral en memoire). Miroir de `useSuppliersRepository` (M2).
|
||||
*
|
||||
* Les filtres (recherche, categories, sites, inclusion des archives) sont pilotes
|
||||
* par la page via `setFilters` du composable partage — la remise en page 1 est
|
||||
* garantie. Par defaut, aucun `includeArchived` n'est envoye : le back masque
|
||||
* donc les prestataires archives (exclusion par defaut, spec-back § 2.11).
|
||||
* Les filtres (recherche, categories, sites, archives) sont pilotes par la page
|
||||
* via `setFilters` du composable partage — la remise en page 1 est garantie. Par
|
||||
* defaut, aucun `archivedOnly` n'est envoye : le back masque donc les prestataires
|
||||
* archives (exclusion par defaut, spec-back § 2.11). Cocher « Voir les archivés »
|
||||
* envoie `archivedOnly=true` → seules les archives sont listees (aligne sur Client).
|
||||
*
|
||||
* Le cloisonnement par site est applique AUTOMATIQUEMENT cote back (§ 2.13) en
|
||||
* fonction de l'utilisateur — rien a filtrer cote front.
|
||||
|
||||
@@ -129,13 +129,13 @@
|
||||
</div>
|
||||
</MalioAccordionItem>
|
||||
|
||||
<!-- Statut : bool unique. Coche = inclut aussi les archives (sinon actifs seuls). -->
|
||||
<!-- Statut : bool unique. Coche = archives uniquement, sinon actifs. -->
|
||||
<MalioAccordionItem :title="t('technique.providers.filters.status')" value="status">
|
||||
<MalioCheckbox
|
||||
id="filter-include-archived"
|
||||
:label="t('technique.providers.filters.includeArchived')"
|
||||
:model-value="draftIncludeArchived"
|
||||
@update:model-value="(val: boolean) => draftIncludeArchived = val"
|
||||
id="filter-archived-only"
|
||||
:label="t('technique.providers.filters.archivedOnly')"
|
||||
:model-value="draftArchivedOnly"
|
||||
@update:model-value="(val: boolean) => draftArchivedOnly = val"
|
||||
/>
|
||||
</MalioAccordionItem>
|
||||
</MalioAccordion>
|
||||
@@ -258,12 +258,12 @@ const filterDrawerOpen = ref(false)
|
||||
const draftSearch = ref('')
|
||||
const draftCategoryCodes = ref<string[]>([])
|
||||
const draftSiteIds = ref<string[]>([])
|
||||
const draftIncludeArchived = ref(false)
|
||||
const draftArchivedOnly = ref(false)
|
||||
|
||||
const appliedSearch = ref('')
|
||||
const appliedCategoryCodes = ref<string[]>([])
|
||||
const appliedSiteIds = ref<string[]>([])
|
||||
const appliedIncludeArchived = ref(false)
|
||||
const appliedArchivedOnly = ref(false)
|
||||
|
||||
// Options des selects multi, chargees une fois (referentiels courts).
|
||||
const categoryOptions = ref<FilterOption[]>([])
|
||||
@@ -274,7 +274,7 @@ const activeFilterCount = computed(() => {
|
||||
if (appliedSearch.value.trim() !== '') count++
|
||||
if (appliedCategoryCodes.value.length > 0) count++
|
||||
if (appliedSiteIds.value.length > 0) count++
|
||||
if (appliedIncludeArchived.value) count++
|
||||
if (appliedArchivedOnly.value) count++
|
||||
return count
|
||||
})
|
||||
|
||||
@@ -289,7 +289,7 @@ function openFilters(): void {
|
||||
draftSearch.value = appliedSearch.value
|
||||
draftCategoryCodes.value = [...appliedCategoryCodes.value]
|
||||
draftSiteIds.value = [...appliedSiteIds.value]
|
||||
draftIncludeArchived.value = appliedIncludeArchived.value
|
||||
draftArchivedOnly.value = appliedArchivedOnly.value
|
||||
filterDrawerOpen.value = true
|
||||
}
|
||||
|
||||
@@ -315,7 +315,7 @@ function buildFilterPayload(): Record<string, string | string[] | boolean> {
|
||||
if (appliedSearch.value.trim() !== '') payload.search = appliedSearch.value.trim()
|
||||
if (appliedCategoryCodes.value.length > 0) payload['categoryCode[]'] = [...appliedCategoryCodes.value]
|
||||
if (appliedSiteIds.value.length > 0) payload['siteId[]'] = [...appliedSiteIds.value]
|
||||
if (appliedIncludeArchived.value) payload.includeArchived = true
|
||||
if (appliedArchivedOnly.value) payload.archivedOnly = true
|
||||
return payload
|
||||
}
|
||||
|
||||
@@ -325,7 +325,7 @@ function applyFilters(): void {
|
||||
appliedSearch.value = draftSearch.value.trim()
|
||||
appliedCategoryCodes.value = [...draftCategoryCodes.value]
|
||||
appliedSiteIds.value = [...draftSiteIds.value]
|
||||
appliedIncludeArchived.value = draftIncludeArchived.value
|
||||
appliedArchivedOnly.value = draftArchivedOnly.value
|
||||
|
||||
setFilters(buildFilterPayload(), { replace: true })
|
||||
filterDrawerOpen.value = false
|
||||
@@ -337,12 +337,12 @@ function resetFilters(): void {
|
||||
draftSearch.value = ''
|
||||
draftCategoryCodes.value = []
|
||||
draftSiteIds.value = []
|
||||
draftIncludeArchived.value = false
|
||||
draftArchivedOnly.value = false
|
||||
|
||||
appliedSearch.value = ''
|
||||
appliedCategoryCodes.value = []
|
||||
appliedSiteIds.value = []
|
||||
appliedIncludeArchived.value = false
|
||||
appliedArchivedOnly.value = false
|
||||
|
||||
setFilters({}, { replace: true })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user