diff --git a/src/app/(dashboard)/profile/page.tsx b/src/app/(dashboard)/profile/page.tsx
index 97a47ae..b562a4c 100755
--- a/src/app/(dashboard)/profile/page.tsx
+++ b/src/app/(dashboard)/profile/page.tsx
@@ -19,6 +19,10 @@ import {
Loader2,
Save,
X,
+ Crown,
+ FlaskConical,
+ Eye,
+ UserCheck,
} from "lucide-react";
import { Button } from "~/components/ui/button";
@@ -43,6 +47,17 @@ import {
DialogTrigger,
} from "~/components/ui/dialog";
+interface Membership {
+ studyId: string;
+ role: string;
+ joinedAt: Date;
+}
+
+function getMemberRole(memberships: Membership[], studyId: string): string {
+ const membership = memberships.find((m) => m.studyId === studyId);
+ return membership?.role ?? "observer";
+}
+
function ProfilePageContent() {
const { data: session } = useSession();
const utils = api.useUtils();
@@ -59,6 +74,15 @@ function ProfilePageContent() {
{ enabled: !!session?.user?.id },
);
+ const { data: userStudies } = api.studies.list.useQuery({
+ memberOnly: true,
+ limit: 10,
+ });
+
+ const { data: membershipsData } = api.studies.getMyMemberships.useQuery();
+
+ const studyMemberships = membershipsData ?? [];
+
const updateProfile = api.users.update.useMutation({
onSuccess: () => {
toast.success("Profile updated successfully");
@@ -341,16 +365,45 @@ function ProfilePageContent() {
Studies you have access to
-
-
-
-
View your studies
-
+ )}
diff --git a/src/app/(dashboard)/studies/[id]/experiments/page.tsx b/src/app/(dashboard)/studies/[id]/experiments/page.tsx
index f6faf49..02e6859 100755
--- a/src/app/(dashboard)/studies/[id]/experiments/page.tsx
+++ b/src/app/(dashboard)/studies/[id]/experiments/page.tsx
@@ -31,6 +31,8 @@ export default function StudyExperimentsPage() {
}
}, [studyId, selectedStudyId, setSelectedStudyId]);
+ const canManage = study?.userRole === "owner" || study?.userRole === "researcher";
+
return (
-
-
- Create Experiment
-
-
+ canManage ? (
+
+
+
+ Create Experiment
+
+
+ ) : null
}
/>
diff --git a/src/app/(dashboard)/studies/[id]/page.tsx b/src/app/(dashboard)/studies/[id]/page.tsx
index 452a4f7..922749d 100755
--- a/src/app/(dashboard)/studies/[id]/page.tsx
+++ b/src/app/(dashboard)/studies/[id]/page.tsx
@@ -60,6 +60,7 @@ type Study = {
irbProtocol: string | null;
createdAt: Date;
updatedAt: Date;
+ userRole?: string;
};
type Member = {
@@ -157,6 +158,10 @@ export default function StudyDetailPage({ params }: StudyDetailPageProps) {
).length;
const totalTrials = trials.length;
+ const userRole = (studyData as any)?.userRole;
+ const canManage = userRole === "owner" || userRole === "researcher";
+ const canRunTrials = userRole === "owner" || userRole === "researcher" || userRole === "wizard";
+
const stats = {
experiments: experiments.length,
totalTrials: totalTrials,
@@ -182,18 +187,22 @@ export default function StudyDetailPage({ params }: StudyDetailPageProps) {
]}
actions={
-
-
-
- Edit Study
-
-
-
-
-
- New Experiment
-
-
+ {canManage && (
+
+
+
+ Edit Study
+
+
+ )}
+ {canManage && (
+
+
+
+ New Experiment
+
+
+ )}
}
/>
@@ -235,12 +244,14 @@ export default function StudyDetailPage({ params }: StudyDetailPageProps) {
icon="FlaskConical"
description="Design and manage experimental protocols for this study"
actions={
-
-
-
- Add Experiment
-
-
+ canManage ? (
+
+
+
+ Add Experiment
+
+
+ ) : null
}
>
{experiments.length === 0 ? (
@@ -392,12 +403,14 @@ export default function StudyDetailPage({ params }: StudyDetailPageProps) {
icon="Users"
description={`${members.length} team member${members.length !== 1 ? "s" : ""}`}
actions={
-
-
-
- Manage
-
-
+ canManage ? (
+
+
+
+ Manage
+
+
+ ) : null
}
>
diff --git a/src/app/(dashboard)/studies/[id]/participants/page.tsx b/src/app/(dashboard)/studies/[id]/participants/page.tsx
index 41b1e7a..4b5c507 100755
--- a/src/app/(dashboard)/studies/[id]/participants/page.tsx
+++ b/src/app/(dashboard)/studies/[id]/participants/page.tsx
@@ -31,6 +31,8 @@ export default function StudyParticipantsPage() {
}
}, [studyId, selectedStudyId, setSelectedStudyId]);
+ const canManage = study?.userRole === "owner" || study?.userRole === "researcher";
+
return (
-
-
- Add Participant
-
-
+ canManage ? (
+
+
+
+ Add Participant
+
+
+ ) : null
}
/>
diff --git a/src/app/(dashboard)/studies/[id]/trials/page.tsx b/src/app/(dashboard)/studies/[id]/trials/page.tsx
index 3a3b112..7f98900 100755
--- a/src/app/(dashboard)/studies/[id]/trials/page.tsx
+++ b/src/app/(dashboard)/studies/[id]/trials/page.tsx
@@ -32,6 +32,8 @@ export default function StudyTrialsPage() {
}
}, [studyId, selectedStudyId, setSelectedStudyId]);
+ const canRun = ["owner", "researcher", "wizard"].includes(study?.userRole ?? "");
+
return (
-
-
- Schedule Trial
-
-
+ canRun ? (
+
+
+
+ Schedule Trial
+
+
+ ) : null
}
/>
diff --git a/src/server/api/routers/studies.ts b/src/server/api/routers/studies.ts
index aa04177..6881c6d 100755
--- a/src/server/api/routers/studies.ts
+++ b/src/server/api/routers/studies.ts
@@ -1001,4 +1001,20 @@ export const studiesRouter = createTRPCRouter({
return updatedPlugin;
}),
+
+ getMyMemberships: protectedProcedure.query(async ({ ctx }) => {
+ const userId = ctx.session.user.id;
+
+ const memberships = await ctx.db.query.studyMembers.findMany({
+ where: eq(studyMembers.userId, userId),
+ columns: {
+ studyId: true,
+ role: true,
+ joinedAt: true,
+ },
+ orderBy: [desc(studyMembers.joinedAt)],
+ });
+
+ return memberships;
+ }),
});