feat(front) : add usePaginatedList composable + paginate all admin lists via MalioDataTable
- frontend/shared/composables/usePaginatedList.ts : composable generique de liste paginee serveur (Hydra), branche directement sur MalioDataTable - 22 tests Vitest (navigation, bornes, parse Hydra, hors-borne, reset, filtres, tri, swallow erreur) - Migration des pages admin existantes : sites, users, roles, categories - Refactor de useCategoriesAdmin pour ne porter que le referentiel CategoryType (charge en une fois via ?pagination=false) - Etat page/tri/filtre 100% local dans le composable (respect regle ABSOLUE n°6 — pas de persistance URL) - Section dediee dans .claude/rules/frontend.md documentant le pattern obligatoire pour toute nouvelle liste ERP-73 — volet front de la pagination, depend du back ERP-72 deja merge.
This commit is contained in:
@@ -13,14 +13,19 @@
|
||||
</template>
|
||||
</PageHeader>
|
||||
|
||||
<!-- Table des sites -->
|
||||
<!-- Table des sites — pagination serveur via usePaginatedList (#73). -->
|
||||
<MalioDataTable
|
||||
:columns="columns"
|
||||
:items="siteItems"
|
||||
:total-items="sites.length"
|
||||
:total-items="totalItems"
|
||||
:page="currentPage"
|
||||
:per-page="itemsPerPage"
|
||||
:per-page-options="itemsPerPageOptions"
|
||||
:row-clickable="canManage"
|
||||
:empty-message="t('admin.sites.noSites')"
|
||||
@row-click="onRowClick"
|
||||
@update:page="goToPage"
|
||||
@update:per-page="setItemsPerPage"
|
||||
>
|
||||
<template #cell-color="{ item }">
|
||||
<span class="inline-flex items-center gap-2">
|
||||
@@ -67,8 +72,20 @@ const canManage = computed(() => can('sites.manage'))
|
||||
|
||||
useHead({ title: t('admin.sites.title') })
|
||||
|
||||
const sites = ref<Site[]>([])
|
||||
const loading = ref(false)
|
||||
// Pagination serveur via le composable partage (#73). Aucun OrderFilter
|
||||
// declare cote API Platform sur Site, donc on s'appuie sur le tri par
|
||||
// defaut du repository (id ASC). Le composable est neanmoins pret a
|
||||
// recevoir un `defaultSort` ou des filtres le jour ou l'API les expose.
|
||||
const {
|
||||
items: sites,
|
||||
totalItems,
|
||||
currentPage,
|
||||
itemsPerPage,
|
||||
itemsPerPageOptions,
|
||||
fetch: loadSites,
|
||||
goToPage,
|
||||
setItemsPerPage,
|
||||
} = usePaginatedList<Site>({ url: '/sites' })
|
||||
|
||||
const columns = [
|
||||
{ key: 'name', label: t('admin.sites.table.name') },
|
||||
@@ -107,24 +124,6 @@ const deleteModalOpen = ref(false)
|
||||
const siteToDelete = ref<Site | null>(null)
|
||||
const deleting = ref(false)
|
||||
|
||||
async function loadSites() {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await api.get<{ member: Site[] }>(
|
||||
'/sites',
|
||||
{ itemsPerPage: 999 },
|
||||
{ toast: false },
|
||||
)
|
||||
sites.value = data.member
|
||||
} catch {
|
||||
// Reset sur echec pour ne pas afficher de donnees stale (ancienne
|
||||
// requete reussie avant une perte reseau ou 403).
|
||||
sites.value = []
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function openCreateDrawer() {
|
||||
selectedSite.value = null
|
||||
drawerOpen.value = true
|
||||
|
||||
Reference in New Issue
Block a user