diff --git a/src/modules/activities/composables/useActivities.ts b/src/modules/activities/composables/useActivities.ts index 78b1bb5..67b49b5 100644 --- a/src/modules/activities/composables/useActivities.ts +++ b/src/modules/activities/composables/useActivities.ts @@ -8,6 +8,7 @@ import type { TicketedEvent } from '../types/ticket' import { ticketedEventToActivity } from '../types/activity' import { useActivitiesStore } from '../stores/activities' import { useActivityFilters } from './useActivityFilters' +import { useOwnedTickets } from './useOwnedTickets' /** * Main composable for activities discovery. @@ -17,6 +18,7 @@ export function useActivities() { const store = useActivitiesStore() const filters = useActivityFilters() const { isAuthenticated, currentUser } = useAuth() + const { ownedActivityIds } = useOwnedTickets() const isSubscribed = ref(false) const subscriptionError = ref(null) @@ -70,7 +72,10 @@ export function useActivities() { const all = store.activities.sort( (a, b) => a.startDate.getTime() - b.startDate.getTime() ) - return filters.applyFilters(all) + const filtered = filters.applyFilters(all) + if (!filters.onlyOwnedTickets.value) return filtered + const owned = ownedActivityIds.value + return filtered.filter(a => owned.has(a.id)) }) /** diff --git a/src/modules/activities/composables/useActivityFilters.ts b/src/modules/activities/composables/useActivityFilters.ts index ab3624b..60bcb5e 100644 --- a/src/modules/activities/composables/useActivityFilters.ts +++ b/src/modules/activities/composables/useActivityFilters.ts @@ -15,6 +15,13 @@ export function useActivityFilters() { const temporal = ref(DEFAULT_FILTERS.temporal) const selectedCategories = ref([]) const selectedDate = ref(undefined) + /** + * When true, the feed is narrowed to activities the current user + * holds at least one paid ticket for. Crossed with the + * `ownedActivityIds` set from useOwnedTickets in useActivities + * (this composable stays free of ticket fetching). + */ + const onlyOwnedTickets = ref(false) const filters = computed(() => ({ temporal: temporal.value, @@ -81,12 +88,18 @@ export function useActivityFilters() { temporal.value = DEFAULT_FILTERS.temporal selectedCategories.value = [] selectedDate.value = undefined + onlyOwnedTickets.value = false + } + + function toggleOwnedTickets() { + onlyOwnedTickets.value = !onlyOwnedTickets.value } const hasActiveFilters = computed(() => temporal.value !== 'all' || selectedCategories.value.length > 0 || - selectedDate.value !== undefined + selectedDate.value !== undefined || + onlyOwnedTickets.value ) return { @@ -94,6 +107,7 @@ export function useActivityFilters() { temporal, selectedCategories, selectedDate, + onlyOwnedTickets, filters, hasActiveFilters, @@ -103,6 +117,7 @@ export function useActivityFilters() { selectDate, toggleCategory, clearCategories, + toggleOwnedTickets, resetFilters, } } diff --git a/src/modules/activities/views/ActivitiesPage.vue b/src/modules/activities/views/ActivitiesPage.vue index 684aa97..d685a11 100644 --- a/src/modules/activities/views/ActivitiesPage.vue +++ b/src/modules/activities/views/ActivitiesPage.vue @@ -8,8 +8,9 @@ import { CollapsibleContent, CollapsibleTrigger, } from '@/components/ui/collapsible' -import { SlidersHorizontal, ChevronDown } from 'lucide-vue-next' +import { SlidersHorizontal, ChevronDown, Ticket } from 'lucide-vue-next' import { useActivities } from '../composables/useActivities' +import { useAuth } from '@/composables/useAuthService' import ActivitySearchOverlay from '../components/ActivitySearchOverlay.vue' import TemporalFilterBar from '../components/TemporalFilterBar.vue' import CategoryFilterBar from '../components/CategoryFilterBar.vue' @@ -28,14 +29,18 @@ const { selectedCategories, hasActiveFilters, selectedDate, + onlyOwnedTickets, selectDate, setTemporal, toggleCategory, clearCategories, + toggleOwnedTickets, resetFilters, subscribe, } = useActivities() +const { isAuthenticated } = useAuth() + const filtersOpen = ref(false) onMounted(() => { @@ -74,6 +79,21 @@ function handleSelectActivity(activity: Activity) { + +
+ +
+