From f20b404d0953c1dd01ddfb1e0b652901d660a10e Mon Sep 17 00:00:00 2001 From: Padreug Date: Tue, 16 Jun 2026 00:45:41 +0200 Subject: [PATCH] feat(events): show total ticket capacity alongside remaining Availability only showed remaining ("N tickets available"), not the total capacity. Derive total (remaining + sold) on EventTicketInfo and display "N of M tickets left" on both the event card and the detail page, so buyers can gauge demand. Unlimited events are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/i18n/locales/en.ts | 1 + src/i18n/locales/es.ts | 1 + src/i18n/locales/fr.ts | 1 + src/i18n/types.ts | 1 + src/modules/events/components/EventCard.vue | 2 +- src/modules/events/types/event.ts | 5 +++++ src/modules/events/views/EventDetailPage.vue | 2 +- 7 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index 331c5d4..34f4bc6 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -107,6 +107,7 @@ const messages: LocaleMessages = { when: 'When', tickets: 'Tickets', ticketsAvailable: '{count} tickets available', + ticketsRemainingOfTotal: '{count} of {total} tickets left', ticketsOwned: 'You have {count} ticket | You have {count} tickets', unlimitedTickets: 'Unlimited tickets', buyTicket: 'Buy ticket', diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts index 6b42a69..048c71a 100644 --- a/src/i18n/locales/es.ts +++ b/src/i18n/locales/es.ts @@ -107,6 +107,7 @@ const messages: LocaleMessages = { when: 'Cuándo', tickets: 'Boletos', ticketsAvailable: '{count} boletos disponibles', + ticketsRemainingOfTotal: '{count} de {total} boletos restantes', ticketsOwned: 'Tienes {count} boleto | Tienes {count} boletos', unlimitedTickets: 'Boletos ilimitados', buyTicket: 'Comprar boleto', diff --git a/src/i18n/locales/fr.ts b/src/i18n/locales/fr.ts index ff76d79..57b3797 100644 --- a/src/i18n/locales/fr.ts +++ b/src/i18n/locales/fr.ts @@ -107,6 +107,7 @@ const messages: LocaleMessages = { when: 'Quand', tickets: 'Billets', ticketsAvailable: '{count} billets disponibles', + ticketsRemainingOfTotal: '{count} sur {total} billets restants', ticketsOwned: 'Vous avez {count} billet | Vous avez {count} billets', unlimitedTickets: 'Billets illimités', buyTicket: 'Acheter un billet', diff --git a/src/i18n/types.ts b/src/i18n/types.ts index 63e8fc3..f4177ba 100644 --- a/src/i18n/types.ts +++ b/src/i18n/types.ts @@ -82,6 +82,7 @@ export interface LocaleMessages { when: string tickets: string ticketsAvailable: string + ticketsRemainingOfTotal: string ticketsOwned: string unlimitedTickets: string buyTicket: string diff --git a/src/modules/events/components/EventCard.vue b/src/modules/events/components/EventCard.vue index 91ccb0b..2604798 100644 --- a/src/modules/events/components/EventCard.vue +++ b/src/modules/events/components/EventCard.vue @@ -245,7 +245,7 @@ const isNonApproved = computed( {{ t('events.detail.unlimitedTickets', 'Unlimited tickets') }} - {{ t('events.detail.ticketsAvailable', { count: event.ticketInfo.available }) }} + {{ t('events.detail.ticketsRemainingOfTotal', { count: event.ticketInfo.available, total: event.ticketInfo.total }) }} {{ t('events.detail.soldOut') }} diff --git a/src/modules/events/types/event.ts b/src/modules/events/types/event.ts index 56a446d..88762b3 100644 --- a/src/modules/events/types/event.ts +++ b/src/modules/events/types/event.ts @@ -78,6 +78,8 @@ export interface EventTicketInfo { available?: number /** Running paid count. */ sold: number + /** Total capacity (available + sold). Undefined means unlimited. */ + total?: number /** Whether the organizer enabled fiat checkout. */ allowFiat: boolean /** Fiat settle currency when allowFiat is true. */ @@ -91,6 +93,9 @@ function ticketTagsToInfo(ticket: TicketTags | undefined): EventTicketInfo | und currency: ticket.currency, available: ticket.available, sold: ticket.sold, + // Capacity isn't published directly; derive it from remaining + sold. + // Undefined `available` means unlimited, so total stays undefined too. + total: ticket.available !== undefined ? ticket.available + ticket.sold : undefined, allowFiat: ticket.allowFiat, fiatCurrency: ticket.fiatCurrency, } diff --git a/src/modules/events/views/EventDetailPage.vue b/src/modules/events/views/EventDetailPage.vue index b67aa66..10fdbc8 100644 --- a/src/modules/events/views/EventDetailPage.vue +++ b/src/modules/events/views/EventDetailPage.vue @@ -347,7 +347,7 @@ function goToMyTickets() { {{ t('events.detail.unlimitedTickets', 'Unlimited tickets') }} - {{ t('events.detail.ticketsAvailable', { count: event.ticketInfo.available }) }} + {{ t('events.detail.ticketsRemainingOfTotal', { count: event.ticketInfo.available, total: event.ticketInfo.total }) }}