feat : agence d'intérim sur les contrats INTERIM + renommage Types d'absence en Types de statut + colonne Absence en Statut
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
- Nouvelle entité InterimAgency (table interim_agencies, API lecture seule) - Sélecteur agence conditionnel dans les formulaires création employé et ajout contrat - Affichage "Intérim (NomAgence)" sur la liste employés et l'historique contrat - Date de fin obligatoire côté frontend pour CDD et INTERIM (aligné backend) - Renommage "Types d'absence" → "Types de statut" (sidebar, page, titre) - Renommage en-tête "Absence" → "Statut" sur les vues jour heures et conducteurs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="h-full flex flex-col overflow-hidden">
|
||||
<div class="flex items-center justify-between pb-6">
|
||||
<h1 class="text-4xl font-bold text-primary-500">Types d'absence</h1>
|
||||
<h1 class="text-4xl font-bold text-primary-500">Types de statut</h1>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-lg bg-primary-500 px-4 py-2 text-md font-semibold text-white hover:bg-secondary-500"
|
||||
@@ -164,7 +164,7 @@ import type { AbsenceType } from '~/services/dto/absence-type'
|
||||
import { createAbsenceType, deleteAbsenceType, listAbsenceTypes, updateAbsenceType } from '~/services/absence-types'
|
||||
|
||||
useHead({
|
||||
title: 'Types d\'absences'
|
||||
title: 'Types de statut'
|
||||
})
|
||||
|
||||
const isDrawerOpen = ref(false)
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
:on-submit-suspension="submitSuspension"
|
||||
:on-add-suspension-form="addSuspensionForm"
|
||||
:current-contract-period-id="currentActiveContractPeriodId"
|
||||
:interim-agencies="interimAgencies"
|
||||
/>
|
||||
<div v-else-if="showLeaveTab && activeTab === 'leave'" class="h-full">
|
||||
<div v-if="isLeaveLoading" class="mt-6 rounded-lg border border-neutral-200 bg-white p-6 text-md text-neutral-600">
|
||||
@@ -295,6 +296,7 @@ const {
|
||||
submitSuspension,
|
||||
addSuspensionForm,
|
||||
currentActiveContractPeriodId,
|
||||
interimAgencies,
|
||||
isLeaveLoading,
|
||||
isRttLoading,
|
||||
mileageAllowances,
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
class="absolute inset-0 flex items-center justify-center bg-primary-500 p-4 text-white opacity-0 transition-opacity duration-200 group-hover:opacity-100">
|
||||
<div class="w-full rounded-md bg-white/15 p-4 text-sm">
|
||||
<p class="text-base font-semibold">{{ employee.lastName }} {{ employee.firstName }}</p>
|
||||
<p><strong>Type:</strong> {{ contractNatureLabel(employee.currentContractNature) }}</p>
|
||||
<p><strong>Type:</strong> {{ employee.currentInterimAgencyName ? `${contractNatureLabel(employee.currentContractNature)} (${employee.currentInterimAgencyName})` : contractNatureLabel(employee.currentContractNature) }}</p>
|
||||
<p><strong>Temps de travail:</strong> {{ employee.contract?.name ?? '-' }}</p>
|
||||
<p><strong>Site:</strong> {{ employee.site?.name ?? '-' }}</p>
|
||||
<p><strong>Date d'entrée :</strong> {{ employee.entryDate ? employee.entryDate.split('-').reverse().join('/') : '-' }}</p>
|
||||
@@ -147,6 +147,21 @@
|
||||
Le type de contrat est obligatoire.
|
||||
</p>
|
||||
</div>
|
||||
<div v-if="form.contractNature === 'INTERIM'">
|
||||
<label class="text-md font-semibold text-neutral-700" for="interim-agency">
|
||||
Agence d'intérim
|
||||
</label>
|
||||
<select
|
||||
id="interim-agency"
|
||||
v-model="form.interimAgencyId"
|
||||
class="mt-2 w-full rounded-md border border-neutral-300 bg-white px-3 py-2 text-md text-neutral-900"
|
||||
>
|
||||
<option value="">Aucune</option>
|
||||
<option v-for="agency in interimAgencies" :key="agency.id" :value="agency.id">
|
||||
{{ agency.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-md font-semibold text-neutral-700" for="contract">
|
||||
Temps de travail <span class="text-red-600">*</span>
|
||||
@@ -191,7 +206,7 @@
|
||||
:class="contractEndDateFieldClass"
|
||||
/>
|
||||
<p v-if="showContractEndDateError" class="mt-1 text-sm text-red-600">
|
||||
La date de fin est obligatoire pour un CDD.
|
||||
La date de fin est obligatoire pour un CDD ou un Intérim.
|
||||
</p>
|
||||
</div>
|
||||
<div class="rounded-md border border-neutral-200 bg-neutral-50 p-3">
|
||||
@@ -246,6 +261,7 @@ import type {Site} from '~/services/dto/site'
|
||||
import {listContracts} from '~/services/contracts'
|
||||
import {createEmployee, deleteEmployee, listEmployees, updateEmployee} from '~/services/employees'
|
||||
import {listSites} from '~/services/sites'
|
||||
import {listInterimAgencies, type InterimAgency} from '~/services/interim-agencies'
|
||||
import SiteFilterSelector from '~/components/SiteFilterSelector.vue'
|
||||
import SalaryRecapDrawer from '~/components/SalaryRecapDrawer.vue'
|
||||
import {contractNatureLabel, isContractNature, requiresContractEndDate, showsContractEndDate} from '~/utils/contract'
|
||||
@@ -269,6 +285,7 @@ const drawerTitle = computed(() =>
|
||||
const employees = ref<Employee[]>([])
|
||||
const sites = ref<Site[]>([])
|
||||
const contracts = ref<Contract[]>([])
|
||||
const interimAgencies = ref<InterimAgency[]>([])
|
||||
const employeeFilter = ref('')
|
||||
const contractStatusFilter = ref<'active' | 'inactive' | 'all'>('active')
|
||||
const selectedSiteIds = ref<number[]>([])
|
||||
@@ -300,7 +317,8 @@ const form = reactive({
|
||||
contractStartDate: '',
|
||||
contractEndDate: '',
|
||||
isDriver: false,
|
||||
workDaysHours: null as Record<number, number> | null
|
||||
workDaysHours: null as Record<number, number> | null,
|
||||
interimAgencyId: '' as number | ''
|
||||
})
|
||||
|
||||
const validationTouched = reactive({
|
||||
@@ -451,8 +469,12 @@ const loadContracts = async () => {
|
||||
contracts.value = await listContracts()
|
||||
}
|
||||
|
||||
const loadInterimAgencies = async () => {
|
||||
interimAgencies.value = await listInterimAgencies()
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await Promise.all([loadEmployees(), loadSites(), loadContracts()])
|
||||
await Promise.all([loadEmployees(), loadSites(), loadContracts(), loadInterimAgencies()])
|
||||
if (form.contractStartDate === '') {
|
||||
form.contractStartDate = new Date().toISOString().slice(0, 10)
|
||||
}
|
||||
@@ -503,7 +525,8 @@ const handleSubmit = async () => {
|
||||
contractStartDate: form.contractStartDate,
|
||||
contractEndDate: form.contractEndDate || null,
|
||||
isDriverInput: form.isDriver,
|
||||
workDaysHoursInput: requiresSchedule.value ? form.workDaysHours : null
|
||||
workDaysHoursInput: requiresSchedule.value ? form.workDaysHours : null,
|
||||
interimAgencyId: form.contractNature === 'INTERIM' && form.interimAgencyId !== '' ? Number(form.interimAgencyId) : null
|
||||
})
|
||||
}
|
||||
|
||||
@@ -516,6 +539,7 @@ const handleSubmit = async () => {
|
||||
form.contractEndDate = ''
|
||||
form.isDriver = false
|
||||
form.workDaysHours = null
|
||||
form.interimAgencyId = ''
|
||||
editingEmployee.value = null
|
||||
isDrawerOpen.value = false
|
||||
await loadEmployees()
|
||||
@@ -542,6 +566,12 @@ watch(showsContractEndDateComputed, (shows) => {
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => form.contractNature, (nature) => {
|
||||
if (nature !== 'INTERIM') {
|
||||
form.interimAgencyId = ''
|
||||
}
|
||||
})
|
||||
|
||||
watch(requiresSchedule, (required) => {
|
||||
if (!required) {
|
||||
form.workDaysHours = null
|
||||
@@ -567,6 +597,7 @@ const openCreate = () => {
|
||||
form.contractEndDate = ''
|
||||
form.isDriver = false
|
||||
form.workDaysHours = null
|
||||
form.interimAgencyId = ''
|
||||
isDrawerOpen.value = true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user