"use client"; import * as React from "react"; import Link from "next/link"; import { format } from "date-fns"; import { formatDistanceToNow } from "date-fns"; import { Activity, ArrowRight, Calendar, CheckCircle, CheckCircle2, Clock, FlaskConical, HelpCircle, LayoutDashboard, MoreHorizontal, Play, PlayCircle, Plus, Search, Settings, Users, Radio, Gamepad2, AlertTriangle, Bot, User, MessageSquare, } from "lucide-react"; import { Button } from "~/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "~/components/ui/card"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "~/components/ui/dropdown-menu"; import { Progress } from "~/components/ui/progress"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "~/components/ui/select"; import { Badge } from "~/components/ui/badge"; import { ScrollArea } from "~/components/ui/scroll-area"; import { api } from "~/trpc/react"; import { useTour } from "~/components/onboarding/TourProvider"; import { useSession } from "next-auth/react"; export default function DashboardPage() { const { startTour } = useTour(); const { data: session } = useSession(); const [studyFilter, setStudyFilter] = React.useState(null); // --- Data Fetching --- const { data: userStudiesData } = api.studies.list.useQuery({ memberOnly: true, limit: 100, }); const userStudies = userStudiesData?.studies ?? []; const { data: stats } = api.dashboard.getStats.useQuery({ studyId: studyFilter ?? undefined, }); const { data: liveTrials } = api.dashboard.getLiveTrials.useQuery( { studyId: studyFilter ?? undefined }, { refetchInterval: 5000 }, ); const { data: recentActivity } = api.dashboard.getRecentActivity.useQuery({ limit: 15, studyId: studyFilter ?? undefined, }); const { data: studyProgress } = api.dashboard.getStudyProgress.useQuery({ limit: 5, studyId: studyFilter ?? undefined, }); const userName = session?.user?.name ?? "Researcher"; const getWelcomeMessage = () => { const hour = new Date().getHours(); let greeting = "Good evening"; if (hour < 12) greeting = "Good morning"; else if (hour < 18) greeting = "Good afternoon"; return `${greeting}, ${userName.split(" ")[0]}`; }; return (
{/* Header Section */}

{getWelcomeMessage()}

Here's what's happening with your research today.

{/* Main Stats Grid */}
{/* Action Center & Recent Activity */}
{/* Quick Actions Card */} Quick Actions Common tasks to get you started {/* Recent Activity Card */} Recent Activity Your latest interactions across the platform
{recentActivity?.map((activity) => { let eventColor = "bg-primary/30 ring-background"; let Icon = Activity; if (activity.type === "trial_started") { eventColor = "bg-blue-500 ring-blue-100 dark:ring-blue-900"; Icon = PlayCircle; } else if (activity.type === "trial_completed") { eventColor = "bg-green-500 ring-green-100 dark:ring-green-900"; Icon = CheckCircle; } else if (activity.type === "error") { eventColor = "bg-red-500 ring-red-100 dark:ring-red-900"; Icon = AlertTriangle; } else if (activity.type === "intervention") { eventColor = "bg-orange-500 ring-orange-100 dark:ring-orange-900"; Icon = Gamepad2; } else if (activity.type === "annotation") { eventColor = "bg-yellow-500 ring-yellow-100 dark:ring-yellow-900"; Icon = MessageSquare; } return (
{activity.title}
{activity.description}
{formatDistanceToNow(new Date(activity.time), { addSuffix: true, })}
); })} {!recentActivity?.length && (

No recent activity recorded.

Start a trial to see experiment events stream here.

)}
{/* Live Trials */} 0 ? "border-primary bg-primary/5 shadow-sm" : "border-muted/40"} col-span-4 transition-colors duration-500`} >
Live Sessions {liveTrials && liveTrials.length > 0 && ( )} Currently running trials in the Wizard interface
{!liveTrials?.length ? (

No trials are currently running.

) : (
{liveTrials.map((trial) => (

{trial.participantCode} • {trial.experimentName}

Started{" "} {trial.startedAt ? formatDistanceToNow(new Date(trial.startedAt), { addSuffix: true, }) : "just now"}
))}
)}
{/* Study Progress */} Study Progress Completion tracking for active studies {studyProgress?.map((study) => (
{study.name}
{study.participants} / {study.totalParticipants}{" "} Participants
))} {!studyProgress?.length && (

No active studies to track.

)}
); } function StatsCard({ title, value, icon: Icon, description, trend, iconColor, }: { title: string; value: string | number; icon: React.ElementType; description: string; trend?: string; iconColor?: string; }) { return ( {title}
{value}

{description} {trend && ( {trend} )}

); }