Compare commits
3 commits
2febf0926d
...
83ea3e609c
| Author | SHA1 | Date | |
|---|---|---|---|
| 83ea3e609c | |||
| 3514d93451 | |||
| db4c9b8bf3 |
6 changed files with 72 additions and 7 deletions
|
|
@ -71,6 +71,8 @@ const messages: LocaleMessages = {
|
|||
past: 'Past',
|
||||
filters: 'Filters',
|
||||
clearAll: 'Clear all',
|
||||
filteringBy: 'Filtering by:',
|
||||
removeCategory: 'Remove {category} filter',
|
||||
},
|
||||
categories: {
|
||||
concert: 'Concert',
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ const messages: LocaleMessages = {
|
|||
past: 'Pasado',
|
||||
filters: 'Filtros',
|
||||
clearAll: 'Limpiar todo',
|
||||
filteringBy: 'Filtrando por:',
|
||||
removeCategory: 'Quitar el filtro {category}',
|
||||
},
|
||||
categories: {
|
||||
concert: 'Concierto',
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ const messages: LocaleMessages = {
|
|||
past: 'Passé',
|
||||
filters: 'Filtres',
|
||||
clearAll: 'Tout effacer',
|
||||
filteringBy: 'Filtré par :',
|
||||
removeCategory: 'Retirer le filtre {category}',
|
||||
},
|
||||
categories: {
|
||||
concert: 'Concert',
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ export interface LocaleMessages {
|
|||
past: string
|
||||
filters: string
|
||||
clearAll: string
|
||||
filteringBy: string
|
||||
removeCategory: string
|
||||
}
|
||||
categories: Record<string, string>
|
||||
detail: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import {
|
||||
DialogRoot,
|
||||
DialogPortal,
|
||||
|
|
@ -10,8 +11,10 @@ import {
|
|||
DialogClose,
|
||||
} from 'reka-ui'
|
||||
import { X } from 'lucide-vue-next'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import EventCalendarView from './EventCalendarView.vue'
|
||||
import type { Event } from '../types/event'
|
||||
import type { EventCategory } from '../types/category'
|
||||
|
||||
// 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
|
||||
|
|
@ -21,23 +24,40 @@ import type { Event } from '../types/event'
|
|||
// DialogContent) so it can use a light, blurred overlay instead of the
|
||||
// usual opaque dark dim — the feed stays visible, softly blurred, behind
|
||||
// the frosted-glass panel.
|
||||
const props = defineProps<{
|
||||
open: boolean
|
||||
events: Event[]
|
||||
title: string
|
||||
description: string
|
||||
}>()
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
open: boolean
|
||||
events: Event[]
|
||||
title: string
|
||||
description: string
|
||||
// Active category filter mirrored from the feed. Rendered as
|
||||
// deselectable chips so the user can see — and loosen — what's
|
||||
// narrowing the calendar without closing it. Defaults to none for
|
||||
// callers that don't filter by category (e.g. My Tickets).
|
||||
selectedCategories?: EventCategory[]
|
||||
}>(),
|
||||
{
|
||||
selectedCategories: () => [],
|
||||
},
|
||||
)
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:open': [value: boolean]
|
||||
selectDate: [date: Date]
|
||||
'toggle-category': [category: EventCategory]
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const isOpen = computed({
|
||||
get: () => props.open,
|
||||
set: (v) => emit('update:open', v),
|
||||
})
|
||||
|
||||
function categoryLabel(cat: EventCategory): string {
|
||||
return t(`events.categories.${cat}`, cat)
|
||||
}
|
||||
|
||||
function onSelectDate(date: Date) {
|
||||
emit('selectDate', date)
|
||||
isOpen.value = false
|
||||
|
|
@ -62,6 +82,29 @@ function onSelectDate(date: Date) {
|
|||
{{ description }}
|
||||
</DialogDescription>
|
||||
</div>
|
||||
<!-- Active category filter — only the selected categories, each
|
||||
removable. Clicking deselects via the parent's toggle, which
|
||||
reactively re-narrows the calendar dots without closing. -->
|
||||
<div
|
||||
v-if="selectedCategories.length"
|
||||
class="flex flex-wrap items-center gap-1.5"
|
||||
>
|
||||
<span class="text-xs text-muted-foreground">
|
||||
{{ t('events.filters.filteringBy') }}
|
||||
</span>
|
||||
<Badge
|
||||
v-for="cat in selectedCategories"
|
||||
:key="cat"
|
||||
variant="secondary"
|
||||
class="cursor-pointer gap-1 text-xs select-none hover:opacity-80 transition-opacity"
|
||||
:aria-label="t('events.filters.removeCategory', { category: categoryLabel(cat) })"
|
||||
@click="emit('toggle-category', cat)"
|
||||
>
|
||||
{{ categoryLabel(cat) }}
|
||||
<X class="w-3 h-3" />
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<EventCalendarView :events="events" picker-mode @select-date="onSelectDate" />
|
||||
<DialogClose
|
||||
class="absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none"
|
||||
|
|
|
|||
|
|
@ -61,6 +61,18 @@ const {
|
|||
const filtersOpen = ref(false)
|
||||
const calendarOpen = ref(false)
|
||||
|
||||
// Events feeding the calendar popup's per-day dots. Respects the active
|
||||
// category filter (so the calendar reflects what the user is browsing),
|
||||
// but not the temporal/day filters — the calendar is for picking any
|
||||
// date. No categories selected ⇒ all events.
|
||||
const calendarEvents = computed(() =>
|
||||
selectedCategories.value.length
|
||||
? allEvents.value.filter(
|
||||
(e) => e.category && selectedCategories.value.includes(e.category),
|
||||
)
|
||||
: allEvents.value,
|
||||
)
|
||||
|
||||
// Human label for the active day filter, shown as a removable chip.
|
||||
const selectedDateLabel = computed(() =>
|
||||
selectedDate.value
|
||||
|
|
@ -255,10 +267,12 @@ onBeforeRouteLeave(() => {
|
|||
day filters the feed to it and closes. -->
|
||||
<EventCalendarPopup
|
||||
v-model:open="calendarOpen"
|
||||
:events="allEvents"
|
||||
:events="calendarEvents"
|
||||
:selected-categories="selectedCategories"
|
||||
:title="t('events.nav.calendar', 'Calendar')"
|
||||
:description="t('events.calendar.pickDay', 'Pick a day to see its events')"
|
||||
@select-date="onSelectDate"
|
||||
@toggle-category="toggleCategory"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue