Event search (Ctrl+F), locale/RTL handling, weekday selector workday/weekend, refactored event handling, Firefox compatibility #3
27
src/App.vue
27
src/App.vue
@ -1,12 +1,10 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
|
||||
import CalendarView from './components/CalendarView.vue'
|
||||
import EventDialog from './components/EventDialog.vue'
|
||||
import { useCalendarStore } from './stores/CalendarStore'
|
||||
import { lang } from './utils/locale'
|
||||
import { formatTodayString } from './utils/date'
|
||||
|
||||
const eventDialog = ref(null)
|
||||
const calendarStore = useCalendarStore()
|
||||
|
||||
// Initialize holidays when app starts
|
||||
@ -47,24 +45,6 @@ onBeforeUnmount(() => {
|
||||
document.removeEventListener('keydown', handleGlobalKey)
|
||||
})
|
||||
|
||||
const handleCreateEvent = (eventData) => {
|
||||
if (eventDialog.value) {
|
||||
const selectionData = {
|
||||
startDate: eventData.startDate,
|
||||
dayCount: eventData.dayCount,
|
||||
}
|
||||
setTimeout(() => eventDialog.value.openCreateDialog(selectionData), 50)
|
||||
}
|
||||
}
|
||||
|
||||
const handleEditEvent = (eventClickPayload) => {
|
||||
if (eventDialog.value) {
|
||||
eventDialog.value.openEditDialog(eventClickPayload)
|
||||
}
|
||||
}
|
||||
|
||||
const handleClearSelection = () => {}
|
||||
|
||||
// Watch today's date to update document title
|
||||
watch(
|
||||
() => calendarStore.now,
|
||||
@ -76,12 +56,7 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CalendarView @create-event="handleCreateEvent" @edit-event="handleEditEvent" />
|
||||
<EventDialog
|
||||
ref="eventDialog"
|
||||
:selection="{ startDate: null, dayCount: 0 }"
|
||||
@clear-selection="handleClearSelection"
|
||||
/>
|
||||
<CalendarView />
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
@ -14,9 +14,20 @@ import { toLocalString, fromLocalString, DEFAULT_TZ } from '@/utils/date'
|
||||
import { addDays, differenceInWeeks } from 'date-fns'
|
||||
import { createVirtualWeekManager } from '@/plugins/virtualWeeks'
|
||||
import { rtl } from '@/utils/locale'
|
||||
import EventDialog from '@/components/EventDialog.vue'
|
||||
|
||||
const calendarStore = useCalendarStore()
|
||||
const emit = defineEmits(['create-event', 'edit-event'])
|
||||
defineEmits([]) // previously emitted create/edit events externally
|
||||
import { shallowRef } from 'vue'
|
||||
const eventDialogRef = shallowRef(null)
|
||||
function openCreateEventDialog(eventData) {
|
||||
if (!eventDialogRef.value) return
|
||||
const selectionData = { startDate: eventData.startDate, dayCount: eventData.dayCount }
|
||||
setTimeout(() => eventDialogRef.value?.openCreateDialog(selectionData), 30)
|
||||
}
|
||||
function openEditEventDialog(eventClickPayload) {
|
||||
eventDialogRef.value?.openEditDialog(eventClickPayload)
|
||||
}
|
||||
const viewport = ref(null)
|
||||
const viewportHeight = ref(600)
|
||||
const rowHeight = ref(64)
|
||||
@ -207,7 +218,7 @@ function finalizeDragAndCreate() {
|
||||
const eventData = createEventFromSelection()
|
||||
if (eventData) {
|
||||
clearSelection()
|
||||
emit('create-event', eventData)
|
||||
openCreateEventDialog(eventData)
|
||||
}
|
||||
removeGlobalTouchListeners()
|
||||
}
|
||||
@ -373,7 +384,7 @@ const handleDayMouseUp = (d) => {
|
||||
const ev = createEventFromSelection()
|
||||
if (ev) {
|
||||
clearSelection()
|
||||
emit('create-event', ev)
|
||||
openCreateEventDialog(ev)
|
||||
}
|
||||
}
|
||||
const handleDayTouchStart = (d) => {
|
||||
@ -383,7 +394,7 @@ const handleDayTouchStart = (d) => {
|
||||
}
|
||||
|
||||
const handleEventClick = (payload) => {
|
||||
emit('edit-event', payload)
|
||||
openEditEventDialog(payload)
|
||||
}
|
||||
|
||||
// Heuristic: rotate month label (180deg) only for predominantly Latin text.
|
||||
@ -489,6 +500,7 @@ window.addEventListener('resize', () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<EventDialog ref="eventDialogRef" :selection="{ startDate: null, dayCount: 0 }" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -594,8 +594,10 @@ const recurrenceSummary = computed(() => {
|
||||
<template>
|
||||
<BaseDialog v-model="showDialog" :anchor-el="anchorElement" @submit="saveEvent">
|
||||
<template #title>
|
||||
{{ dialogMode === 'create' ? 'Create Event' : 'Edit Event'
|
||||
}}<template v-if="headerDateShort"> · {{ headerDateShort }}</template>
|
||||
<div class="dialog-title-row">
|
||||
{{ dialogMode === 'create' ? 'Create Event' : 'Edit Event' }}
|
||||
<span> · {{ headerDateShort }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<label class="ec-field">
|
||||
<input type="text" v-model="title" autocomplete="off" ref="titleInput" />
|
||||
@ -620,9 +622,7 @@ const recurrenceSummary = computed(() => {
|
||||
</label>
|
||||
<span class="recurrence-summary" v-if="recurrenceEnabled">
|
||||
{{ recurrenceSummary }}
|
||||
<template v-if="recurrenceOccurrences > 0">
|
||||
until {{ formattedFinalOccurrence }}</template
|
||||
>
|
||||
<span v-if="recurrenceOccurrences > 0"> until {{ formattedFinalOccurrence }} </span>
|
||||
</span>
|
||||
<span class="recurrence-summary muted" v-else>Does not recur</span>
|
||||
</div>
|
||||
@ -668,7 +668,7 @@ const recurrenceSummary = computed(() => {
|
||||
<template v-if="showDeleteVariants">
|
||||
<div class="ec-delete-group">
|
||||
<button type="button" class="ec-btn delete-btn" @click="deleteEventOne">
|
||||
Delete {{ formattedOccurrenceShort }}
|
||||
Delete <span>{{ formattedOccurrenceShort }}</span>
|
||||
</button>
|
||||
<button
|
||||
v-if="!isLastOccurrence"
|
||||
@ -676,7 +676,7 @@ const recurrenceSummary = computed(() => {
|
||||
class="ec-btn delete-btn"
|
||||
@click="deleteEventFrom"
|
||||
>
|
||||
Rest
|
||||
+ Rest
|
||||
</button>
|
||||
<button type="button" class="ec-btn delete-btn" @click="deleteEventAll">All</button>
|
||||
</div>
|
||||
@ -1003,4 +1003,7 @@ const recurrenceSummary = computed(() => {
|
||||
.ec-occurrences-field .ec-field input[type='number'] {
|
||||
max-width: 6rem;
|
||||
}
|
||||
span {
|
||||
unicode-bidi: isolate;
|
||||
}
|
||||
</style>
|
||||
|
@ -159,7 +159,13 @@ defineExpose({ open })
|
||||
v-model="show"
|
||||
title="Settings"
|
||||
class="settings-modal"
|
||||
:style="{ top: '4.5rem', insetInlineEnd: '2rem', bottom: 'auto', insetInlineStart: 'auto', transform: 'none' }"
|
||||
:style="{
|
||||
top: '4.5rem',
|
||||
insetInlineEnd: '2rem',
|
||||
bottom: 'auto',
|
||||
insetInlineStart: 'auto',
|
||||
transform: 'none',
|
||||
}"
|
||||
>
|
||||
<div class="setting-group">
|
||||
<label class="ec-field">
|
||||
|
Loading…
x
Reference in New Issue
Block a user