feat(events): calendar date-picker popup, remove calendar page, My Tickets filtering #110
1 changed files with 52 additions and 7 deletions
feat(events): filter the feed by day via the calendar popup
The calendar button now opens the date-picker popup instead of navigating to a separate page. Picking a day filters the feed to that day (button highlights while active) and shows a removable date chip whose ✕ clears ONLY the date selection — distinct from category clearing, which keeps its own clear in the filter dropdown. Dots in the popup come from the full (unfiltered) event set. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
commit
5753e34499
|
|
@ -8,7 +8,8 @@ import {
|
||||||
CollapsibleContent,
|
CollapsibleContent,
|
||||||
CollapsibleTrigger,
|
CollapsibleTrigger,
|
||||||
} from '@/components/ui/collapsible'
|
} from '@/components/ui/collapsible'
|
||||||
import { SlidersHorizontal, CalendarDays, Plus } from 'lucide-vue-next'
|
import { SlidersHorizontal, CalendarDays, Plus, X } from 'lucide-vue-next'
|
||||||
|
import { format } from 'date-fns'
|
||||||
import brandAppLogoUrl from '@brand-app-logo?url'
|
import brandAppLogoUrl from '@brand-app-logo?url'
|
||||||
import brandAppBannerUrl from '@brand-app-banner?url'
|
import brandAppBannerUrl from '@brand-app-banner?url'
|
||||||
// Brand name flows through VITE_APP_NAME (set in vite.events.config.ts
|
// Brand name flows through VITE_APP_NAME (set in vite.events.config.ts
|
||||||
|
|
@ -26,23 +27,30 @@ import { useEventsStore } from '../stores/events'
|
||||||
import EventSearchOverlay from '../components/EventSearchOverlay.vue'
|
import EventSearchOverlay from '../components/EventSearchOverlay.vue'
|
||||||
import TemporalFilterBar from '../components/TemporalFilterBar.vue'
|
import TemporalFilterBar from '../components/TemporalFilterBar.vue'
|
||||||
import CategoryFilterBar from '../components/CategoryFilterBar.vue'
|
import CategoryFilterBar from '../components/CategoryFilterBar.vue'
|
||||||
|
import EventCalendarPopup from '../components/EventCalendarPopup.vue'
|
||||||
import EventList from '../components/EventList.vue'
|
import EventList from '../components/EventList.vue'
|
||||||
|
import { useDateLocale } from '../composables/useDateLocale'
|
||||||
import type { Event } from '../types/event'
|
import type { Event } from '../types/event'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const { dateLocale } = useDateLocale()
|
||||||
const eventsStore = useEventsStore()
|
const eventsStore = useEventsStore()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
events,
|
events,
|
||||||
|
allEvents,
|
||||||
isLoading,
|
isLoading,
|
||||||
error,
|
error,
|
||||||
temporal,
|
temporal,
|
||||||
selectedCategories,
|
selectedCategories,
|
||||||
|
selectedDate,
|
||||||
hasActiveFilters,
|
hasActiveFilters,
|
||||||
showPast,
|
showPast,
|
||||||
onlyHosting,
|
onlyHosting,
|
||||||
setTemporal,
|
setTemporal,
|
||||||
|
selectDate,
|
||||||
|
clearSelectedDate,
|
||||||
toggleCategory,
|
toggleCategory,
|
||||||
clearCategories,
|
clearCategories,
|
||||||
togglePast,
|
togglePast,
|
||||||
|
|
@ -51,6 +59,14 @@ const {
|
||||||
} = useEvents()
|
} = useEvents()
|
||||||
|
|
||||||
const filtersOpen = ref(false)
|
const filtersOpen = ref(false)
|
||||||
|
const calendarOpen = ref(false)
|
||||||
|
|
||||||
|
// Human label for the active day filter, shown as a removable chip.
|
||||||
|
const selectedDateLabel = computed(() =>
|
||||||
|
selectedDate.value
|
||||||
|
? format(selectedDate.value, 'EEE, MMM d', { locale: dateLocale.value })
|
||||||
|
: '',
|
||||||
|
)
|
||||||
|
|
||||||
// Badge count on the Filters trigger so the user can see at a glance
|
// Badge count on the Filters trigger so the user can see at a glance
|
||||||
// that hidden toggles (categories) are currently active even when the
|
// that hidden toggles (categories) are currently active even when the
|
||||||
|
|
@ -77,8 +93,9 @@ function openCreate() {
|
||||||
eventsStore.showCreateDialog = true
|
eventsStore.showCreateDialog = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function openCalendar() {
|
function onSelectDate(date: Date) {
|
||||||
router.push('/events/calendar')
|
// The popup closes itself; just apply the day filter.
|
||||||
|
selectDate(date)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -161,15 +178,16 @@ function openCalendar() {
|
||||||
@toggle-past="togglePast"
|
@toggle-past="togglePast"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- Calendar shortcut — sits at the end of the filter row next to
|
<!-- Calendar shortcut — opens the date-picker popup to filter the
|
||||||
the temporal pills (the week-day strip was removed in favour
|
feed to a single day. Highlighted while a day filter is
|
||||||
of the calendar for picking specific dates). -->
|
active. -->
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
class="h-8 w-8 shrink-0"
|
class="h-8 w-8 shrink-0"
|
||||||
|
:class="{ 'bg-accent text-accent-foreground': selectedDate }"
|
||||||
:aria-label="t('events.nav.calendar')"
|
:aria-label="t('events.nav.calendar')"
|
||||||
@click="openCalendar"
|
@click="calendarOpen = true"
|
||||||
>
|
>
|
||||||
<CalendarDays class="h-4 w-4" />
|
<CalendarDays class="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -183,6 +201,23 @@ function openCalendar() {
|
||||||
</CollapsibleContent>
|
</CollapsibleContent>
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
|
|
||||||
|
<!-- Active day-filter chip — removing it clears ONLY the date
|
||||||
|
selection (categories have their own clear in the filter
|
||||||
|
dropdown). Shown when a day is picked from the calendar popup. -->
|
||||||
|
<div v-if="selectedDate" class="mb-3 flex">
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
size="sm"
|
||||||
|
class="h-7 gap-1.5"
|
||||||
|
:aria-label="t('events.filters.clearDate', 'Clear date filter')"
|
||||||
|
@click="clearSelectedDate"
|
||||||
|
>
|
||||||
|
<CalendarDays class="w-3.5 h-3.5" />
|
||||||
|
{{ selectedDateLabel }}
|
||||||
|
<X class="w-3.5 h-3.5" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Create-activity CTA — shown when the Hosting bottom-nav tab is
|
<!-- Create-activity CTA — shown when the Hosting bottom-nav tab is
|
||||||
active. Replaces the dedicated Create entry that used to live
|
active. Replaces the dedicated Create entry that used to live
|
||||||
in the bottom nav; lives here so it shows up exactly when the
|
in the bottom nav; lives here so it shows up exactly when the
|
||||||
|
|
@ -210,5 +245,15 @@ function openCalendar() {
|
||||||
:compact="onlyHosting"
|
:compact="onlyHosting"
|
||||||
@select="handleSelectEvent"
|
@select="handleSelectEvent"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- Date-picker popup: month grid with per-day event dots. Picking a
|
||||||
|
day filters the feed to it and closes. -->
|
||||||
|
<EventCalendarPopup
|
||||||
|
v-model:open="calendarOpen"
|
||||||
|
:events="allEvents"
|
||||||
|
:title="t('events.nav.calendar', 'Calendar')"
|
||||||
|
:description="t('events.calendar.pickDay', 'Pick a day to see its events')"
|
||||||
|
@select-date="onSelectDate"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue