feat(heures) : calendrier des jours validés (vue Jour) + harmonisation Malio UI
- Calendrier MalioDate en vue Jour (Heures + Heures Conducteurs) : jours entièrement validés (admin) peints en vert. Endpoint GET /work-hours/validation-status?from=&to=[&driver=1] (scope conducteur inversé), chargement à la volée par mois, refresh après validation/saisie/absence. - Suite à @malio/layer-ui 1.7.11 : reserveMessageSpace=false sur les champs ; tous les drawers migrés sur MalioDrawer (titre via slot #header, AppDrawer custom supprimé) ; boutons d'action en MalioButton (deux boutons partagent l'espace) ; inputs date en MalioDate ; MalioDateWeek en vue Semaine. - Boutons d'ajout uniformisés sur « Ajouter » + icône. - .env : EXCLUDED_PUBLIC_HOLIDAYS="null". - Doc : doc/hours-validated-days.md, documentation-content.ts, CLAUDE.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<!-- Desktop: filters row -->
|
||||
<div class="hidden lg:flex lg:items-center lg:gap-4">
|
||||
<div v-if="sites.length > 0 && isAdmin" class="relative z-50 w-80">
|
||||
<MalioSelectCheckbox
|
||||
<MalioSelectCheckbox :reserve-message-space="false"
|
||||
v-model="selectedSiteIds"
|
||||
:options="siteOptions"
|
||||
groupClass="w-80"
|
||||
@@ -11,8 +11,8 @@
|
||||
display-select-all
|
||||
/>
|
||||
</div>
|
||||
<div v-if="isAdmin" class="w-80">
|
||||
<MalioInputText
|
||||
<div v-if="isAdmin" class="w-96">
|
||||
<MalioInputText :reserve-message-space="false"
|
||||
v-model="employeeFilter"
|
||||
label="Recherche d'un employé"
|
||||
icon-name="mdi:magnify"
|
||||
@@ -23,7 +23,7 @@
|
||||
<!-- Mobile: search + filter button -->
|
||||
<div v-if="isAdmin" class="flex items-center gap-2 lg:hidden">
|
||||
<div class="flex-1 min-w-0">
|
||||
<MalioInputText
|
||||
<MalioInputText :reserve-message-space="false"
|
||||
v-model="employeeFilter"
|
||||
label="Recherche d'un employé"
|
||||
icon-name="mdi:magnify"
|
||||
@@ -39,12 +39,15 @@
|
||||
</div>
|
||||
|
||||
<!-- Mobile filters drawer -->
|
||||
<AppDrawer v-model="filtersDrawerOpen" title="Filtres">
|
||||
<MalioDrawer v-model="filtersDrawerOpen">
|
||||
<template #header>
|
||||
<h2 class="text-[32px] font-semibold text-primary-500">Filtres</h2>
|
||||
</template>
|
||||
<div class="space-y-6">
|
||||
<div v-if="sites.length > 0 && isAdmin">
|
||||
<label class="text-md font-semibold text-neutral-700">Sites</label>
|
||||
<div class="mt-2">
|
||||
<MalioSelectCheckbox
|
||||
<MalioSelectCheckbox :reserve-message-space="false"
|
||||
v-model="selectedSiteIds"
|
||||
:options="siteOptions"
|
||||
groupClass="w-80"
|
||||
@@ -77,11 +80,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AppDrawer>
|
||||
</MalioDrawer>
|
||||
|
||||
<!-- Date navigation -->
|
||||
<div class="flex flex-col gap-3 lg:flex-row lg:justify-between lg:items-center lg:gap-4">
|
||||
<div class="flex flex-col gap-3 lg:flex-row lg:flex-wrap lg:gap-4">
|
||||
<div class="flex flex-col gap-3 lg:flex-row lg:flex-wrap lg:items-center lg:gap-4">
|
||||
<div
|
||||
v-if="viewMode === 'day'"
|
||||
class="inline-flex h-10 w-full overflow-hidden rounded-md border border-primary-500 bg-white lg:w-[320px]"
|
||||
@@ -142,10 +145,33 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Vue Jour (opt-in) : calendrier Malio avec jours validés en vert (markedDates). -->
|
||||
<MalioDate
|
||||
v-if="viewMode === 'day' && showValidationCalendar"
|
||||
:model-value="selectedDate"
|
||||
:clearable="false"
|
||||
:reserve-message-space="false"
|
||||
:marked-dates="markedDates"
|
||||
group-class="w-full lg:w-96"
|
||||
label="Date"
|
||||
@update:model-value="onDatePicked"
|
||||
@month-change="(payload) => emit('month-change', payload)"
|
||||
/>
|
||||
<!-- Vue Semaine : sélecteur de semaine Malio. -->
|
||||
<MalioDateWeek
|
||||
v-else-if="viewMode === 'week'"
|
||||
:model-value="pickerValue"
|
||||
:clearable="false"
|
||||
:reserve-message-space="false"
|
||||
group-class="w-full lg:w-96"
|
||||
label="Semaine"
|
||||
@update:model-value="onWeekPicked"
|
||||
/>
|
||||
<PeriodStepperPicker
|
||||
v-else
|
||||
width-class="w-full lg:w-[320px]"
|
||||
:label="formattedSelectedDate"
|
||||
:picker-type="viewMode === 'week' ? 'week' : 'date'"
|
||||
picker-type="date"
|
||||
:picker-value="pickerValue"
|
||||
prev-aria-label="Période précédente"
|
||||
next-aria-label="Période suivante"
|
||||
@@ -195,7 +221,6 @@
|
||||
import type { Site } from '~/services/dto/site'
|
||||
import type { AbsenceType } from '~/services/dto/absence-type'
|
||||
import PeriodStepperPicker from '~/components/PeriodStepperPicker.vue'
|
||||
import AppDrawer from '~/components/AppDrawer.vue'
|
||||
import { weekInputValueToYmd, ymdToWeekInputValue } from '~/utils/date'
|
||||
|
||||
const selectedDate = defineModel<string>('selectedDate', { required: true })
|
||||
@@ -208,6 +233,10 @@ const props = defineProps<{
|
||||
sites: Site[]
|
||||
absenceTypes: AbsenceType[]
|
||||
formattedSelectedDate: string
|
||||
// Calendrier des jours validés (vert) : opt-in, réservé à l'écran Heures.
|
||||
// L'écran Heures Conducteurs ne le passe pas → garde le PeriodStepperPicker.
|
||||
showValidationCalendar?: boolean
|
||||
markedDates?: Record<string, 'success' | 'danger'>
|
||||
shortcutButtonClass: (target: 'yesterday' | 'today' | 'tomorrow') => string
|
||||
weekShortcutButtonClass: (target: 'previousWeek' | 'thisWeek' | 'nextWeek') => string
|
||||
getWeekShortcutLabel: (target: 'previousWeek' | 'thisWeek' | 'nextWeek') => string
|
||||
@@ -223,6 +252,7 @@ const emit = defineEmits<{
|
||||
(e: 'set-this-week'): void
|
||||
(e: 'set-next-week'): void
|
||||
(e: 'shift-date', value: number): void
|
||||
(e: 'month-change', value: { month: number; year: number }): void
|
||||
}>()
|
||||
|
||||
const filtersDrawerOpen = ref(false)
|
||||
@@ -252,4 +282,20 @@ const onPickerValue = (value: string) => {
|
||||
|
||||
selectedDate.value = value
|
||||
}
|
||||
|
||||
// Sélection d'un jour dans le calendrier MalioDate (vue Jour). `clearable=false`
|
||||
// → pas de null en pratique, mais on garde la garde par sécurité.
|
||||
const onDatePicked = (value: string | null) => {
|
||||
if (!value) return
|
||||
selectedDate.value = value
|
||||
}
|
||||
|
||||
// Sélection d'une semaine dans MalioDateWeek (vue Semaine) : v-model au format ISO
|
||||
// week (YYYY-Www) → on repositionne selectedDate sur le lundi de cette semaine.
|
||||
const onWeekPicked = (value: string | null) => {
|
||||
if (!value) return
|
||||
const ymd = weekInputValueToYmd(value)
|
||||
if (!ymd) return
|
||||
selectedDate.value = ymd
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user