150 lines
6.3 KiB
Vue
150 lines
6.3 KiB
Vue
<template>
|
|
<div class="h-full overflow-auto">
|
|
|
|
<div v-if="isLoading" class="mt-6 rounded-lg border border-neutral-200 bg-white p-6 text-md text-neutral-600">
|
|
Chargement...
|
|
</div>
|
|
|
|
<div v-else-if="!employee"
|
|
class="mt-6 rounded-lg border border-neutral-200 bg-white p-6 text-md text-neutral-600">
|
|
Employé introuvable.
|
|
</div>
|
|
|
|
<div v-else>
|
|
<div class="flex items-center justify-between">
|
|
<h1 class="text-4xl font-bold text-primary-500">{{ employee.firstName }} {{ employee.lastName }}</h1>
|
|
<div class="text-right">
|
|
<p class="font-bold text-[20px]">{{ contractNatureLabel(employee.currentContractNature) }} {{ employee.contract?.weeklyHours ?? '-' }} heures</p>
|
|
<p class="text-[18px]">{{ employee.site?.name ?? '-' }}</p>
|
|
</div>
|
|
</div>
|
|
<div class="mt-12 border-b border-primary-500">
|
|
<div class="flex justify-center gap-16 text-2xl font-bold">
|
|
<button
|
|
class="pb-2 border-b-2 flex items-center gap-3"
|
|
:class="activeTab === 'contract'
|
|
? 'border-primary-500 text-primary-500'
|
|
: 'border-transparent text-primary-500/50 hover:text-primary-500'"
|
|
@click="activeTab = 'contract'"
|
|
>
|
|
<Icon name="mdi:magnify" size="24" class="align-self"/>
|
|
Suivi contrat
|
|
</button>
|
|
<button
|
|
class="pb-2 border-b-2 flex items-center gap-3"
|
|
:class="activeTab === 'leave'
|
|
? 'border-primary-500 text-primary-500'
|
|
: 'border-transparent text-primary-500/50 hover:text-primary-500'"
|
|
@click="activeTab = 'leave'"
|
|
>
|
|
<Icon name="mdi:magnify" size="24" class="align-self"/>
|
|
Congé
|
|
</button>
|
|
<button
|
|
class="pb-2 border-b-2 flex items-center gap-3"
|
|
:class="activeTab === 'rtt'
|
|
? 'border-primary-500 text-primary-500'
|
|
: 'border-transparent text-primary-500/50 hover:text-primary-500'"
|
|
@click="activeTab = 'rtt'"
|
|
>
|
|
<Icon name="mdi:magnify" size="24" class="align-self"/>
|
|
RTT
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<section v-if="activeTab === 'contract'" class="mt-8">
|
|
<div class="overflow-hidden rounded-lg border border-neutral-200 bg-white">
|
|
<div class="grid grid-cols-4 border-b border-neutral-200 bg-neutral-50 px-6 py-3 text-md font-semibold text-neutral-700">
|
|
<p>Contrat</p>
|
|
<p>Heures</p>
|
|
<p>Date de début</p>
|
|
<p>Date de fin</p>
|
|
</div>
|
|
<div v-if="contractHistory.length === 0" class="px-6 py-4 text-md text-neutral-600">
|
|
Aucun historique de contrat.
|
|
</div>
|
|
<div v-else>
|
|
<div
|
|
v-for="item in contractHistory"
|
|
:key="`${item.startDate}-${item.endDate ?? 'open'}-${item.contractId ?? item.contractName}`"
|
|
class="grid grid-cols-4 border-b border-neutral-100 px-6 py-3 text-md text-primary-500 last:border-b-0"
|
|
>
|
|
<p>{{ contractNatureLabel(item.contractNature) }}</p>
|
|
<p>{{ contractHistoryLabel(item) }}</p>
|
|
<p>{{ formatDate(item.startDate) }}</p>
|
|
<p>{{ formatDate(item.endDate) }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-center mt-8 gap-12">
|
|
<button class="bg-blue-500 text-white rounded-md w-[200px]">Modifier</button>
|
|
<button class="bg-primary-500 px-4 py-2 text-white text-md rounded-md flex justify-center items-center gap-2 w-[200px]">
|
|
<Icon name="mdi:plus-thick" size="16" />
|
|
Ajouter
|
|
</button>
|
|
</div>
|
|
</section>
|
|
<section v-else-if="activeTab === 'leave'" class="mt-8">
|
|
<!-- Bloc Congé -->
|
|
</section>
|
|
<section v-else class="mt-8">
|
|
<!-- Bloc RTT -->
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type {ContractHistoryItem, Employee} from '~/services/dto/employee'
|
|
import {getEmployee} from '~/services/employees'
|
|
|
|
const route = useRoute()
|
|
const employee = ref<Employee | null>(null)
|
|
const isLoading = ref(false)
|
|
const activeTab = ref<'contract' | 'leave' | 'rtt'>('contract')
|
|
|
|
useHead(() => ({
|
|
title: employee.value
|
|
? `${employee.value.firstName} ${employee.value.lastName}`
|
|
: 'Détail employé'
|
|
}))
|
|
|
|
const contractNatureLabel = (value?: 'CDI' | 'CDD' | 'INTERIM') => {
|
|
if (value === 'CDD') return 'CDD'
|
|
if (value === 'INTERIM') return 'Intérim'
|
|
return 'CDI'
|
|
}
|
|
|
|
const contractHistory = computed(() => employee.value?.contractHistory ?? [])
|
|
|
|
const formatDate = (value?: string | null) => {
|
|
if (!value) return 'En cours'
|
|
const [year, month, day] = value.split('-')
|
|
if (!year || !month || !day) return value
|
|
return `${day}/${month}/${year}`
|
|
}
|
|
|
|
const contractHistoryLabel = (item: ContractHistoryItem) => {
|
|
if (item.weeklyHours !== null && item.weeklyHours !== undefined) {
|
|
return `${item.weeklyHours} heures`
|
|
}
|
|
return item.contractName ?? '-'
|
|
}
|
|
|
|
onMounted(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)
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
})
|
|
</script>
|