mirror of
https://github.com/soconnor0919/hristudio.git
synced 2025-12-11 14:44:44 -05:00
- Upgrade Next.js to version 15.1.7 - Update Drizzle ORM and related dependencies - Add Nodemailer and related type definitions - Refactor authentication routes and components - Modify user schema to include first and last name - Update authentication configuration and session handling - Remove deprecated login and register pages - Restructure authentication-related components and routes
102 lines
3.1 KiB
TypeScript
102 lines
3.1 KiB
TypeScript
"use client";
|
|
|
|
import { useRouter } from "next/navigation";
|
|
import { api } from "~/trpc/react";
|
|
import { PageHeader } from "~/components/layout/page-header";
|
|
import { PageContent } from "~/components/layout/page-content";
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/components/ui/card";
|
|
import { ParticipantForm, type ParticipantFormValues } from "~/components/participants/participant-form";
|
|
import { use } from "react";
|
|
import { useToast } from "~/hooks/use-toast";
|
|
import { ROLES } from "~/lib/permissions/constants";
|
|
|
|
function generateIdentifier(studyId: number, count: number) {
|
|
// Format: P001, P002, etc. with study prefix
|
|
const paddedCount = String(count + 1).padStart(3, '0');
|
|
return `P${paddedCount}`;
|
|
}
|
|
|
|
export default function NewParticipantPage({ params }: { params: Promise<{ id: string }> }) {
|
|
const router = useRouter();
|
|
const { toast } = useToast();
|
|
const resolvedParams = use(params);
|
|
const studyId = Number(resolvedParams.id);
|
|
|
|
const { data: study } = api.study.getById.useQuery({ id: studyId });
|
|
const { data: participantCount = 0 } = api.participant.getCount.useQuery(
|
|
{ studyId },
|
|
{ enabled: !!study }
|
|
);
|
|
|
|
const { mutate: createParticipant, isPending: isCreating } = api.participant.create.useMutation({
|
|
onSuccess: () => {
|
|
toast({
|
|
title: "Success",
|
|
description: "Participant added successfully",
|
|
});
|
|
router.push(`/dashboard/studies/${studyId}/participants`);
|
|
router.refresh();
|
|
},
|
|
onError: (error) => {
|
|
toast({
|
|
title: "Error",
|
|
description: error.message,
|
|
variant: "destructive",
|
|
});
|
|
},
|
|
});
|
|
|
|
function onSubmit(data: ParticipantFormValues) {
|
|
createParticipant({
|
|
studyId,
|
|
...data,
|
|
});
|
|
}
|
|
|
|
if (!study) {
|
|
return <div>Study not found</div>;
|
|
}
|
|
|
|
// Check if user has permission to add participants
|
|
const canAddParticipants = [ROLES.OWNER, ROLES.ADMIN, ROLES.PRINCIPAL_INVESTIGATOR]
|
|
.map(r => r.toLowerCase())
|
|
.includes(study.role.toLowerCase());
|
|
|
|
if (!canAddParticipants) {
|
|
return <div>You do not have permission to add participants to this study.</div>;
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<PageHeader
|
|
title="Add Participant"
|
|
description={`Add a new participant to ${study.title}`}
|
|
/>
|
|
<PageContent>
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Participant Details</CardTitle>
|
|
<CardDescription>
|
|
Enter the participant's information. Fields marked with * are required.
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<ParticipantForm
|
|
defaultValues={{
|
|
identifier: generateIdentifier(studyId, participantCount),
|
|
email: "",
|
|
firstName: "",
|
|
lastName: "",
|
|
notes: "",
|
|
status: "active",
|
|
}}
|
|
onSubmit={onSubmit}
|
|
isSubmitting={isCreating}
|
|
submitLabel="Add Participant"
|
|
/>
|
|
</CardContent>
|
|
</Card>
|
|
</PageContent>
|
|
</>
|
|
);
|
|
}
|