diff --git a/src/activities-app/App.vue b/src/activities-app/App.vue index 640608b..4ac820a 100644 --- a/src/activities-app/App.vue +++ b/src/activities-app/App.vue @@ -7,8 +7,6 @@ import AppShell from '@/components/layout/AppShell.vue' import type { BottomTab } from '@/components/layout/BottomNav.vue' import { useAuth } from '@/composables/useAuthService' import { useActivitiesStore } from '@/modules/activities/stores/activities' -import { useActivities } from '@/modules/activities/composables/useActivities' -import { useApprovalState } from '@/modules/activities/composables/useApprovalState' import { injectService, SERVICE_TOKENS } from '@/core/di-container' import type { TicketApiService } from '@/modules/activities/services/TicketApiService' import type { CreateEventRequest } from '@/modules/activities/types/ticket' @@ -18,11 +16,6 @@ const route = useRoute() const { t } = useI18n() const { isAuthenticated, currentUser } = useAuth() const activitiesStore = useActivitiesStore() -const { isAdmin, autoApprove } = useApprovalState() -// Used to merge own LNbits drafts into the activities feed right after -// the user creates or edits an event — otherwise the new draft only -// surfaces on the next ActivitiesPage subscribe cycle. -const { loadOwnEvents } = useActivities() // Settings dropped — theme/lang/currency now live in the shared profile sheet. // Create lives in the bottom nav (auth-gated): activity creation is a deliberate @@ -34,12 +27,7 @@ const tabs = computed(() => [ { name: t('activities.createNew'), icon: Plus, - onClick: () => { - // Defensively clear any lingering edit selection so the Create - // tap always opens in Create mode regardless of a prior Edit. - activitiesStore.editingEvent = null - activitiesStore.showCreateDialog = true - }, + onClick: () => { activitiesStore.showCreateDialog = true }, disabled: !isAuthenticated.value, }, { name: t('activities.nav.map'), icon: Map, path: '/activities/map' }, @@ -69,40 +57,14 @@ async function handleCreateEvent(eventData: CreateEventRequest) { if (!invoiceKey) throw new Error('No wallet available. Please log in first.') await ticketApi.createEvent(eventData, invoiceKey) } - -async function handleUpdateEvent(eventId: string, eventData: CreateEventRequest) { - const ticketApi = injectService(SERVICE_TOKENS.TICKET_API) as TicketApiService - // PUT /events/{id} requires the event's wallet admin key. - const wallet = (currentUser.value?.wallets ?? []).find( - (w) => w.id === activitiesStore.editingEvent?.wallet, - ) - const adminKey = wallet?.adminkey - if (!adminKey) { - throw new Error("Can't find the admin key for this event's wallet.") - } - await ticketApi.updateEvent(eventId, eventData, adminKey) -} - -function handleDialogOpenChange(open: boolean) { - activitiesStore.showCreateDialog = open - // Closing always clears the edit selection so the next "+ Create" - // opens clean instead of inheriting the last-edited event. - if (!open) activitiesStore.editingEvent = null -} diff --git a/src/modules/activities/components/ActivityCard.vue b/src/modules/activities/components/ActivityCard.vue index d021b10..71054fb 100644 --- a/src/modules/activities/components/ActivityCard.vue +++ b/src/modules/activities/components/ActivityCard.vue @@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n' import { format } from 'date-fns' import { Card, CardContent } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' -import { MapPin, Calendar, Ticket, User } from 'lucide-vue-next' +import { MapPin, Calendar, Ticket } from 'lucide-vue-next' import BookmarkButton from './BookmarkButton.vue' import { useDateLocale } from '../composables/useDateLocale' import type { Activity } from '../types/activity' @@ -87,17 +87,6 @@ const placeholderBg = computed(() => { {{ categoryLabel }} - - - - Yours - - { {{ priceDisplay }} - - - {{ activity.lnbitsStatus === 'rejected' ? 'Rejected' : 'Pending review' }} - diff --git a/src/modules/activities/components/CreateEventDialog.vue b/src/modules/activities/components/CreateEventDialog.vue index 180184b..dd5ab5f 100644 --- a/src/modules/activities/components/CreateEventDialog.vue +++ b/src/modules/activities/components/CreateEventDialog.vue @@ -1,5 +1,5 @@ @@ -123,7 +83,7 @@ function handleEventChanged() {
- @@ -145,16 +105,7 @@ function handleEventChanged() {
-
- {{ event.name }} - - {{ event.status === 'rejected' ? 'Rejected' : 'Pending review' }} - -
+ {{ event.name }} {{ event.info }}
@@ -177,33 +128,19 @@ function handleEventChanged() {
- + - @@ -252,18 +189,10 @@ function handleEventChanged() { diff --git a/src/modules/base/components/ImageUpload.vue b/src/modules/base/components/ImageUpload.vue index e64c825..228e7ec 100644 --- a/src/modules/base/components/ImageUpload.vue +++ b/src/modules/base/components/ImageUpload.vue @@ -449,11 +449,7 @@ const removeImage = async (imageToRemove: ImageWithMetadata) => { if (props.disabled) return try { - // Server-side delete only when we have a delete_token (newly - // uploaded this session). Pre-existing images re-populated from a - // stored URL ship `delete_token: ''` by convention — we don't own - // the original upload's one-time token, and removing on the client - // shouldn't reach back and wipe the server-side file. + // Only try to delete from pict-rs if we have a delete token (newly uploaded images) if (imageToRemove.delete_token) { await imageService.deleteImage(imageToRemove.delete_token, imageToRemove.alias) } diff --git a/src/modules/base/services/ImageUploadService.ts b/src/modules/base/services/ImageUploadService.ts index 69aadae..2063ce3 100644 --- a/src/modules/base/services/ImageUploadService.ts +++ b/src/modules/base/services/ImageUploadService.ts @@ -300,12 +300,9 @@ export class ImageUploadService extends BaseService { } /** - * Extract a pict-rs file ID from an alias, accepting both bare IDs - * and full `/image/original/` URLs. Public so callers - * re-populating uploads from stored URLs (edit flows) don't have to - * re-implement the parse. + * Extract file ID from alias, handling both file IDs and full URLs */ - extractFileId(alias: string): string { + private extractFileId(alias: string): string { if (!alias) { return '' } diff --git a/src/modules/market/components/CreateProductDialog.vue b/src/modules/market/components/CreateProductDialog.vue index 23eb9ac..dd5b505 100644 --- a/src/modules/market/components/CreateProductDialog.vue +++ b/src/modules/market/components/CreateProductDialog.vue @@ -516,17 +516,30 @@ watch(() => props.isOpen, async (isOpen) => { // Reset form with appropriate initial values resetForm({ values: initialValues }) - // Convert existing image URLs to the format expected by ImageUpload. - // delete_token is intentionally empty for pre-existing images: see - // ImageUploadService.deleteImage gate — removing on the client - // should not delete the server-side file. + // Convert existing image URLs to the format expected by ImageUpload component if (props.product?.images && props.product.images.length > 0) { - uploadedImages.value = props.product.images.map((url, index) => ({ - alias: imageService.extractFileId(url), - delete_token: '', - isPrimary: index === 0, - details: {} as any, - })) + // For existing products, we need to convert URLs back to a format ImageUpload can display + uploadedImages.value = props.product.images.map((url, index) => { + let alias = url + + // If it's a full pict-rs URL, extract just the file ID + if (url.includes('/image/original/')) { + const parts = url.split('/image/original/') + if (parts.length > 1 && parts[1]) { + alias = parts[1] + } + } else if (url.startsWith('http://') || url.startsWith('https://')) { + // Keep full URLs as-is + alias = url + } + + return { + alias: alias, + delete_token: '', + isPrimary: index === 0, + details: {} + } + }) } else { uploadedImages.value = [] }