From 01b871e7fad7aac5c5ca6eee2231586335d0703e Mon Sep 17 00:00:00 2001 From: Padreug Date: Thu, 21 May 2026 15:55:19 +0200 Subject: [PATCH] feat(activities): merge own events into the feed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When authenticated, parallel-fetch the caller's own events (any status) alongside the public approved feed and merge with public-wins dedup. Without this, an event that drops to `proposed` after a non-admin edit disappears from the user's view — they couldn't find it to make a follow-up edit or watch for re-approval. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../activities/composables/useEvents.ts | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/modules/activities/composables/useEvents.ts b/src/modules/activities/composables/useEvents.ts index a67cf69..cdc5902 100644 --- a/src/modules/activities/composables/useEvents.ts +++ b/src/modules/activities/composables/useEvents.ts @@ -1,14 +1,43 @@ import { computed } from 'vue' import { useAsyncState } from '@vueuse/core' import { injectService, SERVICE_TOKENS } from '@/core/di-container' +import { useAuth } from '@/composables/useAuthService' import type { TicketApiService } from '../services/TicketApiService' import type { TicketedEvent } from '../types/ticket' export function useEvents() { const ticketApi = injectService(SERVICE_TOKENS.TICKET_API) as TicketApiService + const { isAuthenticated, currentUser } = useAuth() + + // When authenticated, also fetch the user's own events (any status) + // and merge them into the feed. Otherwise an event that drops to + // `proposed` after a non-admin edit disappears from the user's view + // entirely — they'd be unable to find it to make a follow-up edit or + // monitor its approval status. Public approved events from other + // users take precedence on dedup (server is the source of truth for + // the public view). + const fetchAll = async (): Promise => { + const publicEvents = (await ticketApi.fetchTicketedEvents()) as TicketedEvent[] + + if (!isAuthenticated.value) return publicEvents + + const invoiceKey = currentUser.value?.wallets?.[0]?.inkey + if (!invoiceKey) return publicEvents + + try { + const myEvents = (await ticketApi.fetchMyEvents(invoiceKey)) as TicketedEvent[] + const seen = new Set(publicEvents.map((e) => e.id)) + const own = myEvents.filter((e) => !seen.has(e.id)) + return [...publicEvents, ...own] + } catch { + // Falling back to just the public feed is acceptable — the user + // can still browse, they just won't see their own pending events. + return publicEvents + } + } const { state: events, isLoading, error: asyncError, execute: refresh } = useAsyncState( - () => ticketApi.fetchTicketedEvents() as Promise, + fetchAll, [] as TicketedEvent[], { immediate: true,