"use client"; import React from "react"; import Link from "next/link"; import { Plus, FlaskConical } from "lucide-react"; import { Button } from "~/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "~/components/ui/card"; import { PageHeader, ActionButton } from "~/components/ui/page-header"; import { useBreadcrumbsEffect } from "~/components/ui/breadcrumb-provider"; import { useStudyManagement } from "~/hooks/useStudyManagement"; import { StudyCard } from "./StudyCard"; import { api } from "~/trpc/react"; type StudyWithRelations = { id: string; name: string; description: string | null; status: "draft" | "active" | "completed" | "archived"; createdAt: Date; updatedAt: Date; institution: string | null; irbProtocol: string | null; createdBy: string; members?: Array<{ id: string; role: "owner" | "researcher" | "wizard" | "observer"; user: { id: string; name: string | null; email: string; }; }>; experiments?: Array<{ id: string; name: string; }>; trials?: Array<{ id: string; name: string; }>; participants?: Array<{ id: string; name: string; }>; _count?: { experiments: number; trials: number; studyMembers: number; participants: number; }; }; type ProcessedStudy = { id: string; name: string; description: string | null; status: "draft" | "active" | "completed" | "archived"; createdAt: Date; updatedAt: Date; institution: string | null; irbProtocolNumber?: string; ownerId?: string; owner: { name: string | null; email: string; }; _count?: { experiments: number; trials: number; studyMembers: number; participants: number; }; userRole?: "owner" | "researcher" | "wizard" | "observer"; isOwner?: boolean; }; // Process studies helper function const processStudies = ( rawStudies: StudyWithRelations[], currentUserId?: string, ): ProcessedStudy[] => { return rawStudies.map((study) => { // Find current user's membership const userMembership = study.members?.find( (member) => member.user.id === currentUserId, ); // Find owner from members const owner = study.members?.find((member) => member.role === "owner"); return { id: study.id, name: study.name, description: study.description, status: study.status, createdAt: study.createdAt, updatedAt: study.updatedAt, institution: study.institution, irbProtocolNumber: study.irbProtocol ?? undefined, ownerId: owner?.user.id, owner: { name: owner?.user.name ?? null, email: owner?.user.email ?? "", }, _count: { experiments: study._count?.experiments ?? study.experiments?.length ?? 0, trials: study._count?.trials ?? study.trials?.length ?? 0, studyMembers: study._count?.studyMembers ?? study.members?.length ?? 0, participants: study._count?.participants ?? study.participants?.length ?? 0, }, userRole: userMembership?.role, isOwner: userMembership?.role === "owner", }; }); }; export function StudiesGrid() { const { data: session } = api.auth.me.useQuery(); const { userStudies, isLoadingUserStudies, refreshStudyData } = useStudyManagement(); // Auto-refresh studies when component mounts to catch external changes React.useEffect(() => { const interval = setInterval(() => { void refreshStudyData(); }, 30000); // Refresh every 30 seconds return () => clearInterval(interval); }, [refreshStudyData]); // Set breadcrumbs useBreadcrumbsEffect([ { label: "Dashboard", href: "/dashboard" }, { label: "Studies" }, ]); // Process studies data const studies = userStudies ? processStudies(userStudies, session?.id) : []; const isLoading = isLoadingUserStudies; if (isLoading) { return (
Get started by creating your first Human-Robot Interaction research study. Studies help you organize experiments, manage participants, and collaborate with your team.