200 lines
5.4 KiB
TypeScript
200 lines
5.4 KiB
TypeScript
import { ref, reactive, computed, watch, defineComponent, PropType } from 'vue';
|
|
import type { Recurrence, RecurrenceType } from '../../types';
|
|
import { DAYS_OF_WEEK, RECURRENCE_TYPE_OPTIONS } from '../../types';
|
|
|
|
export default defineComponent({
|
|
name: 'RecurrenceSelector',
|
|
|
|
props: {
|
|
modelValue: {
|
|
type: Object as PropType<Recurrence>,
|
|
default: () => ({ type: 'once' })
|
|
}
|
|
},
|
|
|
|
emits: ['update:modelValue'],
|
|
|
|
setup(props, { emit }) {
|
|
// State
|
|
const localRecurrence = reactive<Recurrence>({
|
|
type: 'once',
|
|
daysOfWeek: [],
|
|
customDates: [],
|
|
startDate: '',
|
|
endDate: '',
|
|
excludedDates: []
|
|
});
|
|
|
|
const selectedDates = ref<string[]>([]);
|
|
const excludedDates = ref<string[]>([]);
|
|
|
|
// Opzioni
|
|
const recurrenceTypes = RECURRENCE_TYPE_OPTIONS.map(opt => ({
|
|
label: opt.label,
|
|
value: opt.value,
|
|
icon: opt.icon
|
|
}));
|
|
|
|
const daysOfWeek = DAYS_OF_WEEK;
|
|
|
|
// Watch per sincronizzare con modelValue
|
|
watch(() => props.modelValue, (newVal) => {
|
|
if (newVal) {
|
|
Object.assign(localRecurrence, newVal);
|
|
|
|
if (newVal.customDates) {
|
|
selectedDates.value = newVal.customDates.map(d =>
|
|
typeof d === 'string' ? d : new Date(d).toISOString().split('T')[0]
|
|
);
|
|
}
|
|
|
|
if (newVal.excludedDates) {
|
|
excludedDates.value = newVal.excludedDates.map(d =>
|
|
typeof d === 'string' ? d : new Date(d).toISOString().split('T')[0]
|
|
);
|
|
}
|
|
}
|
|
}, { immediate: true, deep: true });
|
|
|
|
// Watch per emettere update
|
|
watch([localRecurrence, selectedDates, excludedDates], () => {
|
|
const result: Recurrence = {
|
|
type: localRecurrence.type
|
|
};
|
|
|
|
if (localRecurrence.type !== 'once') {
|
|
result.startDate = localRecurrence.startDate;
|
|
result.endDate = localRecurrence.endDate;
|
|
|
|
if (excludedDates.value.length > 0) {
|
|
result.excludedDates = excludedDates.value;
|
|
}
|
|
}
|
|
|
|
if (localRecurrence.type === 'weekly' || localRecurrence.type === 'custom_days') {
|
|
result.daysOfWeek = localRecurrence.daysOfWeek;
|
|
}
|
|
|
|
if (localRecurrence.type === 'custom_dates') {
|
|
result.customDates = selectedDates.value;
|
|
}
|
|
|
|
emit('update:modelValue', result);
|
|
}, { deep: true });
|
|
|
|
// Methods
|
|
const isDaySelected = (day: number): boolean => {
|
|
return localRecurrence.daysOfWeek?.includes(day) || false;
|
|
};
|
|
|
|
const toggleDay = (day: number) => {
|
|
if (!localRecurrence.daysOfWeek) {
|
|
localRecurrence.daysOfWeek = [];
|
|
}
|
|
|
|
const index = localRecurrence.daysOfWeek.indexOf(day);
|
|
if (index === -1) {
|
|
localRecurrence.daysOfWeek.push(day);
|
|
} else {
|
|
localRecurrence.daysOfWeek.splice(index, 1);
|
|
}
|
|
|
|
// Ordina i giorni
|
|
localRecurrence.daysOfWeek.sort((a, b) => a - b);
|
|
};
|
|
|
|
const removeDate = (index: number) => {
|
|
selectedDates.value.splice(index, 1);
|
|
};
|
|
|
|
const removeExcludedDate = (index: number) => {
|
|
excludedDates.value.splice(index, 1);
|
|
};
|
|
|
|
const formatDate = (dateStr: string): string => {
|
|
const date = new Date(dateStr);
|
|
return date.toLocaleDateString('it-IT', {
|
|
weekday: 'short',
|
|
day: 'numeric',
|
|
month: 'short'
|
|
});
|
|
};
|
|
|
|
// Date options (solo date future)
|
|
const dateOptions = (date: string): boolean => {
|
|
const today = new Date();
|
|
today.setHours(0, 0, 0, 0);
|
|
const checkDate = new Date(date);
|
|
return checkDate >= today;
|
|
};
|
|
|
|
const exclusionDateOptions = (date: string): boolean => {
|
|
if (!localRecurrence.startDate || !localRecurrence.endDate) {
|
|
return dateOptions(date);
|
|
}
|
|
const checkDate = new Date(date);
|
|
const start = new Date(localRecurrence.startDate);
|
|
const end = new Date(localRecurrence.endDate);
|
|
return checkDate >= start && checkDate <= end;
|
|
};
|
|
|
|
// Riepilogo testuale
|
|
const summaryText = computed(() => {
|
|
switch (localRecurrence.type) {
|
|
case 'once':
|
|
return 'Viaggio singolo, senza ripetizioni';
|
|
|
|
case 'weekly':
|
|
if (!localRecurrence.daysOfWeek?.length) {
|
|
return 'Seleziona i giorni della settimana';
|
|
}
|
|
const weeklyDays = localRecurrence.daysOfWeek
|
|
.map(d => daysOfWeek.find(day => day.value === d)?.label)
|
|
.join(', ');
|
|
return `Ogni settimana: ${weeklyDays}`;
|
|
|
|
case 'custom_days':
|
|
if (!localRecurrence.daysOfWeek?.length) {
|
|
return 'Seleziona i giorni della settimana';
|
|
}
|
|
const customDays = localRecurrence.daysOfWeek
|
|
.map(d => daysOfWeek.find(day => day.value === d)?.label)
|
|
.join(', ');
|
|
return `Giorni selezionati: ${customDays}`;
|
|
|
|
case 'custom_dates':
|
|
if (!selectedDates.value.length) {
|
|
return 'Seleziona le date dal calendario';
|
|
}
|
|
return `${selectedDates.value.length} date selezionate`;
|
|
|
|
default:
|
|
return '';
|
|
}
|
|
});
|
|
|
|
return {
|
|
// State
|
|
localRecurrence,
|
|
selectedDates,
|
|
excludedDates,
|
|
|
|
// Options
|
|
recurrenceTypes,
|
|
daysOfWeek,
|
|
|
|
// Computed
|
|
summaryText,
|
|
|
|
// Methods
|
|
isDaySelected,
|
|
toggleDay,
|
|
removeDate,
|
|
removeExcludedDate,
|
|
formatDate,
|
|
dateOptions,
|
|
exclusionDateOptions
|
|
};
|
|
}
|
|
});
|