Major new version #2
@ -31,6 +31,9 @@ const eventSaved = ref(false)
|
|||||||
const titleInput = ref(null)
|
const titleInput = ref(null)
|
||||||
const modalRef = ref(null)
|
const modalRef = ref(null)
|
||||||
|
|
||||||
|
// UI display mode - stays fixed unless user manually changes it
|
||||||
|
const uiDisplayFrequency = ref('weeks') // 'weeks' | 'months' | 'years'
|
||||||
|
|
||||||
// Drag functionality
|
// Drag functionality
|
||||||
const isDragging = ref(false)
|
const isDragging = ref(false)
|
||||||
const dragOffset = ref({ x: 0, y: 0 })
|
const dragOffset = ref({ x: 0, y: 0 })
|
||||||
@ -107,11 +110,66 @@ const fallbackWeekdays = computed(() => {
|
|||||||
return fallback
|
return fallback
|
||||||
})
|
})
|
||||||
|
|
||||||
// Repeat mapping uses 'weeks' | 'months' | 'none' directly
|
// Computed property to handle UI frequency (weeks/months/years) vs store frequency (weeks/months)
|
||||||
|
const displayFrequency = computed({
|
||||||
|
get() {
|
||||||
|
return uiDisplayFrequency.value
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
const oldFreq = uiDisplayFrequency.value
|
||||||
|
const currentDisplayValue = displayInterval.value // Get the current display value before changing
|
||||||
|
uiDisplayFrequency.value = val
|
||||||
|
|
||||||
|
if (oldFreq === val) return // No change
|
||||||
|
|
||||||
|
if (oldFreq === 'years' && val === 'months') {
|
||||||
|
// Converting from years to months: keep the display value the same, but now it represents months
|
||||||
|
recurrenceFrequency.value = 'months'
|
||||||
|
recurrenceInterval.value = currentDisplayValue // Keep the same number, now as months
|
||||||
|
} else if (oldFreq === 'months' && val === 'years') {
|
||||||
|
// Converting from months to years: keep the display value the same, but now it represents years
|
||||||
|
recurrenceFrequency.value = 'months'
|
||||||
|
recurrenceInterval.value = currentDisplayValue * 12 // Convert to months for storage
|
||||||
|
} else if (val === 'years') {
|
||||||
|
// Converting from weeks to years
|
||||||
|
recurrenceFrequency.value = 'months'
|
||||||
|
recurrenceInterval.value = 12 // Default to 1 year
|
||||||
|
} else if (val === 'months') {
|
||||||
|
// Converting to months from weeks
|
||||||
|
recurrenceFrequency.value = 'months'
|
||||||
|
if (oldFreq === 'weeks') {
|
||||||
|
recurrenceInterval.value = 1 // Default to 1 month
|
||||||
|
}
|
||||||
|
} else if (val === 'weeks') {
|
||||||
|
// Converting to weeks
|
||||||
|
recurrenceFrequency.value = 'weeks'
|
||||||
|
recurrenceInterval.value = 1 // Default to 1 week
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Computed property for display interval (handles years conversion)
|
||||||
|
const displayInterval = computed({
|
||||||
|
get() {
|
||||||
|
if (uiDisplayFrequency.value === 'years') {
|
||||||
|
return recurrenceInterval.value / 12
|
||||||
|
}
|
||||||
|
return recurrenceInterval.value
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
if (uiDisplayFrequency.value === 'years') {
|
||||||
|
recurrenceInterval.value = val * 12
|
||||||
|
} else {
|
||||||
|
recurrenceInterval.value = val
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Repeat mapping uses 'weeks' | 'months' | 'none' directly (store only supports weeks/months)
|
||||||
const repeat = computed({
|
const repeat = computed({
|
||||||
get() {
|
get() {
|
||||||
if (!recurrenceEnabled.value) return 'none'
|
if (!recurrenceEnabled.value) return 'none'
|
||||||
return recurrenceFrequency.value // 'weeks' | 'months'
|
return recurrenceFrequency.value // Always 'weeks' | 'months' for store
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
if (val === 'none') {
|
if (val === 'none') {
|
||||||
@ -119,8 +177,16 @@ const repeat = computed({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
recurrenceEnabled.value = true
|
recurrenceEnabled.value = true
|
||||||
if (val === 'weeks') recurrenceFrequency.value = 'weeks'
|
if (val === 'weeks') {
|
||||||
else if (val === 'months') recurrenceFrequency.value = 'months'
|
recurrenceFrequency.value = 'weeks'
|
||||||
|
uiDisplayFrequency.value = 'weeks'
|
||||||
|
if (recurrenceInterval.value >= 12) {
|
||||||
|
recurrenceInterval.value = 1 // Reset to sensible weekly default
|
||||||
|
}
|
||||||
|
} else if (val === 'months') {
|
||||||
|
recurrenceFrequency.value = 'months'
|
||||||
|
// Don't change UI display frequency here - let it be determined by context
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -187,6 +253,7 @@ function openCreateDialog(selectionData = null) {
|
|||||||
recurrenceEnabled.value = false
|
recurrenceEnabled.value = false
|
||||||
recurrenceInterval.value = 1
|
recurrenceInterval.value = 1
|
||||||
recurrenceFrequency.value = 'weeks'
|
recurrenceFrequency.value = 'weeks'
|
||||||
|
uiDisplayFrequency.value = 'weeks' // Set initial UI display mode
|
||||||
recurrenceWeekdays.value = [false, false, false, false, false, false, false]
|
recurrenceWeekdays.value = [false, false, false, false, false, false, false]
|
||||||
recurrenceOccurrences.value = 0
|
recurrenceOccurrences.value = 0
|
||||||
colorId.value = calendarStore.selectEventColorId(start, end)
|
colorId.value = calendarStore.selectEventColorId(start, end)
|
||||||
@ -294,6 +361,21 @@ function openEditDialog(payload) {
|
|||||||
loadWeekdayPatternFromStore(event.repeatWeekdays)
|
loadWeekdayPatternFromStore(event.repeatWeekdays)
|
||||||
repeat.value = event.repeat // triggers setter mapping into recurrence state
|
repeat.value = event.repeat // triggers setter mapping into recurrence state
|
||||||
if (event.repeatInterval) recurrenceInterval.value = event.repeatInterval
|
if (event.repeatInterval) recurrenceInterval.value = event.repeatInterval
|
||||||
|
|
||||||
|
// Set UI display frequency based on loaded data
|
||||||
|
if (event.repeat === 'weeks') {
|
||||||
|
uiDisplayFrequency.value = 'weeks'
|
||||||
|
} else if (event.repeat === 'months') {
|
||||||
|
// If it's a yearly interval (multiple of 12), show as years
|
||||||
|
if (event.repeatInterval && event.repeatInterval % 12 === 0 && event.repeatInterval >= 12) {
|
||||||
|
uiDisplayFrequency.value = 'years'
|
||||||
|
} else {
|
||||||
|
uiDisplayFrequency.value = 'months'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uiDisplayFrequency.value = 'weeks' // fallback
|
||||||
|
}
|
||||||
|
|
||||||
// Map repeatCount
|
// Map repeatCount
|
||||||
const rc = event.repeatCount ?? 'unlimited'
|
const rc = event.repeatCount ?? 'unlimited'
|
||||||
recurrenceOccurrences.value = rc === 'unlimited' ? 0 : parseInt(rc, 10) || 0
|
recurrenceOccurrences.value = rc === 'unlimited' ? 0 : parseInt(rc, 10) || 0
|
||||||
@ -510,7 +592,7 @@ const finalOccurrenceDate = computed(() => {
|
|||||||
const base = editingEventId.value ? calendarStore.getEventById(editingEventId.value) : null
|
const base = editingEventId.value ? calendarStore.getEventById(editingEventId.value) : null
|
||||||
if (!base) return null
|
if (!base) return null
|
||||||
const start = new Date(base.startDate + 'T00:00:00')
|
const start = new Date(base.startDate + 'T00:00:00')
|
||||||
if (recurrenceFrequency.value === 'weeks') {
|
if (uiDisplayFrequency.value === 'weeks') {
|
||||||
// iterate days until we count 'count-1' additional occurrences (first is base if selected weekday)
|
// iterate days until we count 'count-1' additional occurrences (first is base if selected weekday)
|
||||||
const pattern = buildStoreWeekdayPattern() // Sun..Sat
|
const pattern = buildStoreWeekdayPattern() // Sun..Sat
|
||||||
// Build Monday-first pattern again for selection clarity
|
// Build Monday-first pattern again for selection clarity
|
||||||
@ -530,11 +612,16 @@ const finalOccurrenceDate = computed(() => {
|
|||||||
}
|
}
|
||||||
if (occs === count) return cursor
|
if (occs === count) return cursor
|
||||||
return null
|
return null
|
||||||
} else if (recurrenceFrequency.value === 'months') {
|
} else if (uiDisplayFrequency.value === 'months') {
|
||||||
const monthsToAdd = recurrenceInterval.value * (count - 1)
|
const monthsToAdd = displayInterval.value * (count - 1)
|
||||||
const d = new Date(start)
|
const d = new Date(start)
|
||||||
d.setMonth(d.getMonth() + monthsToAdd)
|
d.setMonth(d.getMonth() + monthsToAdd)
|
||||||
return d
|
return d
|
||||||
|
} else if (uiDisplayFrequency.value === 'years') {
|
||||||
|
const yearsToAdd = displayInterval.value * (count - 1)
|
||||||
|
const d = new Date(start)
|
||||||
|
d.setFullYear(d.getFullYear() + yearsToAdd)
|
||||||
|
return d
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -560,15 +647,18 @@ const formattedFinalOccurrence = computed(() => {
|
|||||||
|
|
||||||
const recurrenceSummary = computed(() => {
|
const recurrenceSummary = computed(() => {
|
||||||
if (!recurrenceEnabled.value) return 'Does not recur'
|
if (!recurrenceEnabled.value) return 'Does not recur'
|
||||||
if (recurrenceFrequency.value === 'weeks') {
|
if (uiDisplayFrequency.value === 'weeks') {
|
||||||
return recurrenceInterval.value === 1 ? 'Weekly' : `Every ${recurrenceInterval.value} weeks`
|
return displayInterval.value === 1 ? 'Weekly' : `Every ${displayInterval.value} weeks`
|
||||||
|
} else if (uiDisplayFrequency.value === 'years') {
|
||||||
|
return displayInterval.value === 1 ? 'Annually' : `Every ${displayInterval.value} years`
|
||||||
}
|
}
|
||||||
// months frequency
|
// For months frequency - always check the underlying recurrenceInterval for yearly patterns
|
||||||
if (recurrenceInterval.value % 12 === 0) {
|
if (recurrenceFrequency.value === 'months' && recurrenceInterval.value % 12 === 0) {
|
||||||
const years = recurrenceInterval.value / 12
|
const years = recurrenceInterval.value / 12
|
||||||
return years === 1 ? 'Annually' : `Every ${years} years`
|
return years === 1 ? 'Annually' : `Every ${years} years`
|
||||||
}
|
}
|
||||||
return recurrenceInterval.value === 1 ? 'Monthly' : `Every ${recurrenceInterval.value} months`
|
// Regular monthly display
|
||||||
|
return displayInterval.value === 1 ? 'Monthly' : `Every ${displayInterval.value} months`
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -610,15 +700,16 @@ const recurrenceSummary = computed(() => {
|
|||||||
<div v-if="recurrenceEnabled" class="recurrence-form">
|
<div v-if="recurrenceEnabled" class="recurrence-form">
|
||||||
<div class="line compact">
|
<div class="line compact">
|
||||||
<Numeric
|
<Numeric
|
||||||
v-model="recurrenceInterval"
|
v-model="displayInterval"
|
||||||
:prefix-values="[{ value: 1, display: 'Every' }]"
|
:prefix-values="[{ value: 1, display: 'Every' }]"
|
||||||
:min="2"
|
:min="2"
|
||||||
number-prefix="Every "
|
number-prefix="Every "
|
||||||
aria-label="Interval"
|
aria-label="Interval"
|
||||||
/>
|
/>
|
||||||
<select v-model="recurrenceFrequency" class="freq-select">
|
<select v-model="displayFrequency" class="freq-select">
|
||||||
<option value="weeks">{{ recurrenceInterval === 1 ? 'week' : 'weeks' }}</option>
|
<option value="weeks">{{ displayInterval === 1 ? 'week' : 'weeks' }}</option>
|
||||||
<option value="months">{{ recurrenceInterval === 1 ? 'month' : 'months' }}</option>
|
<option value="months">{{ displayInterval === 1 ? 'month' : 'months' }}</option>
|
||||||
|
<option value="years">{{ displayInterval === 1 ? 'year' : 'years' }}</option>
|
||||||
</select>
|
</select>
|
||||||
<Numeric
|
<Numeric
|
||||||
class="occ-stepper"
|
class="occ-stepper"
|
||||||
@ -630,7 +721,7 @@ const recurrenceSummary = computed(() => {
|
|||||||
extra-class="occ"
|
extra-class="occ"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="recurrenceFrequency === 'weeks'" @click.stop>
|
<div v-if="uiDisplayFrequency === 'weeks'" @click.stop>
|
||||||
<WeekdaySelector
|
<WeekdaySelector
|
||||||
v-model="recurrenceWeekdays"
|
v-model="recurrenceWeekdays"
|
||||||
:fallback="fallbackWeekdays"
|
:fallback="fallbackWeekdays"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user