Files
hristudio/src/app/(dashboard)/studies/[id]/participants/page.tsx
Sean O'Connor 67ad904f62 feat: add role-based permissions and profile page improvements
- Add getMyMemberships API endpoint for user role lookup
- Add getMemberRole helper for profile page display
- Add role-based UI controls to study page (owner/researcher only)
- Add canManage checks to experiments, participants, trials pages
- Hide management actions for wizard/observer roles

Backend already enforces permissions; UI now provides cleaner UX
2026-03-22 17:25:04 -04:00

60 lines
2.0 KiB
TypeScript
Executable File

"use client";
import { useParams } from "next/navigation";
import { Suspense, useEffect } from "react";
import { Users, Plus } from "lucide-react";
import { ParticipantsTable } from "~/components/participants/ParticipantsTable";
import { PageHeader } from "~/components/ui/page-header";
import { Button } from "~/components/ui/button";
import { useBreadcrumbsEffect } from "~/components/ui/breadcrumb-provider";
import { useStudyContext } from "~/lib/study-context";
import { useSelectedStudyDetails } from "~/hooks/useSelectedStudyDetails";
export default function StudyParticipantsPage() {
const params = useParams();
const studyId: string = typeof params.id === "string" ? params.id : "";
const { setSelectedStudyId, selectedStudyId } = useStudyContext();
const { study } = useSelectedStudyDetails();
// Set breadcrumbs
useBreadcrumbsEffect([
{ label: "Dashboard", href: "/dashboard" },
{ label: "Studies", href: "/studies" },
{ label: study?.name ?? "Study", href: `/studies/${studyId}` },
{ label: "Participants" },
]);
// Sync selected study (unified study-context)
useEffect(() => {
if (studyId && selectedStudyId !== studyId) {
setSelectedStudyId(studyId);
}
}, [studyId, selectedStudyId, setSelectedStudyId]);
const canManage = study?.userRole === "owner" || study?.userRole === "researcher";
return (
<div className="space-y-6">
<PageHeader
title="Participants"
description="Manage participant registration, consent, and trial assignments for this study"
icon={Users}
actions={
canManage ? (
<Button asChild>
<a href={`/studies/${studyId}/participants/new`}>
<Plus className="mr-2 h-4 w-4" />
Add Participant
</a>
</Button>
) : null
}
/>
<Suspense fallback={<div>Loading participants...</div>}>
<ParticipantsTable studyId={studyId} />
</Suspense>
</div>
);
}