208 lines
7.4 KiB
Vue
208 lines
7.4 KiB
Vue
<template>
|
|
<section class="mt-8">
|
|
<div class="overflow-hidden bg-white">
|
|
<div
|
|
class="grid grid-cols-3 border border-black bg-tertiary-500 px-6 py-3 text-[20px] font-semibold text-black rounded-t-md">
|
|
<p>Mois</p>
|
|
<p>Montant €</p>
|
|
<p>Commentaire</p>
|
|
</div>
|
|
<div v-if="bonuses.length === 0" class="px-6 py-4 text-[20px] font-bold text-primary-500 border-x border-b border-primary-500 rounded-b-md">
|
|
Aucune prime.
|
|
</div>
|
|
<div v-else class="border-x border-b border-primary-500 rounded-b-md">
|
|
<div
|
|
v-for="item in bonuses"
|
|
:key="item.id"
|
|
class="grid grid-cols-3 border-b border-primary-500 px-6 py-3 text-md font-bold text-primary-500 last:border-b-0 cursor-pointer hover:bg-tertiary-500"
|
|
@click="onOpenEditDrawer(item)"
|
|
>
|
|
<p>{{ formatMonth(item.month) }}</p>
|
|
<p>{{ item.amount }} €</p>
|
|
<p>{{ item.comment ?? '-' }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-center mb-4 mt-8">
|
|
<button
|
|
type="button"
|
|
class="flex w-[200px] items-center justify-center gap-2 rounded-md bg-primary-500 px-4 py-2 text-md text-white disabled:cursor-not-allowed disabled:opacity-50"
|
|
@click="onOpenCreateDrawer"
|
|
>
|
|
+ Ajouter
|
|
</button>
|
|
</div>
|
|
|
|
<AppDrawer v-model="isDrawerOpen" :title="isEditing ? 'Modification prime' : 'Nouvelle prime'">
|
|
<form class="space-y-4" @submit.prevent="onSubmit">
|
|
<div>
|
|
<label class="text-md font-semibold text-neutral-700" for="bonus-month">
|
|
Mois <span class="text-red-600">*</span>
|
|
</label>
|
|
<input
|
|
id="bonus-month"
|
|
v-model="form.month"
|
|
type="month"
|
|
class="capitalize mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-base text-neutral-900 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-secondary-500/20"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="text-md font-semibold text-neutral-700" for="bonus-amount">
|
|
Montant (€) <span class="text-red-600">*</span>
|
|
</label>
|
|
<input
|
|
id="bonus-amount"
|
|
v-model.number="form.amount"
|
|
type="number"
|
|
step="0.01"
|
|
min="0"
|
|
class="mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-base text-neutral-900 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-secondary-500/20"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="text-md font-semibold text-neutral-700" for="bonus-comment">
|
|
Commentaire
|
|
</label>
|
|
<textarea
|
|
id="bonus-comment"
|
|
v-model="form.comment"
|
|
rows="3"
|
|
class="mt-2 w-full rounded-md border border-neutral-300 px-3 py-2 text-base text-neutral-900 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-secondary-500/20"
|
|
placeholder="Commentaire..."
|
|
/>
|
|
</div>
|
|
|
|
<div v-if="isEditing" class="grid grid-cols-2 gap-3 pt-2">
|
|
<button
|
|
type="button"
|
|
class="flex items-center justify-center rounded-md bg-red-500 px-4 py-2 text-md font-semibold text-white hover:bg-red-600"
|
|
@click="onDelete"
|
|
>
|
|
Supprimer
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
class="flex items-center justify-center rounded-md bg-primary-500 px-4 py-2 text-md font-semibold text-white hover:bg-secondary-500 disabled:cursor-not-allowed disabled:opacity-50"
|
|
:disabled="!isFormValid"
|
|
>
|
|
Modifier
|
|
</button>
|
|
</div>
|
|
<div v-else class="flex justify-center pt-2">
|
|
<button
|
|
type="submit"
|
|
class="flex w-[200px] items-center justify-center gap-2 rounded-md bg-primary-500 px-4 py-2 text-md font-semibold text-white hover:bg-secondary-500 disabled:cursor-not-allowed disabled:opacity-50"
|
|
:disabled="!isFormValid"
|
|
>
|
|
+ Ajouter
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</AppDrawer>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { Bonus } from '~/services/dto/bonus'
|
|
import AppDrawer from '~/components/AppDrawer.vue'
|
|
|
|
const props = defineProps<{
|
|
bonuses: Bonus[]
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
(event: 'create', data: { month: string; amount: number; comment?: string }): void
|
|
(event: 'update', id: number, data: { month: string; amount: number; comment?: string }): void
|
|
(event: 'delete', id: number): void
|
|
}>()
|
|
|
|
const isDrawerOpen = ref(false)
|
|
const isEditing = ref(false)
|
|
const editingItem = ref<Bonus | null>(null)
|
|
|
|
const currentYearMonth = () => {
|
|
const now = new Date()
|
|
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`
|
|
}
|
|
|
|
const form = reactive({
|
|
month: currentYearMonth(),
|
|
amount: 0,
|
|
comment: ''
|
|
})
|
|
|
|
const isFormValid = computed(() => {
|
|
return form.month && form.amount > 0
|
|
})
|
|
|
|
const monthLabels: Record<number, string> = {
|
|
1: 'Janvier',
|
|
2: 'Février',
|
|
3: 'Mars',
|
|
4: 'Avril',
|
|
5: 'Mai',
|
|
6: 'Juin',
|
|
7: 'Juillet',
|
|
8: 'Août',
|
|
9: 'Septembre',
|
|
10: 'Octobre',
|
|
11: 'Novembre',
|
|
12: 'Décembre'
|
|
}
|
|
|
|
const formatMonth = (dateStr: string): string => {
|
|
const date = new Date(dateStr)
|
|
if (Number.isNaN(date.getTime())) return dateStr
|
|
const month = date.getMonth() + 1
|
|
const year = date.getFullYear()
|
|
return `${monthLabels[month]} ${year}`
|
|
}
|
|
|
|
const resetForm = () => {
|
|
form.month = currentYearMonth()
|
|
form.amount = 0
|
|
form.comment = ''
|
|
}
|
|
|
|
const onOpenCreateDrawer = () => {
|
|
isEditing.value = false
|
|
editingItem.value = null
|
|
resetForm()
|
|
isDrawerOpen.value = true
|
|
}
|
|
|
|
const onOpenEditDrawer = (item: Bonus) => {
|
|
isEditing.value = true
|
|
editingItem.value = item
|
|
form.month = item.month.substring(0, 7)
|
|
form.amount = item.amount
|
|
form.comment = item.comment ?? ''
|
|
isDrawerOpen.value = true
|
|
}
|
|
|
|
const onSubmit = () => {
|
|
const data = {
|
|
month: `${form.month}-01`,
|
|
amount: form.amount,
|
|
comment: form.comment || undefined
|
|
}
|
|
|
|
if (isEditing.value && editingItem.value) {
|
|
emit('update', editingItem.value.id, data)
|
|
} else {
|
|
emit('create', data)
|
|
}
|
|
isDrawerOpen.value = false
|
|
}
|
|
|
|
const onDelete = () => {
|
|
if (!editingItem.value) return
|
|
const ok = window.confirm('Supprimer cette prime ?')
|
|
if (!ok) return
|
|
emit('delete', editingItem.value.id)
|
|
isDrawerOpen.value = false
|
|
}
|
|
</script>
|