feat : améliorations page inventory et filtre date masqué

- Colonnes Bâtiment et Case ajoutées sur inventory (inline buildingCase via readableLink)
- Bouton Rafraîchir repositionné dans l'en-tête du tableau (pattern case.vue)
- Sync : date du jour pour l'appel EDNOTIF, extraction de la dernière exit date
- UiDateMaskedInput : nouveau composant date masqué JJ/MM/AAAA
- Propagation du masque date sur tous les datatables (reception, shipment, case, inventory)
- Label de colonne "Date et heure" raccourci en "Date"
- Champ exitDate ajouté en back (caché côté front, prêt pour future feature)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-24 09:04:08 +02:00
parent 22797791dc
commit 9d3cfd10db
13 changed files with 229 additions and 39 deletions

View File

@@ -59,7 +59,7 @@
/>
</template>
<template #header-arrivalDate>
<UiDateInput v-model="arrivalDateFilter" size="compact" />
<UiDateMaskedInput v-model="arrivalDateFilter" placeholder="Date d'arrivée" size="compact" />
</template>
<template #cell-arrivalDate="{ item }">
{{ formatDate(item.arrivalDate) }}

View File

@@ -1,22 +1,27 @@
<template>
<div class="flex items-center justify-between gap-4">
<div class="flex items-center gap-10">
<Icon @click="router.push('/')" name="gg:arrow-left-o" size="44" class="cursor-pointer text-primary-500"/>
<h1 class="text-3xl font-bold uppercase text-primary-500">Inventaire bovins</h1>
</div>
<button
v-if="auth.isAdmin"
type="button"
:disabled="syncing"
class="inline-flex items-center gap-2 rounded bg-primary-500 px-4 h-[50px] text-white uppercase text-lg hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-60"
@click="syncInventory"
>
<Icon name="mdi:sync" size="24" :class="syncing ? 'animate-spin' : ''" />
{{ syncing ? 'Synchronisation…' : 'Rafraîchir' }}
</button>
</div>
<div class="px-[86px]">
<div class="flex items-center justify-between relative">
<div class="flex flex-row absolute -left-[60px]">
<Icon
@click="router.push('/')"
name="gg:arrow-left-o"
size="44"
class="cursor-pointer text-primary-500"
/>
</div>
<h1 class="font-bold text-3xl uppercase text-primary-500">Inventaire bovins</h1>
<button
v-if="auth.isAdmin"
type="button"
:disabled="syncing"
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-6 rounded hover:opacity-80 gap-2 disabled:cursor-not-allowed disabled:opacity-60"
@click="syncInventory"
>
<Icon name="mdi:sync" size="28" :class="syncing ? 'animate-spin' : ''" />
Rafraîchir
</button>
</div>
<div class="mt-6 mb-16">
<UiDataTable
v-model:page="page"
@@ -43,13 +48,13 @@
<template #header-sex>
<UiSelect
v-model="filters.sex"
placeholder="Sex"
placeholder="Sexe"
:options="sexOptions"
size="compact"
/>
</template>
<template #header-birthDate>
<UiDateInput v-model="birthDateFilter" size="compact" />
<UiDateMaskedInput v-model="birthDateFilter" size="compact" placeholder="Né le" />
</template>
<template #header-breedCode>
<UiTextInput
@@ -59,7 +64,13 @@
/>
</template>
<template #header-arrivalDate>
<UiDateInput v-model="arrivalDateFilter" size="compact" />
<UiDateMaskedInput v-model="arrivalDateFilter" size="compact" placeholder="Entrée le" />
</template>
<template #header-buildingCase.building.label>
<UiTextInput :model-value="''" placeholder="Bâtiment" size="compact" disabled />
</template>
<template #header-buildingCase.caseNumber>
<UiTextInput :model-value="''" placeholder="Case" size="compact" disabled />
</template>
<template #cell-birthDate="{ item }">
{{ formatDate(item.birthDate) }}
@@ -67,11 +78,18 @@
<template #cell-arrivalDate="{ item }">
{{ formatDate(item.arrivalDate) }}
</template>
<template #cell-buildingCase.building.label="{ item }">
{{ item.buildingCase?.building?.label ?? '—' }}
</template>
<template #cell-buildingCase.caseNumber="{ item }">
{{ item.buildingCase?.caseNumber ?? '—' }}
</template>
</UiDataTable>
</div>
</div>
</template>
<script setup lang="ts">
import type { BovineData } from '~/services/dto/bovine-data'
import { useAuthStore } from '~/stores/auth'
@@ -160,9 +178,11 @@ const birthDateFilter = singleDateFilter('birthDate[after]', 'birthDate[strictly
const columns = [
{ key: 'nationalNumber', label: 'N° National', width: '160px' },
{ key: 'workNumber', label: 'N° Travail', width: '110px' },
{ key: 'sex', label: 'Sex', width: '90px' },
{ key: 'sex', label: 'Sexe', width: '90px' },
{ key: 'birthDate', label: 'Né le', width: '120px' },
{ key: 'breedCode', label: 'Race' },
{ key: 'buildingCase.building.label', label: 'Bâtiment' },
{ key: 'buildingCase.caseNumber', label: 'Case', width: '80px' },
{ key: 'arrivalDate', label: 'Entrée le', width: '120px' }
]

View File

@@ -24,8 +24,9 @@
/>
</template>
<template #header-receptionDate>
<UiDateInput
<UiDateMaskedInput
v-model="receptionDateFilter"
placeholder="Date"
size="compact"
/>
</template>
@@ -119,7 +120,7 @@ const receptionDateFilter = computed<string>({
const columns = [
{ key: 'identificationNumber', label: 'Numéro', width: '75px' },
{ key: 'receptionDate', label: 'Date et heure', width: '120px' },
{ key: 'receptionDate', label: 'Date', width: '120px' },
{ key: 'supplier.name', label: 'Fournisseur', width: '1.5fr' },
{ key: 'address.fullAddress', label: 'Adresse', width: '2fr' },
{ key: 'receptionType.label', label: 'Type réception', width: '0.9fr' },

View File

@@ -18,7 +18,7 @@
@row-click="goToReception"
>
<template #header-receptionDate>
<UiDateInput v-model="receptionDateFilter" size="compact" />
<UiDateMaskedInput v-model="receptionDateFilter" placeholder="Date" size="compact" />
</template>
<template #header-supplier.name>
<UiTextInput
@@ -122,7 +122,7 @@ const receptionDateFilter = computed<string>({
})
const columns = [
{ key: 'receptionDate', label: 'Date et heure', width: '120px' },
{ key: 'receptionDate', label: 'Date', width: '120px' },
{ key: 'supplier.name', label: 'Fournisseur', width: '1.5fr' },
{ key: 'address.fullAddress', label: 'Adresse', width: '2fr' },
{ key: 'receptionType.label', label: 'Type réception', width: '1.1fr' },

View File

@@ -24,7 +24,7 @@
/>
</template>
<template #header-shipmentDate>
<UiDateInput v-model="shipmentDateFilter" size="compact" />
<UiDateMaskedInput v-model="shipmentDateFilter" placeholder="Date" size="compact" />
</template>
<template #header-customer.name>
<UiTextInput

View File

@@ -18,7 +18,7 @@
@row-click="goToShipment"
>
<template #header-shipmentDate>
<UiDateInput v-model="shipmentDateFilter" size="compact" />
<UiDateMaskedInput v-model="shipmentDateFilter" placeholder="Date" size="compact" />
</template>
<template #header-customer.name>
<UiTextInput
@@ -134,7 +134,7 @@ const shipmentDateFilter = computed<string>({
})
const columns = [
{ key: 'shipmentDate', label: 'Date et heure', width: '120px' },
{ key: 'shipmentDate', label: 'Date', width: '120px' },
{ key: 'customer.name', label: 'Client', width: '1.5fr' },
{ key: 'address.fullAddress', label: 'Adresse', width: '2fr' },
{ key: 'shipmentType.label', label: "Type d'expé.", width: '1.1fr' },