import React from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { YStack, XStack } from '@tamagui/stacks'; import { SizableText as Text } from '@tamagui/text'; import { Button } from '@tamagui/button'; import { Sparkles, ChevronLeft, Camera } from 'lucide-react'; import AppShell from '../components/AppShell'; import SurfaceCard from '../components/SurfaceCard'; import { fetchTasks, type TaskItem } from '../services/tasksApi'; import { useEventData } from '../context/EventDataContext'; import { buildEventPath } from '../lib/routes'; import { useTranslation } from '@/guest/i18n/useTranslation'; import { useGuestThemeVariant } from '../lib/guestTheme'; function getTaskValue(task: TaskItem, key: string): string | undefined { const value = task?.[key as keyof TaskItem]; if (typeof value === 'string' && value.trim() !== '') return value; if (value && typeof value === 'object') { const obj = value as Record; const candidate = Object.values(obj).find((item) => typeof item === 'string' && item.trim() !== ''); if (typeof candidate === 'string') return candidate; } return undefined; } function getTaskList(task: TaskItem, key: string): string[] { const value = task?.[key as keyof TaskItem]; if (Array.isArray(value)) { return value.filter((item) => typeof item === 'string' && item.trim() !== '') as string[]; } if (typeof value === 'string' && value.trim() !== '') { return [value]; } return []; } export default function TaskDetailScreen() { const { token, tasksEnabled } = useEventData(); const { taskId } = useParams<{ taskId: string }>(); const { t, locale } = useTranslation(); const navigate = useNavigate(); const { isDark } = useGuestThemeVariant(); const mutedText = isDark ? 'rgba(248, 250, 252, 0.7)' : 'rgba(15, 23, 42, 0.65)'; const [task, setTask] = React.useState(null); const [loading, setLoading] = React.useState(true); const [error, setError] = React.useState(null); if (!tasksEnabled) { return ( {t('tasks.disabled.title', 'Tasks are disabled')} {t('tasks.disabled.subtitle', 'This event is set to photo-only mode.')} ); } React.useEffect(() => { let active = true; if (!token || !taskId) { setLoading(false); setTask(null); return; } setLoading(true); setError(null); fetchTasks(token, { locale }) .then((tasks) => { if (!active) return; const match = tasks.find((item) => { const id = item?.id ?? item?.task_id ?? item?.slug; return String(id) === String(taskId); }) ?? null; setTask(match); setLoading(false); }) .catch((err) => { if (!active) return; setError(err instanceof Error ? err.message : t('tasks.error', 'Tasks could not be loaded.')); setLoading(false); }); return () => { active = false; }; }, [locale, taskId, t, token]); const title = task ? (getTaskValue(task, 'title') ?? getTaskValue(task, 'name') ?? 'Task') : 'Task'; const description = task ? (getTaskValue(task, 'description') ?? getTaskValue(task, 'prompt') ?? '') : ''; const tips = task ? getTaskList(task, 'tips') : []; const steps = task ? getTaskList(task, 'steps') : []; const inspiration = task ? getTaskList(task, 'inspiration') : []; const duration = task ? (task.duration ?? task.time_limit ?? null) : null; const groupSize = task ? (task.group_size ?? task.groupSize ?? null) : null; return ( {t('tasks.page.title', 'Your next task')} {t('tasks.page.subtitle', 'Choose a mood or get surprised.')} {loading ? ( {t('tasks.loading', 'Loading tasks...')} ) : error ? ( {t('tasks.page.emptyTitle', 'No matching task found')} {error} ) : task ? ( <> {title} {description ? ( {description} ) : null} {duration ? ( ) : null} {groupSize ? ( ) : null} {steps.length > 0 ? ( {t('tasks.page.checklist', 'Checklist')} {steps.map((step, index) => ( {index + 1}. {step} ))} ) : null} {tips.length > 0 ? ( {t('tasks.page.tips', 'Tips')} {tips.map((tip, index) => ( {tip} ))} ) : null} {inspiration.length > 0 ? ( {t('tasks.page.inspirationTitleSecondary', 'Inspiration')} {inspiration.map((item, index) => ( {item} ))} ) : null} ) : ( {t('tasks.page.emptyTitle', 'No matching task found')} )} ); }