import React from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { useQuery } from '@tanstack/react-query'; import { BarChart2, TrendingUp, Users, ListTodo, Lock, Trophy, Calendar } from 'lucide-react'; import { YStack, XStack } from '@tamagui/stacks'; import { SizableText as Text } from '@tamagui/text'; import { format, parseISO } from 'date-fns'; import { de, enGB } from 'date-fns/locale'; import { MobileShell } from './components/MobileShell'; import { MobileCard, CTAButton, SkeletonCard } from './components/Primitives'; import { getEventAnalytics, EventAnalytics } from '../api'; import { ApiError } from '../lib/apiError'; import { useAdminTheme } from './theme'; import { adminPath } from '../constants'; import { useEventContext } from '../context/EventContext'; export default function MobileEventAnalyticsPage() { const { slug } = useParams<{ slug: string }>(); const { t, i18n } = useTranslation('management'); const navigate = useNavigate(); const { activeEvent } = useEventContext(); const { textStrong, muted, border, surface, primary, accentSoft } = useAdminTheme(); const dateLocale = i18n.language.startsWith('de') ? de : enGB; const { data, isLoading, error } = useQuery({ queryKey: ['event-analytics', slug], queryFn: () => getEventAnalytics(slug!), enabled: Boolean(slug), retry: false, // Don't retry if 403 }); const isFeatureLocked = error?.status === 403 || error?.code === 'feature_locked'; if (isFeatureLocked) { return ( {t('analytics.lockedTitle', 'Unlock Analytics')} {t('analytics.lockedBody', 'Get deep insights into your event engagement with the Premium package.')} navigate(adminPath('/mobile/billing/shop'))} /> ); } if (isLoading) { return ( ); } if (error || !data) { return ( {t('common.error', 'Something went wrong')} ); } const { timeline, contributors, tasks } = data; const hasTimeline = timeline.length > 0; const hasContributors = contributors.length > 0; const hasTasks = tasks.length > 0; // Prepare chart data const maxCount = Math.max(...timeline.map((p) => p.count), 1); return ( {/* Activity Timeline */} {t('analytics.activityTitle', 'Activity Timeline')} {hasTimeline ? ( {timeline.map((point, index) => { const heightPercent = (point.count / maxCount) * 100; const date = parseISO(point.timestamp); // Show label every 3rd point or if few points const showLabel = timeline.length < 8 || index % 3 === 0; return ( {showLabel && ( {format(date, 'HH:mm')} )} ); })} {t('analytics.uploadsPerHour', 'Uploads per hour')} ) : ( )} {/* Top Contributors */} {t('analytics.contributorsTitle', 'Top Contributors')} {hasContributors ? ( {contributors.map((contributor, idx) => ( {idx + 1} {contributor.name || t('common.anonymous', 'Anonymous')} {t('analytics.likesCount', { count: contributor.likes, defaultValue: '{{count}} likes' })} {contributor.count} ))} ) : ( )} {/* Task Stats */} {t('analytics.tasksTitle', 'Popular Tasks')} {hasTasks ? ( {tasks.map((task) => { const maxTaskCount = Math.max(...tasks.map(t => t.count), 1); const percent = (task.count / maxTaskCount) * 100; return ( {task.task_name} {task.count} ); })} ) : ( )} ); } function EmptyState({ message }: { message: string }) { const { muted } = useAdminTheme(); return ( {message} ); }