- Parte 3 : Viaggi
- Chat
This commit is contained in:
199
src/modules/viaggi/components/ride/RecurrenceSelector.ts
Normal file
199
src/modules/viaggi/components/ride/RecurrenceSelector.ts
Normal file
@@ -0,0 +1,199 @@
|
||||
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
|
||||
};
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user