2025-09-10 12:10:37 +03:00

123 lines
4.4 KiB
Vue

<template>
<div class="flex max-w-md min-w-[320px] flex-1 flex-col gap-6">
<p class="text-center text-lg text-[var(--midnight-blue)]">Sélectionnez une date disponible</p>
<div class="flex items-center justify-between">
<button @click="handlePreviousMonth" class="rounded-full p-2 text-[var(--midnight-blue)] hover:bg-[var(--linen)]">
<svg fill="currentColor" height="24px" viewBox="0 0 256 256" width="24px" xmlns="http://www.w3.org/2000/svg">
<path d="M165.66,202.34a8,8,0,0,1-11.32,11.32l-80-80a8,8,0,0,1,0-11.32l80-80a8,8,0,0,1,11.32,11.32L91.31,128Z"></path>
</svg>
</button>
<h3 class="text-center text-2xl font-bold text-[var(--midnight-blue)]">{{ monthName }} {{ currentYear }}</h3>
<button @click="handleNextMonth" class="rounded-full p-2 text-[var(--midnight-blue)] hover:bg-[var(--linen)]">
<svg fill="currentColor" height="24px" viewBox="0 0 256 256" width="24px" xmlns="http://www.w3.org/2000/svg">
<path
d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"
></path>
</svg>
</button>
</div>
<div class="grid grid-cols-7 gap-1">
<p v-for="day in dayNames" :key="day" class="p-3 text-center text-sm font-bold text-[var(--spiritual-earth)]">{{ day }}</p>
<div v-for="blank in firstDayOfMonth" :key="'blank-' + blank" class="col-start-auto"></div>
<button
v-for="day in daysInMonth"
:key="day"
@click="selectDay(day)"
:class="{
'rounded-full p-3 text-base font-medium hover:bg-[var(--linen)]': true,
'bg-[var(--spiritual-earth)] text-[var(--pure-white)] ring-2 ring-[var(--subtle-gold)] ring-offset-2 ring-offset-[var(--light-ivory)]':
isSelected(day),
'text-gray-400': isDisabled(day),
}"
:disabled="isDisabled(day)"
>
{{ day }}
</button>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, defineEmits, defineProps, ref, watch } from 'vue';
const props = defineProps({
selectedDate: {
type: Date,
default: () => new Date(),
},
});
const emit = defineEmits(['update:selectedDate']);
const today = new Date();
const currentMonth = ref(props.selectedDate.getMonth());
const currentYear = ref(props.selectedDate.getFullYear());
const dayNames = ['D', 'L', 'M', 'M', 'J', 'V', 'S'];
const monthNames = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'];
const monthName = computed(() => {
return monthNames[currentMonth.value];
});
const firstDayOfMonth = computed(() => {
const date = new Date(currentYear.value, currentMonth.value, 1);
return date.getDay(); // 0 for Sunday, 1 for Monday...
});
const daysInMonth = computed(() => {
return new Date(currentYear.value, currentMonth.value + 1, 0).getDate();
});
const handlePreviousMonth = () => {
if (currentMonth.value === 0) {
currentMonth.value = 11;
currentYear.value--;
} else {
currentMonth.value--;
}
};
const handleNextMonth = () => {
if (currentMonth.value === 11) {
currentMonth.value = 0;
currentYear.value++;
} else {
currentMonth.value++;
}
};
const selectDay = (day: number) => {
const newDate = new Date(currentYear.value, currentMonth.value, day);
emit('update:selectedDate', newDate);
};
const isSelected = (day: number) => {
return (
day === props.selectedDate.getDate() &&
currentMonth.value === props.selectedDate.getMonth() &&
currentYear.value === props.selectedDate.getFullYear()
);
};
const isDisabled = (day: number) => {
const date = new Date(currentYear.value, currentMonth.value, day);
const todayAtMidnight = new Date(today.getFullYear(), today.getMonth(), today.getDate());
return date.getTime() < todayAtMidnight.getTime();
};
// Watch for changes in the prop to update internal state
watch(
() => props.selectedDate,
(newDate) => {
currentMonth.value = newDate.getMonth();
currentYear.value = newDate.getFullYear();
},
{ deep: true },
);
</script>