feat : étape 4/5 - bouton Rafraîchir l'inventaire
- Admin only avec confirmation window.confirm au clic - Loader sur le bouton pendant l'appel POST - Toast de succès avec les stats (créés, maj, sortis, total) - reload() du tableau après succès Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center justify-start gap-10">
|
<div class="flex items-center justify-between gap-4">
|
||||||
<Icon @click="router.push('/')" name="gg:arrow-left-o" size="44" class="cursor-pointer text-primary-500"/>
|
<div class="flex items-center gap-10">
|
||||||
<h1 class="text-3xl font-bold uppercase text-primary-500">Inventaire bovins</h1>
|
<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>
|
||||||
|
|
||||||
<div class="px-[86px]">
|
<div class="px-[86px]">
|
||||||
@@ -62,9 +74,44 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { BovineData } from '~/services/dto/bovine-data'
|
import type { BovineData } from '~/services/dto/bovine-data'
|
||||||
|
import { useAuthStore } from '~/stores/auth'
|
||||||
import { useDataTableServerState } from '~/composables/useDataTableServerState'
|
import { useDataTableServerState } from '~/composables/useDataTableServerState'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const auth = useAuthStore()
|
||||||
|
const api = useApi()
|
||||||
|
const toast = useToast()
|
||||||
|
|
||||||
|
interface SyncResult {
|
||||||
|
created: number
|
||||||
|
updated: number
|
||||||
|
exited: number
|
||||||
|
total: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const syncing = ref(false)
|
||||||
|
|
||||||
|
const syncInventory = async () => {
|
||||||
|
if (syncing.value) return
|
||||||
|
const confirmed = window.confirm(
|
||||||
|
"Lancer la synchronisation avec EDNOTIF ?\n\nLes bovins absents de la réponse seront marqués comme sortis."
|
||||||
|
)
|
||||||
|
if (!confirmed) return
|
||||||
|
|
||||||
|
syncing.value = true
|
||||||
|
try {
|
||||||
|
const result = await api.post<SyncResult>('bovines/sync-inventory')
|
||||||
|
toast.success({
|
||||||
|
title: 'Inventaire synchronisé',
|
||||||
|
message: `Créés : ${result.created} · Mis à jour : ${result.updated} · Sortis : ${result.exited} · Total EDNOTIF : ${result.total}`
|
||||||
|
})
|
||||||
|
reload()
|
||||||
|
} catch {
|
||||||
|
// error toast already handled by useApi onResponseError
|
||||||
|
} finally {
|
||||||
|
syncing.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const { items, totalItems, page, perPage, filters, loading, reload } =
|
const { items, totalItems, page, perPage, filters, loading, reload } =
|
||||||
useDataTableServerState<BovineData>(
|
useDataTableServerState<BovineData>(
|
||||||
|
|||||||
Reference in New Issue
Block a user