Compare commits

...

1 Commits

Author SHA1 Message Date
359c4e27a5 feat : ajout loader skeleton 2026-02-13 15:20:35 +01:00
10 changed files with 90 additions and 25 deletions

View File

@@ -46,7 +46,7 @@ Ajouter dans le fichier .env du frontend
* [#324] Creation page admin listing clients * [#324] Creation page admin listing clients
* [#326] Admin modification creation client * [#326] Admin modification creation client
* [#325] Correction diverses * [#325] Correction diverses
* [#319] Réflexion sur des loaders de type skeleton
### Changed ### Changed
### Fixed ### Fixed

View File

@@ -1,5 +1,6 @@
<template> <template>
<form @submit.prevent="validate"> <skeletonForm v-if="isPageLoading"/>
<form v-else @submit.prevent="validate">
<div class="grid grid-cols-2 items-start gap-y-8 gap-x-40 mb-16"> <div class="grid grid-cols-2 items-start gap-y-8 gap-x-40 mb-16">
<h1 class="font-bold text-5xl uppercase col-start-1 row-start-1">Réception</h1> <h1 class="font-bold text-5xl uppercase col-start-1 row-start-1">Réception</h1>
<!-- Nom de l'utilisateur --> <!-- Nom de l'utilisateur -->
@@ -147,6 +148,7 @@ import {RECEPTION_TYPE_CODES, SUPPLIER_CODE} from "~/utils/constants";
import {deleteReceptionBovine, getReceptionBovineList} from "~/services/reception-bovine"; import {deleteReceptionBovine, getReceptionBovineList} from "~/services/reception-bovine";
import type {ReceptionFormData} from "~/services/dto/reception-data"; import type {ReceptionFormData} from "~/services/dto/reception-data";
const isPageLoading = ref(true)
const router = useRouter() const router = useRouter()
const receptionStore = useReceptionStore() const receptionStore = useReceptionStore()
const form = reactive<ReceptionFormData>({ const form = reactive<ReceptionFormData>({
@@ -338,6 +340,8 @@ onMounted(async () => {
await loadVehicles() await loadVehicles()
await authStore.ensureSession() await authStore.ensureSession()
setDefaultUser() setDefaultUser()
//isPageLoading.value = false
}) })
// Ajuste driver/vehicle quand le transporteur change (logique LIOT) // Ajuste driver/vehicle quand le transporteur change (logique LIOT)

View File

@@ -1,5 +1,6 @@
<template> <template>
<form @submit.prevent="validate"> <skeletonForm v-if="isPageLoading"/>
<form v-else @submit.prevent="validate">
<div class="grid grid-cols-2 items-start gap-y-8 gap-x-40 mb-16"> <div class="grid grid-cols-2 items-start gap-y-8 gap-x-40 mb-16">
<h1 class="font-bold text-5xl uppercase col-start-1 row-start-1">Expédition</h1> <h1 class="font-bold text-5xl uppercase col-start-1 row-start-1">Expédition</h1>
<!-- Nom de l'utilisateur --> <!-- Nom de l'utilisateur -->
@@ -123,7 +124,7 @@
<div class="flex justify-center"> <div class="flex justify-center">
<button <button
type="submit" type="submit"
class="text-xl uppercase bg-primary-500 text-white h-[50px] w-[272px] justify-self-end" class="text-xl uppercase bg-primary-500 text-white h-[50px] w-[272px]"
>Valider >Valider
</button> </button>
</div> </div>
@@ -148,13 +149,12 @@ import type {ShipmentFormData} from '~/services/dto/shipment-data'
import {SUPPLIER_CODE} from "~/utils/constants" import {SUPPLIER_CODE} from "~/utils/constants"
import {useAuthStore} from '~/stores/auth' import {useAuthStore} from '~/stores/auth'
import {useShipmentStore} from '~/stores/shipment' import {useShipmentStore} from '~/stores/shipment'
import { computed, reactive, ref, watch, onMounted } from 'vue' import {computed, reactive, ref, watch, onMounted} from 'vue'
import type {ShipmentTypeData} from "~/services/dto/shipment-type-data"; import type {ShipmentTypeData} from "~/services/dto/shipment-type-data";
import {getShipmentTypeList} from "~/services/shipment-type"; import {getShipmentTypeList} from "~/services/shipment-type";
import { import {
createShipmentBovine, createShipmentBovine,
deleteShipmentBovine, deleteShipmentBovine,
getBovinShipmentList,
updateShipmentBovine updateShipmentBovine
} from "~/services/bovin-shipment"; } from "~/services/bovin-shipment";
@@ -164,7 +164,7 @@ const trucks = ref<TruckData[]>([])
const carriers = ref<CarrierData[]>([]) const carriers = ref<CarrierData[]>([])
const drivers = ref<DriverData[]>([]) const drivers = ref<DriverData[]>([])
const vehicles = ref<VehicleData[]>([]) const vehicles = ref<VehicleData[]>([])
const isPageLoading = ref(true)
const isLoadingUsers = ref(false) const isLoadingUsers = ref(false)
const isLoadingShipmentTypes = ref(false) const isLoadingShipmentTypes = ref(false)
const isLoadingCustomers = ref(false) const isLoadingCustomers = ref(false)
@@ -310,6 +310,7 @@ onMounted(async () => {
await loadDrivers() await loadDrivers()
await authStore.ensureSession() await authStore.ensureSession()
setDefaultUser() setDefaultUser()
isPageLoading.value = false
}) })
// Hydrate le formulaire depuis l'expédition en cours // Hydrate le formulaire depuis l'expédition en cours
watch( watch(

View File

@@ -0,0 +1,17 @@
<template>
<div class="grid grid-cols-2 items-start gap-y-8 gap-x-40 mb-16">
<UiSkeletonBlock height="48px"/>
<div class="flex flex-col gap-2" v-for="i in 9">
<UiSkeletonBlock width="96px"/>
<UiSkeletonBlock width="100%" height="42px"/>
</div>
</div>
<div class="flex justify-center">
<UiSkeletonBlock
width="272px"
height="50px"
/>
</div>
</template>
<script setup lang="ts">
</script>

View File

@@ -0,0 +1,13 @@
<template>
<div class="ps-20">
<UiSkeletonBlock height="48px" class="my-4"/>
<div class="grid grid-cols-3 justify-evenly bg-slate-100 py-4">
<UiSkeletonBlock v-for="i in 3"/>
</div>
<div
class="grid grid-cols-3 gap-4 px-4 py-4 text-sm hover:bg-slate-50 cursor-pointer border-t border-slate-200"
v-for="i in 3">
<UiSkeletonBlock v-for="i in 3"/>
</div>
</div>
</template>

View File

@@ -0,0 +1,22 @@
<template>
<div
:class="['animate-pulse', rounded, customClass]"
:style="{ width, height, background }"
/>
</template>
<script setup lang="ts">
withDefaults(defineProps<{
width?: string
height?: string
rounded?: string
background?: string
customClass?: string
}>(), {
width: '50%',
height: '1rem',
rounded: 'rounded-md',
background: '#e5e7eb',
customClass: ''
})
</script>

View File

@@ -46,6 +46,6 @@ definePageMeta({
}) })
onMounted(async () => { onMounted(async () => {
carrierList.value = await getCarrierList(false) carrierList.value = await getCarrierList()
}) })
</script> </script>

View File

@@ -1,10 +1,10 @@
<template> <template>
<skeletonTable v-if="isPageLoading"/>
<div v-else class="ps-20">
<div class="flex items-center justify-start gap-10"> <div class="flex items-center justify-start gap-10">
<Icon @click="router.push('/')" name="gg:arrow-left-o" style="color: black" size="44" /> <Icon @click="router.push('/')" name="gg:arrow-left-o" style="color: black" size="44"/>
<h1 class="text-3xl font-bold uppercase">listes des réceptions finie</h1> <h1 class="text-3xl font-bold uppercase">listes des réceptions finie</h1>
</div> </div>
<div class="ps-20 " >
<div class="mt-6 border border-slate-200 mb-16 "> <div class="mt-6 border border-slate-200 mb-16 ">
<div class="grid grid-cols-6 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide"> <div class="grid grid-cols-6 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide">
<div>Numéro</div> <div>Numéro</div>
@@ -39,7 +39,7 @@ import {getReceptionList} from "~/services/reception";
const receptionList = ref<ReceptionData[]>() const receptionList = ref<ReceptionData[]>()
const router = useRouter() const router = useRouter()
const isPageLoading = ref(true)
const formatWeighing = (reception: ReceptionData, type: 'gross' | 'tare') => { const formatWeighing = (reception: ReceptionData, type: 'gross' | 'tare') => {
const entry = reception.weights?.find((weight) => weight.type === type) const entry = reception.weights?.find((weight) => weight.type === type)
if (!entry || entry.weight == null || entry.dsd == null) { if (!entry || entry.weight == null || entry.dsd == null) {
@@ -54,5 +54,6 @@ const goToReception = (id: number) => {
onMounted(async () => { onMounted(async () => {
receptionList.value = await getReceptionList(true) receptionList.value = await getReceptionList(true)
isPageLoading.value = false
}) })
</script> </script>

View File

@@ -1,10 +1,11 @@
<template> <template>
<skeletonTable v-if="isPageLoading"/>
<div v-else class="ps-20 ">
<div class="flex items-center justify-start gap-10"> <div class="flex items-center justify-start gap-10">
<Icon @click="router.push('/')" name="gg:arrow-left-o" style="color: black" size="44"/> <Icon @click="router.push('/')" name="gg:arrow-left-o" style="color: black" size="44"/>
<h1 class="text-3xl font-bold uppercase">listes des expéditions finie</h1> <h1 class="text-3xl font-bold uppercase">listes des expéditions finie</h1>
</div> </div>
<div class="ps-20 ">
<div class="mt-6 border border-slate-200 mb-16 "> <div class="mt-6 border border-slate-200 mb-16 ">
<div class="grid grid-cols-6 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide"> <div class="grid grid-cols-6 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide">
<div>Numéro</div> <div>Numéro</div>
@@ -50,7 +51,7 @@ import {getShipmentList} from "~/services/shipment";
const shipmentList = ref<ShipmentData[]>() const shipmentList = ref<ShipmentData[]>()
const router = useRouter() const router = useRouter()
const isPageLoading = ref(true)
const formatWeighing = (shipment: ShipmentData, type: 'gross' | 'tare') => { const formatWeighing = (shipment: ShipmentData, type: 'gross' | 'tare') => {
const entry = shipment.weights?.find((weight) => weight.type === type) const entry = shipment.weights?.find((weight) => weight.type === type)
if (!entry || entry.weight == null || entry.dsd == null) { if (!entry || entry.weight == null || entry.dsd == null) {
@@ -73,9 +74,11 @@ const formatBovinShipmentLines = (shipment: ShipmentData) => {
const goToshipment = (id: number) => { const goToshipment = (id: number) => {
//router.push(`/shipment/update/${id}`) //router.push(`/shipment/update/${id}`)
} }
onMounted(async () => { onMounted(async () => {
shipmentList.value = await getShipmentList(true) shipmentList.value = await getShipmentList(true)
isPageLoading.value = false
}) })
</script> </script>

View File

@@ -26,6 +26,10 @@ use Symfony\Component\Serializer\Attribute\Groups;
), ),
new GetCollection( new GetCollection(
normalizationContext: ['groups' => ['supplier:read']], normalizationContext: ['groups' => ['supplier:read']],
),
new GetCollection(
uriTemplate: '/admin/suppliers',
normalizationContext: ['groups' => ['supplier:read']],
security: "is_granted('ROLE_ADMIN')" security: "is_granted('ROLE_ADMIN')"
), ),
new Post( new Post(