From 76af245192b4ea1a630efbac2814050d9e9fcc78 Mon Sep 17 00:00:00 2001 From: Padreug Date: Tue, 16 Jun 2026 12:32:11 +0200 Subject: [PATCH] feat(events): add calendar date visual to My Tickets Replaces the My-tickets filter that lived on the removed calendar page. A calendar button opens the date-picker popup with per-day dots over the user's own events; picking a day filters the ticket list to it (a removable date chip overrides the upcoming/past toggle while active). Co-Authored-By: Claude Opus 4.8 (1M context) --- src/modules/events/views/MyTicketsPage.vue | 114 +++++++++++++++++---- 1 file changed, 96 insertions(+), 18 deletions(-) diff --git a/src/modules/events/views/MyTicketsPage.vue b/src/modules/events/views/MyTicketsPage.vue index 94e851f..de9ae09 100644 --- a/src/modules/events/views/MyTicketsPage.vue +++ b/src/modules/events/views/MyTicketsPage.vue @@ -10,10 +10,14 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { ScrollArea } from '@/components/ui/scroll-area' import { Button } from '@/components/ui/button' import { Badge } from '@/components/ui/badge' -import { format } from 'date-fns' -import { Ticket, User, CreditCard, CheckCircle, Clock, AlertCircle, ChevronLeft, ChevronRight } from 'lucide-vue-next' +import { format, startOfDay, endOfDay } from 'date-fns' +import { Ticket, User, CreditCard, CheckCircle, Clock, AlertCircle, ChevronLeft, ChevronRight, CalendarDays, X } from 'lucide-vue-next' +import EventCalendarPopup from '../components/EventCalendarPopup.vue' +import { useDateLocale } from '../composables/useDateLocale' +import type { Event } from '../types/event' const { isAuthenticated, userDisplay } = useAuth() +const { dateLocale } = useDateLocale() const { tickets, groupedTickets, @@ -50,10 +54,47 @@ function isGroupPast(eventId: string): boolean { return end < new Date() } -const visibleGroups = computed(() => - groupedTickets.value.filter(g => isGroupPast(g.eventId) === showPast.value), +// Calendar popup: visualise the days the user has events. Picking a day +// filters the ticket list to it (overriding the upcoming/past toggle); +// clearing it returns to the toggle. +const calendarOpen = ref(false) +const selectedDay = ref(null) + +// The user's events (resolved from their ticket groups) — feeds the +// calendar popup's per-day dots. +const myEvents = computed(() => { + const out: Event[] = [] + for (const g of groupedTickets.value) { + const ev = eventsStore.getEventById(g.eventId) + if (ev) out.push(ev) + } + return out +}) + +const selectedDayLabel = computed(() => + selectedDay.value + ? format(selectedDay.value, 'EEE, MMM d', { locale: dateLocale.value }) + : '', ) +function isGroupOnDay(eventId: string, day: Date): boolean { + const ev = eventsStore.getEventById(eventId) + if (!ev) return false + const end = ev.endDate ?? ev.startDate + return ev.startDate <= endOfDay(day) && end >= startOfDay(day) +} + +function onSelectDay(date: Date) { + selectedDay.value = date +} + +const visibleGroups = computed(() => { + if (selectedDay.value) { + return groupedTickets.value.filter(g => isGroupOnDay(g.eventId, selectedDay.value!)) + } + return groupedTickets.value.filter(g => isGroupPast(g.eventId) === showPast.value) +}) + // Tab counts derived from the visible (past/upcoming-filtered) groups so // the badges match what's actually shown. const visibleCounts = computed(() => { @@ -205,25 +246,52 @@ onMounted(async () => {
- -
+ +
+
+ + +
@@ -239,7 +307,7 @@ onMounted(async () => {
- {{ showPast ? 'No past tickets' : 'No upcoming tickets' }} + {{ selectedDay ? 'No tickets on this day' : (showPast ? 'No past tickets' : 'No upcoming tickets') }}
@@ -414,5 +482,15 @@ onMounted(async () => {
+ + +