feat : modification de la page employé WIP + ajout d'une navbar

This commit is contained in:
2026-03-02 09:50:09 +01:00
parent 107417a571
commit ea06059c0b
9 changed files with 375 additions and 85 deletions

View File

@@ -0,0 +1,71 @@
<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>
<NuxtLink
to="/employees"
class="rounded-lg border border-neutral-200 px-4 py-2 text-md font-semibold text-neutral-700 hover:bg-neutral-100"
>
Retour
</NuxtLink>
</div>
<div class="mt-6 rounded-lg border border-neutral-200 bg-white p-6">
<p class="text-xl font-semibold text-neutral-900">{{ employee.firstName }} {{ employee.lastName }}</p>
<p class="mt-2 text-md text-neutral-700">Site: {{ employee.site?.name ?? '-' }}</p>
<p class="text-md text-neutral-700">Type de contrat: {{
contractNatureLabel(employee.currentContractNature)
}}</p>
<p class="text-md text-neutral-700">Temps de travail: {{ employee.contract?.name ?? '-' }}</p>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import type {Employee} from '~/services/dto/employee'
import {getEmployee} from '~/services/employees'
const route = useRoute()
const employee = ref<Employee | null>(null)
const isLoading = ref(false)
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'
}
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>

View File

@@ -1,24 +1,22 @@
<template>
<div class="h-full overflow-hidden flex flex-col">
<div class="flex-col">
<div class="shrink-0">
<div class="flex items-center justify-between">
<h1 class="text-4xl font-bold text-primary-500">Employés</h1>
<button
type="button"
class="flex items-center gap-2 rounded-lg bg-primary-500 px-4 py-2 text-md font-semibold text-white hover:bg-secondary-500"
@click="openCreate"
>
<Icon name="mdi:plus-thick" size="16" class="text-white"/>
Ajouter un employé
</button>
</div>
<div class="flex flex-col gap-3 py-6">
<div class="flex justify-between">
<SiteFilterSelector v-if="sites.length > 0" v-model="selectedSiteIds" :sites="sites" />
<button
type="button"
class="rounded-lg bg-primary-500 px-4 py-2 text-md font-semibold text-white hover:bg-secondary-500"
@click="openCreate"
>
Ajouter un employé
</button>
</div>
<div class="flex gap-10 py-7">
<div class="w-80">
<EmployeeNameFilterInput v-model="employeeFilter" />
</div>
<SiteFilterSelector v-if="sites.length > 0" v-model="selectedSiteIds" :sites="sites" />
</div>
</div>
@@ -29,57 +27,33 @@
Aucun employé pour le moment.
</div>
<div v-else class="flex-1 min-h-0 rounded-lg border border-neutral-200 bg-white overflow-hidden">
<div class="h-full overflow-auto">
<div class="min-w-[900px]">
<div class="grid grid-cols-[120px_1fr_1fr_180px_180px_200px] gap-4 border-b border-neutral-200 bg-tertiary-500 px-6 py-3 text-md font-semibold text-neutral-700 sticky top-0 z-10">
<span class="text-left">Prénom</span>
<span class="text-left">Nom</span>
<span class="text-left">Site</span>
<span class="text-left">Nature</span>
<span class="text-left">Contrat</span>
<span class="text-right">Actions</span>
</div>
<div v-if="isLoading" class="px-6 py-4 text-md text-neutral-500">
Chargement...
</div>
<div v-else>
<div
v-for="employee in filteredEmployees"
:key="employee.id"
class="grid grid-cols-[120px_1fr_1fr_180px_180px_200px] items-center gap-4 border-b border-neutral-100 px-6 py-3 text-md text-neutral-800 last:border-b-0"
>
<span>{{ employee.firstName }}</span>
<span>{{ employee.lastName }}</span>
<span
class="inline-flex w-fit max-w-full rounded-md px-2 py-1 text-sm font-semibold"
:style="employee.site ? { backgroundColor: employee.site.color, color: '#0f172a' } : {}"
:class="employee.site ? '' : 'bg-neutral-100 text-neutral-600'"
>
{{ employee.site?.name ?? '-' }}
</span>
<span>{{ contractNatureLabel(employee.currentContractNature) }}</span>
<span>{{ employee.contract?.name ?? '-' }}</span>
<div class="flex items-center justify-end gap-2">
<button
type="button"
class="rounded-md border border-neutral-200 px-2 py-1 text-md font-semibold text-neutral-700 hover:bg-neutral-100"
@click="openEdit(employee)"
>
Modifier
</button>
<button
type="button"
class="rounded-md border border-red-200 px-2 py-1 text-md font-semibold text-red-600 hover:bg-red-50"
@click="confirmDelete(employee)"
>
Supprimer
</button>
</div>
</div>
<div v-else class="grid grid-cols-4 gap-8 lg:[grid-template-columns:repeat(auto-fit,328px)]">
<NuxtLink
v-for="employee in filteredEmployees"
:key="employee.id"
:to="`/employees/${employee.id}`"
target="_blank"
rel="noopener noreferrer"
class="group relative h-[328px] w-[328px] overflow-hidden rounded-lg bg-tertiary-500 p-4 transition-all duration-200 hover:shadow-md"
>
<div class="flex flex-col items-center gap-7 transition-opacity duration-200 group-hover:opacity-0">
<div class="rounded-full bg-neutral-300 h-[175px] w-[175px]"></div>
<div class="text-center text-[20px]">
<p class="text-primary-500 font-bold">{{ employee.lastName }} {{ employee.firstName }}</p>
<p>Nom du poste occupé</p>
<p>Site ({{ employee.site?.name ?? '-' }})</p>
</div>
</div>
</div>
<div 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>Type: {{ contractNatureLabel(employee.currentContractNature) }}</p>
<p>Temps de travail: {{ employee.contract?.name ?? '-' }}</p>
<p>Site: {{ employee.site?.name ?? '-' }}</p>
</div>
</div>
</NuxtLink>
</div>
<AppDrawer v-model="isDrawerOpen" :title="drawerTitle">