160 lines
6.4 KiB
TypeScript
160 lines
6.4 KiB
TypeScript
import type { Employee } from '~/services/dto/employee'
|
||
import { CONTRACT_TYPES } from '~/services/dto/contract'
|
||
import { getEmployee } from '~/services/employees'
|
||
import { useEmployeeContractPhase } from '~/composables/useEmployeeContractPhase'
|
||
|
||
export const useEmployeeDetailPage = () => {
|
||
const route = useRoute()
|
||
const employee = ref<Employee | null>(null)
|
||
const isLoading = ref(false)
|
||
const activeTab = ref<'contract' | 'leave' | 'rtt' | 'mileage' | 'formation' | 'bonus' | 'observation'>('contract')
|
||
|
||
const phase = useEmployeeContractPhase(employee)
|
||
|
||
const showLeaveTab = computed(() => employee.value?.currentContractNature !== 'INTERIM')
|
||
const showRttTab = computed(() => phase.selectedPhase.value?.contractType !== CONTRACT_TYPES.FORFAIT)
|
||
const isForfait = computed(() => phase.selectedPhase.value?.contractType === CONTRACT_TYPES.FORFAIT)
|
||
// Jours à travailler du forfait : prorata exposé par le backend (218 sur année pleine,
|
||
// moins sur une entrée en cours d'année). Fallback 218 tant que le récap n'est pas chargé.
|
||
const forfaitWorkTargetDays = computed(() => {
|
||
const target = leave.leaveSummary.value?.forfaitWorkTargetDays
|
||
return (target === null || target === undefined) ? 218 : Math.round(target)
|
||
})
|
||
const employeeContractWorkLabel = computed(() => {
|
||
const contract = employee.value?.contract
|
||
if (!contract) return '-'
|
||
if (contract.type === CONTRACT_TYPES.FORFAIT) return `Forfait - ${forfaitWorkTargetDays.value} jours`
|
||
if (contract.weeklyHours !== null && contract.weeklyHours !== undefined) return `${contract.weeklyHours} heures`
|
||
return contract.name || '-'
|
||
})
|
||
|
||
const loadEmployee = async () => {
|
||
const idParam = Array.isArray(route.params.id) ? route.params.id[0] : route.params.id
|
||
const employeeId = Number(idParam)
|
||
if (!Number.isInteger(employeeId) || employeeId <= 0) {
|
||
return
|
||
}
|
||
|
||
isLoading.value = true
|
||
try {
|
||
employee.value = await getEmployee(employeeId)
|
||
phase.resetToCurrent()
|
||
|
||
if (!showLeaveTab.value && activeTab.value === 'leave') {
|
||
activeTab.value = 'contract'
|
||
}
|
||
if (!showRttTab.value && activeTab.value === 'rtt') {
|
||
activeTab.value = 'contract'
|
||
}
|
||
|
||
leave.resetLoaded()
|
||
rtt.resetLoaded()
|
||
mileage.resetLoaded()
|
||
formation.resetLoaded()
|
||
bonus.resetLoaded()
|
||
observation.resetLoaded()
|
||
|
||
if (activeTab.value === 'leave' && showLeaveTab.value) {
|
||
await leave.loadLeaveData()
|
||
} else if (activeTab.value === 'rtt' && showRttTab.value) {
|
||
await rtt.loadRttData()
|
||
} else if (activeTab.value === 'mileage') {
|
||
await mileage.loadMileageData()
|
||
} else if (activeTab.value === 'formation') {
|
||
await formation.loadFormationData()
|
||
} else if (activeTab.value === 'bonus') {
|
||
await bonus.loadBonusData()
|
||
} else if (activeTab.value === 'observation') {
|
||
await observation.loadObservationData()
|
||
} else if (showLeaveTab.value) {
|
||
// Eager load: the header shows présence (et jours à travailler/restant pour le forfait),
|
||
// qui proviennent du récap congés — nécessaire même quand on ouvre un autre onglet.
|
||
await leave.loadLeaveData()
|
||
}
|
||
} finally {
|
||
isLoading.value = false
|
||
}
|
||
}
|
||
|
||
const contract = useEmployeeContract(employee, loadEmployee)
|
||
const leave = useEmployeeLeave(employee, loadEmployee, phase.selectedPhase)
|
||
const formatDays = (n: number) => (Number.isInteger(n) ? String(n) : (Math.round(n * 100) / 100).toFixed(2).replace('.', ','))
|
||
// Forfait : « (présence · restant à travailler) ». restant = jours à travailler (prorata) − présence.
|
||
const forfaitRemainingDaysLabel = computed(() => {
|
||
if (!isForfait.value) return ''
|
||
const presence = leave.leaveSummary.value?.presenceDaysToToday
|
||
if (presence === undefined || presence === null) return ''
|
||
const remaining = forfaitWorkTargetDays.value - presence
|
||
return ` (${formatDays(presence)} présence · ${formatDays(remaining)} restants)`
|
||
})
|
||
// Non-forfait : « (présence) » seul (pas de cible de jours à travailler).
|
||
const nonForfaitPresenceLabel = computed(() => {
|
||
if (isForfait.value) return ''
|
||
const presence = leave.leaveSummary.value?.presenceDaysToToday
|
||
if (presence === undefined || presence === null) return ''
|
||
return ` (${formatDays(presence)} présence)`
|
||
})
|
||
const rtt = useEmployeeRtt(employee, loadEmployee, phase.selectedPhase)
|
||
const mileage = useEmployeeMileage(employee, loadEmployee)
|
||
const formation = useEmployeeFormation(employee, loadEmployee)
|
||
const bonus = useEmployeeBonus(employee, loadEmployee)
|
||
const observation = useEmployeeObservation(employee, loadEmployee)
|
||
|
||
watch(() => phase.selectedPhase.value?.id, (newId, oldId) => {
|
||
if (newId === oldId || oldId === undefined) return
|
||
// Bascule onglet si on entre dans une phase qui ne supporte plus le tab actuel
|
||
if (!showRttTab.value && activeTab.value === 'rtt') {
|
||
activeTab.value = 'leave'
|
||
}
|
||
// Recharger l'onglet courant ; sinon recharger quand même le récap congés
|
||
// pour que le libellé de présence / jours à travailler du header reste à jour.
|
||
if (activeTab.value === 'leave' && showLeaveTab.value) {
|
||
leave.loadLeaveData()
|
||
} else if (activeTab.value === 'rtt' && showRttTab.value) {
|
||
rtt.loadRttData()
|
||
} else if (showLeaveTab.value) {
|
||
leave.loadLeaveData()
|
||
}
|
||
})
|
||
|
||
watch(activeTab, (tab) => {
|
||
if (tab === 'leave' && !leave.leaveDataLoaded.value && showLeaveTab.value) {
|
||
leave.loadLeaveData()
|
||
} else if (tab === 'rtt' && !rtt.rttDataLoaded.value && showRttTab.value) {
|
||
rtt.loadRttData()
|
||
} else if (tab === 'mileage' && !mileage.mileageDataLoaded.value) {
|
||
mileage.loadMileageData()
|
||
} else if (tab === 'formation' && !formation.formationDataLoaded.value) {
|
||
formation.loadFormationData()
|
||
} else if (tab === 'bonus' && !bonus.bonusDataLoaded.value) {
|
||
bonus.loadBonusData()
|
||
} else if (tab === 'observation' && !observation.observationDataLoaded.value) {
|
||
observation.loadObservationData()
|
||
}
|
||
})
|
||
|
||
onMounted(async () => {
|
||
await Promise.all([contract.loadContracts(), contract.loadInterimAgencies()])
|
||
await loadEmployee()
|
||
})
|
||
|
||
return {
|
||
employee,
|
||
isLoading,
|
||
activeTab,
|
||
showLeaveTab,
|
||
showRttTab,
|
||
employeeContractWorkLabel,
|
||
forfaitRemainingDaysLabel,
|
||
nonForfaitPresenceLabel,
|
||
...phase,
|
||
...contract,
|
||
...leave,
|
||
...rtt,
|
||
...mileage,
|
||
...formation,
|
||
...bonus,
|
||
...observation
|
||
}
|
||
}
|