From 2730e34f31edc08b2f000715038f63b73645810e Mon Sep 17 00:00:00 2001 From: tristan Date: Tue, 19 May 2026 11:46:24 +0200 Subject: [PATCH] feat(leave) : phase-aware leave tab loading --- frontend/composables/useEmployeeLeave.ts | 60 +++++++++++++----------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/frontend/composables/useEmployeeLeave.ts b/frontend/composables/useEmployeeLeave.ts index 8bfc753..53d721f 100644 --- a/frontend/composables/useEmployeeLeave.ts +++ b/frontend/composables/useEmployeeLeave.ts @@ -1,5 +1,6 @@ import type { Ref } from 'vue' import type { Absence } from '~/services/dto/absence' +import type { ContractPhase } from '~/services/dto/contract-phase' import type { EmployeeLeaveSummary } from '~/services/dto/employee-leave-summary' import type { Employee } from '~/services/dto/employee' import { CONTRACT_TYPES } from '~/services/dto/contract' @@ -12,7 +13,11 @@ export type LeaveYearOption = { label: string } -export const useEmployeeLeave = (employee: Ref, reloadEmployee: () => Promise) => { +export const useEmployeeLeave = ( + employee: Ref, + reloadEmployee: () => Promise, + selectedPhase: Ref, +) => { const employeeAbsences = ref([]) const leaveSummary = ref(null) const publicHolidays = ref>({}) @@ -20,17 +25,18 @@ export const useEmployeeLeave = (employee: Ref, reloadEmployee: const leaveDataLoaded = ref(false) const selectedLeaveYear = ref(null) - const isForfaitContract = (emp: Employee | null) => - emp?.contract?.type === CONTRACT_TYPES.FORFAIT + const isForfaitOnPhase = computed(() => + selectedPhase.value?.contractType === CONTRACT_TYPES.FORFAIT + ) - const computeLeaveYearForDate = (emp: Employee | null, date: Date): number => { - if (isForfaitContract(emp)) return date.getFullYear() + const computeLeaveYearForDate = (date: Date): number => { + if (isForfaitOnPhase.value) return date.getFullYear() return date.getMonth() >= 5 ? date.getFullYear() + 1 : date.getFullYear() } const currentLeaveYear = computed(() => { if (!employee.value) return null - return computeLeaveYearForDate(employee.value, new Date()) + return computeLeaveYearForDate(new Date()) }) const formatLeaveYearLabel = (year: number, isForfait: boolean): string => { @@ -39,23 +45,15 @@ export const useEmployeeLeave = (employee: Ref, reloadEmployee: } const availableLeaveYears = computed(() => { - if (!employee.value || currentLeaveYear.value === null) return [] - const isForfait = isForfaitContract(employee.value) - const current = currentLeaveYear.value + if (!employee.value || !selectedPhase.value || currentLeaveYear.value === null) return [] + const isForfait = isForfaitOnPhase.value + const phase = selectedPhase.value - const startDates: string[] = [] - for (const period of employee.value.contractHistory ?? []) { - if (period.startDate) startDates.push(period.startDate) - } - if (employee.value.entryDate) startDates.push(employee.value.entryDate) - - let contractFloor = current - for (const raw of startDates) { - const date = new Date(`${raw.substring(0, 10)}T00:00:00`) - if (Number.isNaN(date.getTime())) continue - const leaveYear = computeLeaveYearForDate(employee.value, date) - if (leaveYear < contractFloor) contractFloor = leaveYear - } + // Plage = exercices intersectant la phase. + const phaseStartYear = computeLeaveYearForDate(new Date(`${phase.startDate}T00:00:00`)) + const phaseEndYear = phase.endDate + ? computeLeaveYearForDate(new Date(`${phase.endDate}T00:00:00`)) + : currentLeaveYear.value // Hard floor : data-start-date (env RTT_START_DATE) — le logiciel n'a pas // d'historique avant cette date, inutile de proposer des années antérieures. @@ -64,14 +62,15 @@ export const useEmployeeLeave = (employee: Ref, reloadEmployee: if (dataStart) { const dataStartDate = new Date(`${dataStart.substring(0, 10)}T00:00:00`) if (!Number.isNaN(dataStartDate.getTime())) { - dataFloor = computeLeaveYearForDate(employee.value, dataStartDate) + dataFloor = computeLeaveYearForDate(dataStartDate) } } - const minYear = dataFloor !== null ? Math.max(contractFloor, dataFloor) : contractFloor + const minYear = dataFloor !== null ? Math.max(phaseStartYear, dataFloor) : phaseStartYear + const maxYear = phaseEndYear const years: LeaveYearOption[] = [] - for (let y = current; y >= minYear; y -= 1) { + for (let y = maxYear; y >= minYear; y -= 1) { years.push({ value: y, label: formatLeaveYearLabel(y, isForfait) }) } return years @@ -90,7 +89,7 @@ export const useEmployeeLeave = (employee: Ref, reloadEmployee: if (selectedLeaveYear.value === null) return isLeaveLoading.value = true try { - const isForfait = isForfaitContract(employee.value) + const isForfait = isForfaitOnPhase.value const leaveYear = selectedLeaveYear.value const from = isForfait ? `${leaveYear}-01-01` : `${leaveYear - 1}-06-01` const to = isForfait ? `${leaveYear}-12-31` : `${leaveYear}-05-31` @@ -98,7 +97,7 @@ export const useEmployeeLeave = (employee: Ref, reloadEmployee: const [absences, summary, ...holidayResults] = await Promise.all([ listAbsences({ from, to, employeeId: employee.value.id }), - getEmployeeLeaveSummary(employee.value.id, leaveYear), + getEmployeeLeaveSummary(employee.value.id, leaveYear, selectedPhase.value?.id), ...holidayYears.map((y) => listPublicHolidays('metropole', y)) ]) employeeAbsences.value = absences @@ -122,6 +121,13 @@ export const useEmployeeLeave = (employee: Ref, reloadEmployee: selectedLeaveYear.value = null } + watch(() => selectedPhase.value?.id, () => { + // Reset l'année car la plage a peut-être changé. + selectedLeaveYear.value = null + leaveDataLoaded.value = false + // Le rechargement effectif est piloté par useEmployeeDetailPage. + }) + const submitFractionedDays = async (days: number) => { if (!employee.value) return const year = leaveSummary.value?.year ?? undefined