diff --git a/resources/js/admin/i18n/locales/de/management.json b/resources/js/admin/i18n/locales/de/management.json
index 2130ecc4..0593a314 100644
--- a/resources/js/admin/i18n/locales/de/management.json
+++ b/resources/js/admin/i18n/locales/de/management.json
@@ -95,7 +95,10 @@
"noPackage": "Für dieses Event ist derzeit kein Paket zugewiesen.",
"addonsLabel": "Add-ons für dieses Event",
"noAddons": "Für dieses Event wurden noch keine Add-ons gekauft.",
- "eventAddonSource": "Quelle: Event-Paket"
+ "eventAddonSource": "Quelle: Event-Paket",
+ "openAddonShop": "Add-ons für dieses Event kaufen",
+ "openAddonUpsell": "Control-Room-Upgrades öffnen",
+ "noAddonCatalog": "Aktuell sind keine Add-ons zum Kauf verfügbar."
},
"invoices": {
"title": "Rechnungen & Zahlungen",
@@ -106,7 +109,8 @@
"title": "Add-on-Kaufverlauf",
"hint": "Verlauf aller Add-on-Käufe über alle Events. Ein Eintrag hier ist nicht automatisch für das aktuell ausgewählte Event aktiv.",
"empty": "Keine Add-ons gebucht.",
- "otherEventNotice": "Für ein anderes Event gekauft"
+ "otherEventNotice": "Für ein anderes Event gekauft",
+ "openShop": "Jetzt Add-ons kaufen"
},
"overview": {
"title": "Paketübersicht",
@@ -497,6 +501,25 @@
"buyMoreGuests": "Mehr Gäste freischalten",
"extendGallery": "Galerie verlängern"
},
+ "addons": {
+ "title": "Event-Add-ons",
+ "event": "Event",
+ "packageExpires": "Galerie aktiv bis {{date}}",
+ "noPackage": "Für dieses Event ist derzeit kein Paket zugewiesen.",
+ "recommendedTitle": "Jetzt empfohlen",
+ "recommendedBody": "Basierend auf deiner Event-Nutzung sind diese Add-ons aktuell besonders relevant.",
+ "recommendedBadge": "Empfohlen",
+ "buyAction": "Add-on kaufen",
+ "historyTitle": "Gekaufte Add-ons für dieses Event",
+ "noAddonAvailable": "Aktuell sind keine Add-ons verfügbar.",
+ "groups": {
+ "photos": "Foto-Kapazität",
+ "guests": "Gäste-Kapazität",
+ "gallery": "Galerie-Laufzeit",
+ "bundle": "Bundles",
+ "feature": "Feature-Freischaltungen"
+ }
+ },
"form": {
"editTitle": "Event bearbeiten",
"createTitle": "Neues Event erstellen",
diff --git a/resources/js/admin/i18n/locales/en/management.json b/resources/js/admin/i18n/locales/en/management.json
index aa6a3993..59cf8ba6 100644
--- a/resources/js/admin/i18n/locales/en/management.json
+++ b/resources/js/admin/i18n/locales/en/management.json
@@ -95,7 +95,10 @@
"noPackage": "No package is currently assigned to this event.",
"addonsLabel": "Add-ons for this event",
"noAddons": "No add-ons purchased for this event.",
- "eventAddonSource": "Source: event package"
+ "eventAddonSource": "Source: event package",
+ "openAddonShop": "Buy add-ons for this event",
+ "openAddonUpsell": "Open control-room upgrades",
+ "noAddonCatalog": "No add-ons are currently available for purchase."
},
"invoices": {
"title": "Invoices & payments",
@@ -106,7 +109,8 @@
"title": "Add-on purchase history",
"hint": "History of all add-on purchases across all events. An entry here is not automatically active for the currently selected event.",
"empty": "No add-ons booked.",
- "otherEventNotice": "Purchased for another event"
+ "otherEventNotice": "Purchased for another event",
+ "openShop": "Buy add-ons now"
},
"overview": {
"title": "Package overview",
@@ -493,6 +497,25 @@
"buyMoreGuests": "Unlock more guests",
"extendGallery": "Extend gallery"
},
+ "addons": {
+ "title": "Event add-ons",
+ "event": "Event",
+ "packageExpires": "Gallery active until {{date}}",
+ "noPackage": "No package is currently assigned to this event.",
+ "recommendedTitle": "Recommended now",
+ "recommendedBody": "Based on your event usage, these add-ons are likely most relevant.",
+ "recommendedBadge": "Recommended",
+ "buyAction": "Buy add-on",
+ "historyTitle": "Purchased add-ons for this event",
+ "noAddonAvailable": "No add-ons are currently available.",
+ "groups": {
+ "photos": "Photo capacity",
+ "guests": "Guest capacity",
+ "gallery": "Gallery runtime",
+ "bundle": "Bundles",
+ "feature": "Feature unlocks"
+ }
+ },
"form": {
"editTitle": "Edit event",
"createTitle": "Create new event",
diff --git a/resources/js/admin/mobile/EventAddonsPage.tsx b/resources/js/admin/mobile/EventAddonsPage.tsx
index 6f3f903f..dfaff7e9 100644
--- a/resources/js/admin/mobile/EventAddonsPage.tsx
+++ b/resources/js/admin/mobile/EventAddonsPage.tsx
@@ -148,6 +148,21 @@ function resolveScopeFromQuery(input: string | null): 'photos' | 'guests' | 'gal
return null;
}
+function resolveEventName(
+ name: TenantEvent['name'],
+ t: (key: string, fallback: string) => string,
+): string {
+ if (typeof name === 'string' && name.trim() !== '') {
+ return name;
+ }
+
+ if (name && typeof name === 'object') {
+ return name.de ?? name.en ?? Object.values(name)[0] ?? t('events.placeholders.untitled', 'Untitled event');
+ }
+
+ return t('events.placeholders.untitled', 'Untitled event');
+}
+
export default function MobileEventAddonsPage() {
const { slug } = useParams<{ slug: string }>();
const navigate = useNavigate();
@@ -355,7 +370,7 @@ export default function MobileEventAddonsPage() {
{t('events.addons.event', 'Event')}
- {typeof event.name === 'string' ? event.name : t('events.placeholders.untitled', 'Untitled event')}
+ {resolveEventName(event.name, t as any)}
{event.package?.name ? (
@@ -403,7 +418,7 @@ export default function MobileEventAddonsPage() {
{!hasSellableAddons ? (
- {t('events.recap.noAddonAvailable', 'No add-ons are currently available.')}
+ {t('events.addons.noAddonAvailable', 'No add-ons are currently available.')}
) : (
diff --git a/resources/js/admin/mobile/__tests__/EventAddonsPage.test.tsx b/resources/js/admin/mobile/__tests__/EventAddonsPage.test.tsx
index e86dc617..c8ced1ab 100644
--- a/resources/js/admin/mobile/__tests__/EventAddonsPage.test.tsx
+++ b/resources/js/admin/mobile/__tests__/EventAddonsPage.test.tsx
@@ -7,7 +7,7 @@ const navigateMock = vi.fn();
const fixtures = vi.hoisted(() => ({
event: {
id: 42,
- name: 'Demo Event',
+ name: { de: 'Demo Event DE', en: 'Demo Event EN' },
slug: 'demo-event',
status: 'published',
event_date: '2026-02-01T12:00:00Z',
@@ -165,6 +165,7 @@ describe('MobileEventAddonsPage', () => {
it('renders add-ons and event-specific purchase history', async () => {
render();
+ expect(await screen.findByText('Demo Event DE')).toBeInTheDocument();
expect((await screen.findAllByText('Extend gallery 30 days')).length).toBeGreaterThan(0);
expect(screen.getByText('Extra photos 500')).toBeInTheDocument();
expect(screen.getByText('Purchased add-ons for this event')).toBeInTheDocument();