feat(events): add reusable calendar date-picker popup
Add a pickerMode to EventCalendarView (month grid only, emits selectDate on every day tap, no selected-day events panel) and a new EventCalendarPopup dialog wrapping it. Picking a day emits the date and closes. Groundwork for replacing the standalone calendar page with an on-feed date-picker popup and a My-Tickets event-date visual. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
014964b6c2
commit
11db592041
2 changed files with 62 additions and 2 deletions
49
src/modules/events/components/EventCalendarPopup.vue
Normal file
49
src/modules/events/components/EventCalendarPopup.vue
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogDescription,
|
||||||
|
} from '@/components/ui/dialog'
|
||||||
|
import EventCalendarView from './EventCalendarView.vue'
|
||||||
|
import type { Event } from '../types/event'
|
||||||
|
|
||||||
|
// A date-picker popup: the month grid (with per-day event dots) in a
|
||||||
|
// dialog. Picking a day emits selectDate and closes. Reused by the feed
|
||||||
|
// (filter to a day) and My Tickets (visualise the user's event dates).
|
||||||
|
const props = defineProps<{
|
||||||
|
open: boolean
|
||||||
|
events: Event[]
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:open': [value: boolean]
|
||||||
|
selectDate: [date: Date]
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const isOpen = computed({
|
||||||
|
get: () => props.open,
|
||||||
|
set: (v) => emit('update:open', v),
|
||||||
|
})
|
||||||
|
|
||||||
|
function onSelectDate(date: Date) {
|
||||||
|
emit('selectDate', date)
|
||||||
|
isOpen.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Dialog v-model:open="isOpen">
|
||||||
|
<DialogContent class="max-w-sm">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>{{ title }}</DialogTitle>
|
||||||
|
<DialogDescription>{{ description }}</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<EventCalendarView :events="events" picker-mode @select-date="onSelectDate" />
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
@ -12,6 +12,10 @@ import type { Event } from '../types/event'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
events: Event[]
|
events: Event[]
|
||||||
|
/** When true, render only the month grid for date-picking — no
|
||||||
|
* selected-day events panel — and emit selectDate on every day tap
|
||||||
|
* (used inside the calendar popup). */
|
||||||
|
pickerMode?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|
@ -77,6 +81,12 @@ const selectedDayEvents = computed(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
function selectDay(date: Date) {
|
function selectDay(date: Date) {
|
||||||
|
// Picker mode: every tap selects + emits (parent closes the popup).
|
||||||
|
if (props.pickerMode) {
|
||||||
|
selectedDay.value = date
|
||||||
|
emit('selectDate', date)
|
||||||
|
return
|
||||||
|
}
|
||||||
if (selectedDay.value && isSameDay(selectedDay.value, date)) {
|
if (selectedDay.value && isSameDay(selectedDay.value, date)) {
|
||||||
selectedDay.value = null
|
selectedDay.value = null
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -147,8 +157,9 @@ function nextMonth() {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Selected day events -->
|
<!-- Selected day events (hidden in picker mode — the popup just
|
||||||
<div v-if="selectedDay" class="border-t pt-4 space-y-2">
|
picks a day and closes). -->
|
||||||
|
<div v-if="selectedDay && !pickerMode" class="border-t pt-4 space-y-2">
|
||||||
<h3 class="text-sm font-medium text-muted-foreground">
|
<h3 class="text-sm font-medium text-muted-foreground">
|
||||||
{{ format(selectedDay, 'EEEE, MMMM d', { locale: dateLocale }) }}
|
{{ format(selectedDay, 'EEEE, MMMM d', { locale: dateLocale }) }}
|
||||||
<span v-if="selectedDayEvents.length > 0" class="ml-1">
|
<span v-if="selectedDayEvents.length > 0" class="ml-1">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue