266 lines
10 KiB
Vue
266 lines
10 KiB
Vue
<template>
|
|
<div class="px-[86px]">
|
|
<div class="flex items-center justify-start gap-10 relative">
|
|
<Icon
|
|
@click="router.push('/')"
|
|
name="gg:arrow-left-o"
|
|
size="44"
|
|
class="cursor-pointer text-primary-500 absolute -left-[60px]"
|
|
/>
|
|
<h1 class="font-bold text-3xl uppercase text-primary-500">Entrée / Sortie</h1>
|
|
</div>
|
|
|
|
<div class="mt-8 grid grid-cols-2 gap-8">
|
|
<section>
|
|
<h2 class="text-xl font-bold uppercase text-primary-500 mb-4">Entrées en attente</h2>
|
|
<UiDataTable
|
|
v-model:page="entryPage"
|
|
v-model:per-page="entryPerPage"
|
|
:columns="entryColumns"
|
|
:items="entries"
|
|
:total-items="totalEntries"
|
|
:loading="entriesLoading"
|
|
row-clickable
|
|
@row-click="goToEntry"
|
|
>
|
|
<template #header-identificationNumber>
|
|
<UiTextInput
|
|
v-model="entryFilters.identificationNumber"
|
|
placeholder="Numéro"
|
|
size="compact"
|
|
/>
|
|
</template>
|
|
<template #header-receptionDate>
|
|
<UiDateMaskedInput v-model="entryDateFilter" placeholder="Date" size="compact" />
|
|
</template>
|
|
<template #header-declaredCount>
|
|
<UiTextInput :model-value="''" placeholder="Déclarés" size="compact" disabled />
|
|
</template>
|
|
<template #header-registeredBovineCount>
|
|
<UiTextInput :model-value="''" placeholder="Saisis" size="compact" disabled />
|
|
</template>
|
|
<template #header-status>
|
|
<UiTextInput :model-value="''" placeholder="Statut" size="compact" disabled />
|
|
</template>
|
|
<template #cell-identificationNumber="{ item }">
|
|
{{ item.identificationNumber }}
|
|
</template>
|
|
<template #cell-receptionDate="{ item }">
|
|
{{ formatDate(item.receptionDate) }}
|
|
</template>
|
|
<template #cell-declaredCount="{ item }">
|
|
{{ item.declaredBovineCount ?? 0 }}
|
|
</template>
|
|
<template #cell-registeredBovineCount="{ item }">
|
|
{{ item.registeredBovineCount ?? 0 }}
|
|
</template>
|
|
<template #cell-status="{ item }">
|
|
<span
|
|
v-if="!item.entryCompleted"
|
|
class="inline-block rounded px-2 py-0.5 text-xs font-semibold bg-yellow-100 text-yellow-700"
|
|
>
|
|
Attente saisie
|
|
</span>
|
|
<span
|
|
v-else
|
|
class="inline-block rounded px-2 py-0.5 text-xs font-semibold bg-orange-100 text-orange-700"
|
|
>
|
|
Attente EDNOTIF
|
|
</span>
|
|
</template>
|
|
</UiDataTable>
|
|
</section>
|
|
|
|
<section>
|
|
<h2 class="text-xl font-bold uppercase text-primary-500 mb-4">Entrées validées</h2>
|
|
<UiDataTable
|
|
v-model:page="validatedPage"
|
|
v-model:per-page="validatedPerPage"
|
|
:columns="validatedColumns"
|
|
:items="validated"
|
|
:total-items="totalValidated"
|
|
:loading="validatedLoading"
|
|
row-clickable
|
|
@row-click="goToBovineInfo"
|
|
>
|
|
<template #header-identificationNumber>
|
|
<UiTextInput
|
|
v-model="validatedFilters.identificationNumber"
|
|
placeholder="Numéro"
|
|
size="compact"
|
|
/>
|
|
</template>
|
|
<template #header-receptionDate>
|
|
<UiDateMaskedInput v-model="validatedDateFilter" placeholder="Date" size="compact" />
|
|
</template>
|
|
<template #header-registeredBovineCount>
|
|
<UiTextInput :model-value="''" placeholder="Saisis" size="compact" disabled />
|
|
</template>
|
|
<template #header-validatedAt>
|
|
<UiTextInput :model-value="''" placeholder="Validée le" size="compact" disabled />
|
|
</template>
|
|
<template #header-status>
|
|
<UiTextInput :model-value="''" placeholder="Statut" size="compact" disabled />
|
|
</template>
|
|
<template #cell-identificationNumber="{ item }">
|
|
{{ item.identificationNumber }}
|
|
</template>
|
|
<template #cell-receptionDate="{ item }">
|
|
{{ formatDate(item.receptionDate) }}
|
|
</template>
|
|
<template #cell-registeredBovineCount="{ item }">
|
|
{{ item.registeredBovineCount ?? 0 }}
|
|
</template>
|
|
<template #cell-validatedAt="{ item }">
|
|
{{ formatDate(item.validatedAt) }}
|
|
</template>
|
|
<template #cell-status>
|
|
<span
|
|
class="inline-block rounded px-2 py-0.5 text-xs font-semibold bg-green-100 text-green-700"
|
|
>
|
|
Validée
|
|
</span>
|
|
</template>
|
|
</UiDataTable>
|
|
</section>
|
|
</div>
|
|
|
|
<div class="mt-12 mb-16 grid grid-cols-2 gap-8">
|
|
<section>
|
|
<h2 class="text-xl font-bold uppercase text-primary-500 mb-4">Sorties en attente</h2>
|
|
<div class="rounded border border-dashed border-slate-300 p-8 text-center text-slate-500">
|
|
À venir
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h2 class="text-xl font-bold uppercase text-primary-500 mb-4">Sorties validées</h2>
|
|
<div class="rounded border border-dashed border-slate-300 p-8 text-center text-slate-500">
|
|
À venir
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { ReceptionData } from '~/services/dto/reception-data'
|
|
import { useDataTableServerState } from '~/composables/useDataTableServerState'
|
|
|
|
const router = useRouter()
|
|
|
|
const {
|
|
items: entries,
|
|
totalItems: totalEntries,
|
|
page: entryPage,
|
|
perPage: entryPerPage,
|
|
filters: entryFilters,
|
|
loading: entriesLoading,
|
|
reload
|
|
} = useDataTableServerState<ReceptionData>(
|
|
'receptions',
|
|
{
|
|
'isValid': 'true',
|
|
'exists[validatedAt]': 'false',
|
|
'receptionType.code': 'BOVINS',
|
|
'identificationNumber': '',
|
|
'receptionDate[after]': '',
|
|
'receptionDate[strictly_before]': ''
|
|
},
|
|
{ initialPerPage: 5 }
|
|
)
|
|
|
|
const {
|
|
items: validated,
|
|
totalItems: totalValidated,
|
|
page: validatedPage,
|
|
perPage: validatedPerPage,
|
|
filters: validatedFilters,
|
|
loading: validatedLoading,
|
|
reload: reloadValidated
|
|
} = useDataTableServerState<ReceptionData>(
|
|
'receptions',
|
|
{
|
|
'isValid': 'true',
|
|
'exists[validatedAt]': 'true',
|
|
'receptionType.code': 'BOVINS',
|
|
'identificationNumber': '',
|
|
'receptionDate[after]': '',
|
|
'receptionDate[strictly_before]': ''
|
|
},
|
|
{ initialPerPage: 5 }
|
|
)
|
|
|
|
const addOneDay = (dateString: string): string => {
|
|
const [year, month, day] = dateString.split('-').map(Number)
|
|
const next = new Date(Date.UTC(year, month - 1, day + 1))
|
|
return next.toISOString().slice(0, 10)
|
|
}
|
|
|
|
const entryDateFilter = computed<string>({
|
|
get: () => (entryFilters.value['receptionDate[after]'] as string) ?? '',
|
|
set: (value: string) => {
|
|
if (!value) {
|
|
entryFilters.value['receptionDate[after]'] = ''
|
|
entryFilters.value['receptionDate[strictly_before]'] = ''
|
|
return
|
|
}
|
|
entryFilters.value['receptionDate[after]'] = value
|
|
entryFilters.value['receptionDate[strictly_before]'] = addOneDay(value)
|
|
}
|
|
})
|
|
|
|
const validatedDateFilter = computed<string>({
|
|
get: () => (validatedFilters.value['receptionDate[after]'] as string) ?? '',
|
|
set: (value: string) => {
|
|
if (!value) {
|
|
validatedFilters.value['receptionDate[after]'] = ''
|
|
validatedFilters.value['receptionDate[strictly_before]'] = ''
|
|
return
|
|
}
|
|
validatedFilters.value['receptionDate[after]'] = value
|
|
validatedFilters.value['receptionDate[strictly_before]'] = addOneDay(value)
|
|
}
|
|
})
|
|
|
|
const entryColumns = [
|
|
{ key: 'identificationNumber', label: 'Numéro', width: '75px' },
|
|
{ key: 'receptionDate', label: 'Date', width: '75px' },
|
|
{ key: 'declaredCount', label: 'Déclarés', width: '75px' },
|
|
{ key: 'registeredBovineCount', label: 'Saisis', width: '70px' },
|
|
{ key: 'status', label: 'Statut', width: '1fr' }
|
|
]
|
|
|
|
const validatedColumns = [
|
|
{ key: 'identificationNumber', label: 'Numéro', width: '75px' },
|
|
{ key: 'receptionDate', label: 'Date', width: '75px' },
|
|
{ key: 'registeredBovineCount', label: 'Saisis', width: '50px' },
|
|
{ key: 'validatedAt', label: 'Validée le', width: '75px' },
|
|
{ key: 'status', label: 'Statut', width: '1fr' }
|
|
]
|
|
|
|
const formatDate = (date: string | null | undefined) => {
|
|
if (!date) return '—'
|
|
const d = new Date(date.replace(' ', 'T'))
|
|
if (isNaN(d.getTime())) return date
|
|
return d.toLocaleDateString('fr-FR', {
|
|
day: '2-digit',
|
|
month: '2-digit',
|
|
year: 'numeric'
|
|
})
|
|
}
|
|
|
|
const goToEntry = (reception: ReceptionData) => {
|
|
router.push(`/entry-exit/entry/${reception.id}`)
|
|
}
|
|
|
|
const goToBovineInfo = (reception: ReceptionData) => {
|
|
router.push(`/entry-exit/bovine-info/${reception.id}`)
|
|
}
|
|
|
|
onMounted(() => {
|
|
reload()
|
|
reloadValidated()
|
|
})
|
|
</script>
|