feat : ajout de la gestion RTT
This commit is contained in:
@@ -1,56 +1,65 @@
|
||||
<template>
|
||||
<section class="mt-8">
|
||||
<div class="grid grid-cols-4 rounded-md bg-primary-500 text-white text-[20]">
|
||||
<div class="flex flex-col jutify-center items-center border-r-4 border-white py-3">
|
||||
<p><strong class="uppercase font-semibold">Acquis année :</strong> {{ formatCount(summary?.acquiredDays) }} Jours</p>
|
||||
<p><strong class="uppercase font-semibold">Reste à prendre :</strong> {{ formatCount(summary?.remainingDays) }} Jours</p>
|
||||
</div>
|
||||
<div class="flex flex-col jutify-center items-center border-r-4 border-white py-3">
|
||||
<p><span class="uppercase font-semibold">Samedi acquis :</span> {{ formatCount(summary?.acquiredSaturdays) }} Jours</p>
|
||||
<p><span class="uppercase font-semibold">Reste à prendre :</span> {{ formatCount(summary?.remainingSaturdays) }} Jours</p>
|
||||
</div>
|
||||
<div class="flex flex-col jutify-center items-center border-r-4 border-white py-3">
|
||||
<p><span class="uppercase font-semibold">Acquis fractionné :</span></p>
|
||||
<p>{{ formatCount(summary?.fractionedDays) }} Jours</p>
|
||||
</div>
|
||||
<div class="flex flex-col jutify-center items-center py-3">
|
||||
<p><span class="uppercase font-semibold">En cours d'acquisition :</span></p>
|
||||
<p>{{ formatCount(summary?.accruingDays) }} Jours</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-8 grid grid-cols-4 gap-10">
|
||||
<div v-for="month in months" :key="month.label" class="rounded-md bg-tertiary-500 text-primary-500">
|
||||
<div class="flex justify-center rounded-t-md bg-primary-500 py-1 font-bold uppercase text-white">{{ month.label }}</div>
|
||||
<div class="grid grid-cols-7 gap-1 px-2 py-2 text-center text-md font-bold">
|
||||
<p v-for="weekday in weekDayLabels" :key="weekday">{{ weekday }}</p>
|
||||
<section class="flex h-full min-h-0 flex-col overflow-hidden pt-8">
|
||||
<div class="grid grid-cols-4 rounded-md bg-primary-500 text-white text-[20]">
|
||||
<div class="flex flex-col jutify-center items-center border-r-4 border-white py-3">
|
||||
<p><strong class="uppercase font-semibold">Acquis année :</strong> {{
|
||||
formatCount(summary?.acquiredDays)
|
||||
}} Jours</p>
|
||||
<p><strong class="uppercase font-semibold">Reste à prendre :</strong>
|
||||
{{ formatCount(summary?.remainingDays) }} Jours</p>
|
||||
</div>
|
||||
<div class="grid grid-cols-7 gap-4 px-2 pb-2 text-center text-md">
|
||||
<template v-for="(day, index) in month.cells" :key="`${month.label}-${index}`">
|
||||
<div v-if="!day" class="h-6" />
|
||||
<div
|
||||
v-else
|
||||
class="flex items-center justify-center"
|
||||
>
|
||||
<div
|
||||
class="h-6 w-6"
|
||||
:class="getDayClass(day.leave)"
|
||||
:style="getDayStyle(day.leave)"
|
||||
:title="getDayTitle(day.leave)"
|
||||
>
|
||||
{{ getDayText(day) }}
|
||||
<div class="flex flex-col jutify-center items-center border-r-4 border-white py-3">
|
||||
<p><span class="uppercase font-semibold">Samedi acquis :</span>
|
||||
{{ formatCount(summary?.acquiredSaturdays) }} Jours</p>
|
||||
<p><span class="uppercase font-semibold">Reste à prendre :</span>
|
||||
{{ formatCount(summary?.remainingSaturdays) }} Jours</p>
|
||||
</div>
|
||||
<div class="flex flex-col jutify-center items-center border-r-4 border-white py-3">
|
||||
<p><span class="uppercase font-semibold">Acquis fractionné :</span></p>
|
||||
<p>{{ formatCount(summary?.fractionedDays) }} Jours</p>
|
||||
</div>
|
||||
<div class="flex flex-col jutify-center items-center py-3">
|
||||
<p><span class="uppercase font-semibold">En cours d'acquisition :</span></p>
|
||||
<p>{{ formatCount(summary?.accruingDays) }} Jours</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-8 min-h-0 flex-1 overflow-y-auto pr-2">
|
||||
<div class="grid grid-cols-4 gap-10">
|
||||
<div v-for="month in months" :key="month.label" class="rounded-md bg-tertiary-500 text-primary-500">
|
||||
<div class="flex justify-center rounded-t-md bg-primary-500 py-1 font-bold uppercase text-white">
|
||||
{{ month.label }}
|
||||
</div>
|
||||
<div class="grid grid-cols-7 gap-1 px-2 py-2 text-center text-md font-bold">
|
||||
<p v-for="weekday in weekDayLabels" :key="weekday">{{ weekday }}</p>
|
||||
</div>
|
||||
<div class="grid grid-cols-7 gap-4 px-2 pb-2 text-center text-md">
|
||||
<template v-for="(day, index) in month.cells" :key="`${month.label}-${index}`">
|
||||
<div v-if="!day" class="h-6"/>
|
||||
<div
|
||||
v-else
|
||||
class="flex items-center justify-center"
|
||||
>
|
||||
<div
|
||||
class="h-6 w-6"
|
||||
:class="getDayClass(day.leave)"
|
||||
:style="getDayStyle(day.leave)"
|
||||
:title="getDayTitle(day.leave)"
|
||||
>
|
||||
{{ getDayText(day) }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Absence } from '~/services/dto/absence'
|
||||
import type { EmployeeLeaveSummary } from '~/services/dto/employee-leave-summary'
|
||||
import { normalizeDate, toYmd } from '~/utils/date'
|
||||
import type {Absence} from '~/services/dto/absence'
|
||||
import type {EmployeeLeaveSummary} from '~/services/dto/employee-leave-summary'
|
||||
import {normalizeDate, toYmd} from '~/utils/date'
|
||||
|
||||
type DayLeaveState = {
|
||||
am: boolean
|
||||
@@ -212,12 +221,12 @@ const getDayStyle = (leave: DayLeaveState | null) => {
|
||||
|
||||
const color = leave.hasOtherTypes ? '#dc2626' : '#222783'
|
||||
const backgroundImage = leave.am
|
||||
? `linear-gradient(135deg, ${color} 0 50%, transparent 50% 100%)`
|
||||
: `linear-gradient(135deg, transparent 0 50%, ${color} 50% 100%)`
|
||||
? `linear-gradient(135deg, ${color} 0 50%, transparent 50% 100%)`
|
||||
: `linear-gradient(135deg, transparent 0 50%, ${color} 50% 100%)`
|
||||
|
||||
return {
|
||||
backgroundImage,
|
||||
backgroundColor: 'transparent'
|
||||
backgroundImage,
|
||||
backgroundColor: 'transparent'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,122 @@
|
||||
<template>
|
||||
<section class="mt-8">
|
||||
<div class="rounded-lg border border-neutral-200 bg-white p-6 text-md text-neutral-600">
|
||||
Bloc RTT (à implémenter)
|
||||
<section class="flex h-full min-h-0 flex-col overflow-hidden pt-8">
|
||||
<div class="flex justify-center items-center bg-primary-500 rounded-md text-white py-5 text-[20px]">
|
||||
<p><span class="font-semibold uppercase">RTT à la date du jour :</span> {{ formatDays(summary?.availableMinutes ?? 0) }}</p>
|
||||
</div>
|
||||
<div class="mt-8 min-h-0 flex-1 overflow-y-auto pr-2">
|
||||
<div class="grid grid-cols-4 gap-10 pb-4">
|
||||
<div
|
||||
v-for="month in months"
|
||||
:key="month.month"
|
||||
class="rounded-md bg-tertiary-500 text-primary-500"
|
||||
>
|
||||
<div class="flex justify-center rounded-t-md bg-primary-500 py-3 font-bold text-white text-[18px]">
|
||||
{{ month.label }}
|
||||
</div>
|
||||
<div class="grid grid-cols-[60%_40%] text-[18px] border border-primary-500">
|
||||
<template v-for="week in month.weeks" :key="week.key">
|
||||
<div class="py-[6px] pl-3 border-r border-b border-primary-500">
|
||||
<span v-if="week.isEmpty"> </span>
|
||||
<span v-else>Semaine {{ week.weekNumber }}</span>
|
||||
</div>
|
||||
<div class="py-[6px] pl-3 border-b border-primary-500">
|
||||
<span v-if="week.isEmpty"> </span>
|
||||
<span v-else>{{ formatMinutes(week.recoveryMinutes) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="py-[6px] pl-3 border-r border-b border-primary-500 font-semibold">Total</div>
|
||||
<div class="py-[6px] pl-3 border-b border-primary-500 font-semibold">{{ formatMinutes(month.totalMinutes) }}</div>
|
||||
<div class="py-[6px] pl-3 border-r border-primary-500">Heure payée</div>
|
||||
<div class="py-[6px] pl-3">0h</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { EmployeeRttSummary } from '~/services/dto/employee-rtt-summary'
|
||||
|
||||
const props = defineProps<{
|
||||
summary: EmployeeRttSummary | null
|
||||
}>()
|
||||
|
||||
const monthLabels = [
|
||||
'Janvier',
|
||||
'Fevrier',
|
||||
'Mars',
|
||||
'Avril',
|
||||
'Mai',
|
||||
'Juin',
|
||||
'Juillet',
|
||||
'Aout',
|
||||
'Septembre',
|
||||
'Octobre',
|
||||
'Novembre',
|
||||
'Decembre'
|
||||
] as const
|
||||
|
||||
const months = computed(() => {
|
||||
type DisplayWeek = {
|
||||
key: string
|
||||
weekNumber: number
|
||||
recoveryMinutes: number
|
||||
isEmpty?: boolean
|
||||
}
|
||||
|
||||
const byMonth = new Map<number, { month: number; label: string; weeks: DisplayWeek[]; totalMinutes: number }>()
|
||||
const orderedMonths = [6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5]
|
||||
for (const month of orderedMonths) {
|
||||
byMonth.set(month, {
|
||||
month,
|
||||
label: monthLabels[month - 1],
|
||||
weeks: [],
|
||||
totalMinutes: 0
|
||||
})
|
||||
}
|
||||
|
||||
for (const week of props.summary?.weeks ?? []) {
|
||||
const month = byMonth.get(week.month)
|
||||
if (!month) continue
|
||||
|
||||
month.weeks.push({
|
||||
key: week.weekStart,
|
||||
weekNumber: week.weekNumber,
|
||||
recoveryMinutes: week.recoveryMinutes
|
||||
})
|
||||
month.totalMinutes += week.recoveryMinutes
|
||||
}
|
||||
|
||||
return orderedMonths
|
||||
.map((monthNumber) => byMonth.get(monthNumber)!)
|
||||
.filter(Boolean)
|
||||
.map((month) => {
|
||||
const minRows = 5
|
||||
const missing = Math.max(0, minRows - month.weeks.length)
|
||||
for (let i = 0; i < missing; i += 1) {
|
||||
month.weeks.push({
|
||||
key: `empty-${month.month}-${i}`,
|
||||
weekNumber: 0,
|
||||
recoveryMinutes: 0,
|
||||
isEmpty: true
|
||||
})
|
||||
}
|
||||
return month
|
||||
})
|
||||
})
|
||||
|
||||
const formatMinutes = (minutes: number) => {
|
||||
const abs = Math.abs(minutes)
|
||||
const hours = Math.floor(abs / 60)
|
||||
const rest = abs % 60
|
||||
const sign = minutes < 0 ? '-' : ''
|
||||
return `${sign}${hours}h${rest.toString().padStart(2, '0')}`
|
||||
}
|
||||
|
||||
const formatDays = (minutes: number) => {
|
||||
const days = minutes / 420
|
||||
const sign = days < 0 ? '-' : ''
|
||||
return `${sign}${Math.abs(days).toFixed(2)} j`
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user