Fix notification event names and allow welcome onboarding
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-02-04 11:22:38 +01:00
parent 049c4f82b9
commit 9ddb135c03
5 changed files with 53 additions and 3 deletions

View File

@@ -43,6 +43,16 @@ type NotificationSwipeRowProps = {
children: React.ReactNode; children: React.ReactNode;
}; };
function resolveEventName(name: TenantEvent['name'], t: (key: string, fallback?: string) => string): string {
if (typeof name === 'string') {
return name;
}
if (name && typeof name === 'object') {
return name.de ?? name.en ?? Object.values(name)[0] ?? t('events.placeholders.untitled', 'Unbenanntes Event');
}
return t('events.placeholders.untitled', 'Unbenanntes Event');
}
function NotificationSwipeRow({ item, onOpen, onMarkRead, children }: NotificationSwipeRowProps) { function NotificationSwipeRow({ item, onOpen, onMarkRead, children }: NotificationSwipeRowProps) {
const { t } = useTranslation('management'); const { t } = useTranslation('management');
const { successBg, successText, infoBg, infoText } = useAdminTheme(); const { successBg, successText, infoBg, infoText } = useAdminTheme();
@@ -296,7 +306,7 @@ async function loadNotifications(
}); });
const lookup = new Map<number, string>(); const lookup = new Map<number, string>();
(events ?? []).forEach((event) => { (events ?? []).forEach((event) => {
lookup.set(event.id, typeof event.name === 'string' ? event.name : (event.name as Record<string, string>)?.en ?? ''); lookup.set(event.id, resolveEventName(event.name, t));
}); });
return (response.data ?? []) return (response.data ?? [])
@@ -756,7 +766,7 @@ export default function MobileNotificationsPage() {
<XStack alignItems="center" justifyContent="space-between" paddingVertical="$2"> <XStack alignItems="center" justifyContent="space-between" paddingVertical="$2">
<YStack> <YStack>
<Text fontSize="$sm" fontWeight="700" color={text}> <Text fontSize="$sm" fontWeight="700" color={text}>
{ev.name} {resolveEventName(ev.name, t)}
</Text> </Text>
<Text fontSize="$xs" color={muted}> <Text fontSize="$xs" color={muted}>
{ev.slug} {ev.slug}

View File

@@ -27,7 +27,14 @@ vi.mock('react-i18next', () => ({
vi.mock('../../api', () => ({ vi.mock('../../api', () => ({
listNotificationLogs: vi.fn().mockResolvedValue([]), listNotificationLogs: vi.fn().mockResolvedValue([]),
markNotificationLogs: vi.fn(), markNotificationLogs: vi.fn(),
getEvents: vi.fn().mockResolvedValue([]), getEvents: vi.fn().mockResolvedValue([
{
id: 1,
slug: 'demo-event',
name: { de: 'Demo Event' },
status: 'active',
},
]),
})); }));
vi.mock('../../auth/tokens', () => ({ vi.mock('../../auth/tokens', () => ({
@@ -131,5 +138,6 @@ describe('MobileNotificationsPage', () => {
render(<MobileNotificationsPage />); render(<MobileNotificationsPage />);
expect(await screen.findByText('All caught up')).toBeInTheDocument(); expect(await screen.findByText('All caught up')).toBeInTheDocument();
expect(await screen.findByText('Demo Event')).toBeInTheDocument();
}); });
}); });

View File

@@ -12,6 +12,7 @@ describe('resolveOnboardingRedirect', () => {
remainingEvents: null, remainingEvents: null,
pathname: '/event-admin/mobile/dashboard', pathname: '/event-admin/mobile/dashboard',
isBillingPath: false, isBillingPath: false,
isWelcomePath: false,
isOnboardingDismissed: false, isOnboardingDismissed: false,
isOnboardingCompleted: false, isOnboardingCompleted: false,
isSuperAdmin: false, isSuperAdmin: false,
@@ -26,6 +27,7 @@ describe('resolveOnboardingRedirect', () => {
remainingEvents: null, remainingEvents: null,
pathname: ADMIN_BILLING_PATH, pathname: ADMIN_BILLING_PATH,
isBillingPath: true, isBillingPath: true,
isWelcomePath: false,
isOnboardingDismissed: false, isOnboardingDismissed: false,
isOnboardingCompleted: false, isOnboardingCompleted: false,
isSuperAdmin: false, isSuperAdmin: false,
@@ -40,6 +42,7 @@ describe('resolveOnboardingRedirect', () => {
remainingEvents: 1, remainingEvents: 1,
pathname: '/event-admin/mobile/events/new', pathname: '/event-admin/mobile/events/new',
isBillingPath: false, isBillingPath: false,
isWelcomePath: false,
isOnboardingDismissed: false, isOnboardingDismissed: false,
isOnboardingCompleted: false, isOnboardingCompleted: false,
isSuperAdmin: false, isSuperAdmin: false,
@@ -54,6 +57,7 @@ describe('resolveOnboardingRedirect', () => {
remainingEvents: null, remainingEvents: null,
pathname: '/event-admin/mobile/dashboard', pathname: '/event-admin/mobile/dashboard',
isBillingPath: false, isBillingPath: false,
isWelcomePath: false,
isOnboardingDismissed: false, isOnboardingDismissed: false,
isOnboardingCompleted: false, isOnboardingCompleted: false,
isSuperAdmin: false, isSuperAdmin: false,
@@ -68,6 +72,7 @@ describe('resolveOnboardingRedirect', () => {
remainingEvents: 0, remainingEvents: 0,
pathname: '/event-admin/mobile/dashboard', pathname: '/event-admin/mobile/dashboard',
isBillingPath: false, isBillingPath: false,
isWelcomePath: false,
isOnboardingDismissed: false, isOnboardingDismissed: false,
isOnboardingCompleted: false, isOnboardingCompleted: false,
isSuperAdmin: false, isSuperAdmin: false,
@@ -82,6 +87,7 @@ describe('resolveOnboardingRedirect', () => {
remainingEvents: 2, remainingEvents: 2,
pathname: '/event-admin/mobile/dashboard', pathname: '/event-admin/mobile/dashboard',
isBillingPath: false, isBillingPath: false,
isWelcomePath: false,
isOnboardingDismissed: false, isOnboardingDismissed: false,
isOnboardingCompleted: false, isOnboardingCompleted: false,
isSuperAdmin: false, isSuperAdmin: false,
@@ -96,6 +102,7 @@ describe('resolveOnboardingRedirect', () => {
remainingEvents: null, remainingEvents: null,
pathname: '/event-admin/mobile/dashboard', pathname: '/event-admin/mobile/dashboard',
isBillingPath: false, isBillingPath: false,
isWelcomePath: false,
isOnboardingDismissed: false, isOnboardingDismissed: false,
isOnboardingCompleted: false, isOnboardingCompleted: false,
isSuperAdmin: false, isSuperAdmin: false,
@@ -110,6 +117,7 @@ describe('resolveOnboardingRedirect', () => {
remainingEvents: null, remainingEvents: null,
pathname: '/event-admin/mobile/dashboard', pathname: '/event-admin/mobile/dashboard',
isBillingPath: false, isBillingPath: false,
isWelcomePath: false,
isOnboardingDismissed: true, isOnboardingDismissed: true,
isOnboardingCompleted: false, isOnboardingCompleted: false,
isSuperAdmin: false, isSuperAdmin: false,
@@ -124,6 +132,7 @@ describe('resolveOnboardingRedirect', () => {
remainingEvents: null, remainingEvents: null,
pathname: '/event-admin/mobile/dashboard', pathname: '/event-admin/mobile/dashboard',
isBillingPath: false, isBillingPath: false,
isWelcomePath: false,
isOnboardingCompleted: true, isOnboardingCompleted: true,
isSuperAdmin: false, isSuperAdmin: false,
}); });
@@ -137,10 +146,26 @@ describe('resolveOnboardingRedirect', () => {
remainingEvents: null, remainingEvents: null,
pathname: '/event-admin/mobile/dashboard', pathname: '/event-admin/mobile/dashboard',
isBillingPath: false, isBillingPath: false,
isWelcomePath: false,
isOnboardingDismissed: false, isOnboardingDismissed: false,
isOnboardingCompleted: false, isOnboardingCompleted: false,
isSuperAdmin: true, isSuperAdmin: true,
}); });
expect(result).toBeNull(); expect(result).toBeNull();
}); });
it('returns null for welcome paths', () => {
const result = resolveOnboardingRedirect({
hasEvents: false,
hasActivePackage: false,
remainingEvents: null,
pathname: '/event-admin/mobile/welcome',
isBillingPath: false,
isWelcomePath: true,
isOnboardingDismissed: false,
isOnboardingCompleted: false,
isSuperAdmin: false,
});
expect(result).toBeNull();
});
}); });

View File

@@ -9,6 +9,7 @@ type OnboardingRedirectInput = {
remainingEvents?: number | null; remainingEvents?: number | null;
pathname: string; pathname: string;
isBillingPath: boolean; isBillingPath: boolean;
isWelcomePath?: boolean;
isOnboardingDismissed?: boolean; isOnboardingDismissed?: boolean;
isOnboardingCompleted?: boolean; isOnboardingCompleted?: boolean;
isSuperAdmin?: boolean; isSuperAdmin?: boolean;
@@ -20,6 +21,7 @@ export function resolveOnboardingRedirect({
remainingEvents, remainingEvents,
pathname, pathname,
isBillingPath, isBillingPath,
isWelcomePath,
isOnboardingDismissed, isOnboardingDismissed,
isOnboardingCompleted, isOnboardingCompleted,
isSuperAdmin, isSuperAdmin,
@@ -28,6 +30,10 @@ export function resolveOnboardingRedirect({
return null; return null;
} }
if (isWelcomePath) {
return null;
}
if (isOnboardingDismissed || isOnboardingCompleted) { if (isOnboardingDismissed || isOnboardingCompleted) {
return null; return null;
} }

View File

@@ -98,6 +98,7 @@ function RequireAuth() {
remainingEvents, remainingEvents,
pathname: location.pathname, pathname: location.pathname,
isBillingPath, isBillingPath,
isWelcomePath,
isOnboardingDismissed, isOnboardingDismissed,
isOnboardingCompleted, isOnboardingCompleted,
isSuperAdmin, isSuperAdmin,