ui(activities): surface tickets-remaining on the event detail page

The card had it; the detail page didn't. Reuses the same three-
state language as the card ("Unlimited" / "{count} tickets
available" / "Sold out") so the buyer sees the same signal on
both surfaces.

Placed at the top of the tickets section, above the owned-tickets
chip + buy CTA, so it reads top-down: how many are left → how
many you have → buy more.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-05-23 23:08:33 +02:00
commit 7e3ecf81db

View file

@ -274,9 +274,23 @@ function goToMyTickets() {
<!-- Tickets gated on the activity carrying ticketInfo (set
by the calendarActivity converter from the AIO custom
tickets_* tags on the published event). Sections render
bottom-up: existing owned tickets (when count > 0) above
a Purchase CTA (when capacity remains). -->
bottom-up: availability count, then existing owned
tickets (when count > 0) above a Purchase CTA (when
capacity remains). -->
<div v-if="activity.ticketInfo" class="space-y-3">
<div class="flex items-center gap-1.5 text-sm text-muted-foreground">
<Ticket class="w-4 h-4 shrink-0" />
<span v-if="activity.ticketInfo.available === undefined">
{{ t('activities.detail.unlimitedTickets', 'Unlimited tickets') }}
</span>
<span v-else-if="activity.ticketInfo.available > 0">
{{ t('activities.detail.ticketsAvailable', { count: activity.ticketInfo.available }) }}
</span>
<span v-else class="text-destructive font-medium">
{{ t('activities.detail.soldOut') }}
</span>
</div>
<div
v-if="ownedPaidCount > 0"
class="bg-primary/10 border border-primary/30 rounded-lg p-4 flex items-center justify-between gap-3"