345 lines
12 KiB
TypeScript
345 lines
12 KiB
TypeScript
import type { Ref } from 'vue'
|
|
import type { Contract } from '~/services/dto/contract'
|
|
import type { ContractHistoryItem, Employee } from '~/services/dto/employee'
|
|
import { listContracts } from '~/services/contracts'
|
|
import { updateEmployee } from '~/services/employees'
|
|
import { createSuspension, updateSuspension } from '~/services/contractSuspensions'
|
|
import { formatNullableYmdToFr, getTodayYmd, shiftYmd } from '~/utils/date'
|
|
import { contractNatureLabel, isContractNature, requiresContractEndDate, showsContractEndDate } from '~/utils/contract'
|
|
|
|
type SuspensionForm = {
|
|
id: number | null
|
|
startDate: string
|
|
endDate: string
|
|
comment: string
|
|
}
|
|
|
|
export const useEmployeeContract = (employee: Ref<Employee | null>, reloadEmployee: () => Promise<void>) => {
|
|
const toast = useToast()
|
|
const contracts = ref<Contract[]>([])
|
|
const isContractDrawerOpen = ref(false)
|
|
const isContractSubmitting = ref(false)
|
|
const isCreateContractDrawerOpen = ref(false)
|
|
const isCreateContractSubmitting = ref(false)
|
|
const suspensionForms = ref<SuspensionForm[]>([])
|
|
const isSuspensionSubmitting = ref(false)
|
|
|
|
const contractForm = reactive({
|
|
contractId: '' as number | '',
|
|
contractName: '',
|
|
weeklyHours: null as number | null,
|
|
contractNature: 'CDI' as 'CDI' | 'CDD' | 'INTERIM',
|
|
startDate: '',
|
|
endDate: '',
|
|
paidLeaveSettled: false,
|
|
comment: ''
|
|
})
|
|
|
|
const validationTouched = reactive({
|
|
endDate: false
|
|
})
|
|
|
|
const createContractForm = reactive({
|
|
contractId: '' as number | '',
|
|
contractNature: 'CDI' as 'CDI' | 'CDD' | 'INTERIM',
|
|
startDate: '',
|
|
endDate: ''
|
|
})
|
|
|
|
const createValidationTouched = reactive({
|
|
contractId: false,
|
|
contractNature: false,
|
|
startDate: false,
|
|
endDate: false
|
|
})
|
|
|
|
const contractHistory = computed(() => employee.value?.contractHistory ?? [])
|
|
|
|
const formatDate = (value?: string | null) => formatNullableYmdToFr(value)
|
|
|
|
const contractHistoryLabel = (item: ContractHistoryItem) => {
|
|
if (item.weeklyHours !== null && item.weeklyHours !== undefined) {
|
|
return `${item.weeklyHours} heures`
|
|
}
|
|
return item.contractName ?? '-'
|
|
}
|
|
|
|
const currentActiveContractPeriod = computed(() => {
|
|
const today = getTodayYmd()
|
|
const history = employee.value?.contractHistory ?? []
|
|
return history.find((item) => item.startDate <= today && (!item.endDate || item.endDate >= today)) ?? null
|
|
})
|
|
|
|
const currentActiveContractPeriodId = computed<number | null>(() => {
|
|
const period = currentActiveContractPeriod.value
|
|
return period?.periodId ?? null
|
|
})
|
|
|
|
const canCloseCurrentContract = computed(() => {
|
|
const active = currentActiveContractPeriod.value
|
|
if (!active) return false
|
|
if (!active.endDate) return true
|
|
return active.endDate > getTodayYmd()
|
|
})
|
|
|
|
const canCreateContract = computed(() => {
|
|
const active = currentActiveContractPeriod.value
|
|
if (!active) return true
|
|
return !!active.endDate
|
|
})
|
|
|
|
const isContractEndDateValid = computed(() => contractForm.endDate !== '')
|
|
const showContractEndDateError = computed(() => validationTouched.endDate && !isContractEndDateValid.value)
|
|
|
|
const showsCreateContractEndDate = computed(() => showsContractEndDate(createContractForm.contractNature))
|
|
const requiresCreateContractEndDate = computed(() => requiresContractEndDate(createContractForm.contractNature))
|
|
const isCreateContractValid = computed(() => createContractForm.contractId !== '')
|
|
const isCreateContractNatureValid = computed(() => isContractNature(createContractForm.contractNature))
|
|
const isCreateContractStartDateValid = computed(() => createContractForm.startDate !== '')
|
|
const isCreateContractEndDateValid = computed(() => !requiresCreateContractEndDate.value || createContractForm.endDate !== '')
|
|
const isCreateContractFormValid = computed(() =>
|
|
isCreateContractValid.value &&
|
|
isCreateContractNatureValid.value &&
|
|
isCreateContractStartDateValid.value &&
|
|
isCreateContractEndDateValid.value
|
|
)
|
|
|
|
const baseInputClass =
|
|
'mt-2 w-full rounded-md border px-3 py-2 text-base text-neutral-900 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-secondary-500/20'
|
|
const readonlyFieldClass = `${baseInputClass} border-neutral-300 bg-neutral-100 text-neutral-700`
|
|
const contractEndDateFieldClass = computed(() => showContractEndDateError.value ? `${baseInputClass} border-red-500` : `${baseInputClass} border-neutral-300`)
|
|
const baseSelectClass = 'mt-2 w-full rounded-md border bg-white px-3 py-2 text-md text-neutral-900'
|
|
const createContractFieldClass = computed(() => createValidationTouched.contractId && !isCreateContractValid.value ? `${baseSelectClass} border-red-500` : `${baseSelectClass} border-neutral-300`)
|
|
const createContractNatureFieldClass = computed(() => createValidationTouched.contractNature && !isCreateContractNatureValid.value ? `${baseSelectClass} border-red-500` : `${baseSelectClass} border-neutral-300`)
|
|
const createContractStartDateFieldClass = computed(() => createValidationTouched.startDate && !isCreateContractStartDateValid.value ? `${baseInputClass} border-red-500` : `${baseInputClass} border-neutral-300`)
|
|
const createContractEndDateFieldClass = computed(() => createValidationTouched.endDate && !isCreateContractEndDateValid.value ? `${baseInputClass} border-red-500` : `${baseInputClass} border-neutral-300`)
|
|
const closeContractWorkedHoursLabel = computed(() => {
|
|
if (contractForm.weeklyHours !== null && contractForm.weeklyHours !== undefined) return `${contractForm.weeklyHours} heures`
|
|
return contractForm.contractName || '-'
|
|
})
|
|
|
|
const resetContractValidation = () => {
|
|
validationTouched.endDate = false
|
|
}
|
|
|
|
const hydrateSuspensionForms = () => {
|
|
const current = employee.value?.currentSuspensions ?? []
|
|
suspensionForms.value = current.map(s => ({
|
|
id: s.id,
|
|
startDate: s.startDate,
|
|
endDate: s.endDate ?? '',
|
|
comment: s.comment ?? ''
|
|
}))
|
|
}
|
|
|
|
const hydrateContractFormFromCurrent = () => {
|
|
const current = employee.value
|
|
const active = currentActiveContractPeriod.value
|
|
if (!current || !active) return
|
|
|
|
contractForm.contractId = active.contractId ?? current.contract?.id ?? ''
|
|
contractForm.contractName = active.contractName ?? current.contract?.name ?? ''
|
|
contractForm.weeklyHours = active.weeklyHours ?? current.contract?.weeklyHours ?? null
|
|
contractForm.contractNature = active.contractNature
|
|
contractForm.startDate = active.startDate
|
|
contractForm.endDate = getTodayYmd()
|
|
contractForm.paidLeaveSettled = false
|
|
contractForm.comment = ''
|
|
}
|
|
|
|
const openCloseContractDrawer = () => {
|
|
if (!employee.value || !canCloseCurrentContract.value) return
|
|
hydrateContractFormFromCurrent()
|
|
resetContractValidation()
|
|
hydrateSuspensionForms()
|
|
isContractDrawerOpen.value = true
|
|
}
|
|
|
|
const setContractDrawerOpen = (open: boolean) => {
|
|
isContractDrawerOpen.value = open
|
|
}
|
|
|
|
const resetCreateValidation = () => {
|
|
createValidationTouched.contractId = false
|
|
createValidationTouched.contractNature = false
|
|
createValidationTouched.startDate = false
|
|
createValidationTouched.endDate = false
|
|
}
|
|
|
|
const openCreateContractDrawer = () => {
|
|
if (!employee.value || !canCreateContract.value) return
|
|
createContractForm.contractId = ''
|
|
createContractForm.contractNature = 'CDI'
|
|
createContractForm.endDate = ''
|
|
createContractForm.startDate = currentActiveContractPeriod.value?.endDate
|
|
? (shiftYmd(currentActiveContractPeriod.value.endDate, 1) ?? currentActiveContractPeriod.value.endDate)
|
|
: getTodayYmd()
|
|
resetCreateValidation()
|
|
isCreateContractDrawerOpen.value = true
|
|
}
|
|
|
|
const setCreateContractDrawerOpen = (open: boolean) => {
|
|
isCreateContractDrawerOpen.value = open
|
|
}
|
|
|
|
const submitContractUpdate = async () => {
|
|
if (!employee.value || isContractSubmitting.value || !currentActiveContractPeriod.value) return
|
|
|
|
validationTouched.endDate = true
|
|
if (!isContractEndDateValid.value) return
|
|
|
|
if (contractForm.endDate < currentActiveContractPeriod.value.startDate) {
|
|
toast.error({
|
|
title: 'Erreur',
|
|
message: `La date de fin doit être postérieure au ${formatDate(currentActiveContractPeriod.value.startDate)}.`
|
|
})
|
|
return
|
|
}
|
|
|
|
isContractSubmitting.value = true
|
|
try {
|
|
await updateEmployee(employee.value.id, {
|
|
firstName: employee.value.firstName,
|
|
lastName: employee.value.lastName,
|
|
siteId: employee.value.site?.id ?? null,
|
|
contractId: Number(contractForm.contractId),
|
|
contractEndDate: contractForm.endDate || null,
|
|
contractPaidLeaveSettled: contractForm.paidLeaveSettled,
|
|
contractComment: contractForm.comment || null
|
|
})
|
|
|
|
isContractDrawerOpen.value = false
|
|
await reloadEmployee()
|
|
} finally {
|
|
isContractSubmitting.value = false
|
|
}
|
|
}
|
|
|
|
const submitCreateContract = async () => {
|
|
if (!employee.value || isCreateContractSubmitting.value) return
|
|
|
|
createValidationTouched.contractId = true
|
|
createValidationTouched.contractNature = true
|
|
createValidationTouched.startDate = true
|
|
createValidationTouched.endDate = true
|
|
if (!isCreateContractFormValid.value) return
|
|
|
|
if (currentActiveContractPeriod.value?.endDate) {
|
|
const minStartDate = shiftYmd(currentActiveContractPeriod.value.endDate, 1) ?? currentActiveContractPeriod.value.endDate
|
|
if (createContractForm.startDate < minStartDate) {
|
|
toast.error({
|
|
title: 'Erreur',
|
|
message: `La date de début doit être au moins le ${formatDate(minStartDate)}.`
|
|
})
|
|
return
|
|
}
|
|
}
|
|
|
|
isCreateContractSubmitting.value = true
|
|
try {
|
|
await updateEmployee(employee.value.id, {
|
|
firstName: employee.value.firstName,
|
|
lastName: employee.value.lastName,
|
|
siteId: employee.value.site?.id ?? null,
|
|
contractId: Number(createContractForm.contractId),
|
|
contractNature: createContractForm.contractNature,
|
|
contractStartDate: createContractForm.startDate,
|
|
contractEndDate: createContractForm.endDate || null
|
|
})
|
|
isCreateContractDrawerOpen.value = false
|
|
await reloadEmployee()
|
|
} finally {
|
|
isCreateContractSubmitting.value = false
|
|
}
|
|
}
|
|
|
|
const submitSuspension = async (index: number) => {
|
|
const form = suspensionForms.value[index]
|
|
if (!form || !form.startDate) return
|
|
|
|
const periodId = currentActiveContractPeriodId.value
|
|
if (!periodId) return
|
|
|
|
isSuspensionSubmitting.value = true
|
|
try {
|
|
if (form.id) {
|
|
await updateSuspension(form.id, {
|
|
startDate: form.startDate,
|
|
endDate: form.endDate || null,
|
|
comment: form.comment || null
|
|
})
|
|
} else {
|
|
await createSuspension({
|
|
contractPeriodId: periodId,
|
|
startDate: form.startDate,
|
|
endDate: form.endDate || null,
|
|
comment: form.comment || null
|
|
})
|
|
}
|
|
await reloadEmployee()
|
|
hydrateSuspensionForms()
|
|
} finally {
|
|
isSuspensionSubmitting.value = false
|
|
}
|
|
}
|
|
|
|
const addSuspensionForm = () => {
|
|
suspensionForms.value.push({
|
|
id: null,
|
|
startDate: '',
|
|
endDate: '',
|
|
comment: ''
|
|
})
|
|
}
|
|
|
|
const loadContracts = async () => {
|
|
contracts.value = await listContracts()
|
|
}
|
|
|
|
watch(showsCreateContractEndDate, (shows) => {
|
|
if (!shows) {
|
|
createContractForm.endDate = ''
|
|
}
|
|
})
|
|
|
|
return {
|
|
contracts,
|
|
contractHistory,
|
|
contractForm,
|
|
createContractForm,
|
|
isContractDrawerOpen,
|
|
isContractSubmitting,
|
|
isCreateContractDrawerOpen,
|
|
isCreateContractSubmitting,
|
|
canCloseCurrentContract,
|
|
canCreateContract,
|
|
readonlyFieldClass,
|
|
closeContractWorkedHoursLabel,
|
|
contractEndDateFieldClass,
|
|
showContractEndDateError,
|
|
isContractEndDateValid,
|
|
createContractNatureFieldClass,
|
|
createContractFieldClass,
|
|
createContractStartDateFieldClass,
|
|
showsCreateContractEndDate,
|
|
requiresCreateContractEndDate,
|
|
createContractEndDateFieldClass,
|
|
isCreateContractFormValid,
|
|
contractNatureLabel,
|
|
contractHistoryLabel,
|
|
formatDate,
|
|
openCloseContractDrawer,
|
|
openCreateContractDrawer,
|
|
setContractDrawerOpen,
|
|
setCreateContractDrawerOpen,
|
|
submitContractUpdate,
|
|
submitCreateContract,
|
|
suspensionForms,
|
|
isSuspensionSubmitting,
|
|
submitSuspension,
|
|
addSuspensionForm,
|
|
currentActiveContractPeriodId,
|
|
loadContracts
|
|
}
|
|
}
|