import { createFileRoute } from '@tanstack/react-router' import { Title, Text, Card, Stack, Badge, Group, Loader, Center, SimpleGrid, ThemeIcon, } from '@pikku/mantine/core' import { MapPin, Clock, CheckSquare, Smile } from 'lucide-react' import { usePikkuQuery } from '@perauset/functions-sdk/pikku/api.gen' import { TaskActions } from '@/components/task-actions' import { m, mKey } from '@/i18n/messages' import { useLocale } from '@/i18n/config' import { asI18n, type I18nNode } from '@pikku/react' export const Route = createFileRoute('/_authenticated/my/tasks')({ component: MyTasksPage, }) const STATUS_CONFIG: Record = { in_progress: { labelKey: 'my.tasks_in_progress', color: 'orange' }, assigned: { labelKey: 'my.tasks_assigned', color: 'blue' }, open: { labelKey: 'my.tasks_open', color: 'teal' }, blocked: { labelKey: 'my.tasks_blocked', color: 'red' }, } const CATEGORY_COLORS: Record = { housekeeping: 'pink', kitchen: 'yellow', maintenance: 'orange', operations: 'blue', retreat: 'violet', transport: 'cyan', } const DISPLAY_STATUSES = ['in_progress', 'assigned', 'open', 'blocked'] interface TaskItem { taskId: string templateId: string | null title: string description: string | null category: string status: string location: string | null scheduledStartAt: string | Date | null scheduledEndAt: string | Date | null createdByUserId: string } function formatTime(val: string | Date | null): string | null { if (!val) return null const d = typeof val === 'string' ? new Date(val) : val return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit', }) } const cardStyle = { backgroundColor: '#ffffff', boxShadow: '0 2px 12px rgba(61, 43, 31, 0.08), 0 1px 4px rgba(61, 43, 31, 0.04)', maxWidth: 'calc(40rem * var(--mantine-scale))', } function TaskCard({ task }: { task: TaskItem }) { const cfg = STATUS_CONFIG[task.status] return ( {asI18n(task.title)} {cfg ? mKey(cfg.labelKey) : asI18n(task.status)} {asI18n(task.category)} {task.description && ( {asI18n(task.description)} )} {task.location && ( {asI18n(task.location)} )} {task.scheduledStartAt && ( {asI18n( `${formatTime(task.scheduledStartAt)}${ task.scheduledEndAt ? ` – ${formatTime(task.scheduledEndAt)}` : '' }`, )} )} ) } function EmptyState({ message }: { message: I18nNode }) { return ( {message} ) } function MyTasksPage() { useLocale() const { data, isLoading } = usePikkuQuery('listTasks', { limit: 50, offset: 0 }) const tasks = (data?.items ?? []) as TaskItem[] if (isLoading) { return (
) } const grouped: Record = {} for (const status of DISPLAY_STATUSES) { grouped[status] = [] } for (const task of tasks) { if (DISPLAY_STATUSES.includes(task.status)) { grouped[task.status]!.push(task) } } const hasActiveTasks = DISPLAY_STATUSES.some((s) => (grouped[s]?.length ?? 0) > 0) return (
{m.my_tasks_title()} {m.my_tasks_description()}
{!hasActiveTasks ? ( ) : ( DISPLAY_STATUSES.map((status) => { const items = grouped[status]! if (items.length === 0) return null const cfg = STATUS_CONFIG[status]! return (
{mKey(cfg.labelKey)} {items.length} {items.map((task) => ( ))}
) }) )}
) }