"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import Link from "next/link"; import { ArrowLeft, Calendar, Users, FlaskConical, Clock } from "lucide-react"; import { Button } from "~/components/ui/button"; import { Input } from "~/components/ui/input"; import { Label } from "~/components/ui/label"; import { Textarea } from "~/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "~/components/ui/select"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "~/components/ui/card"; import { Separator } from "~/components/ui/separator"; import { api } from "~/trpc/react"; const createTrialSchema = z.object({ experimentId: z.string().uuid("Please select an experiment"), participantId: z.string().uuid("Please select a participant"), scheduledAt: z.string().min(1, "Please select a date and time"), wizardId: z.string().uuid().optional(), notes: z.string().max(1000, "Notes cannot exceed 1000 characters").optional(), }); type CreateTrialFormData = z.infer; export default function NewTrialPage() { const router = useRouter(); const [isSubmitting, setIsSubmitting] = useState(false); const { register, handleSubmit, setValue, watch, formState: { errors }, } = useForm({ resolver: zodResolver(createTrialSchema), }); // Fetch available experiments const { data: experimentsData, isLoading: experimentsLoading } = api.experiments.getUserExperiments.useQuery( { page: 1, limit: 100 }, ); // Fetch available participants const { data: participantsData, isLoading: participantsLoading } = api.participants.list.useQuery( { page: 1, limit: 100 }, ); // Fetch potential wizards (users with wizard or researcher roles) const { data: wizardsData, isLoading: wizardsLoading } = api.users.getWizards.useQuery(); const createTrialMutation = api.trials.create.useMutation({ onSuccess: (trial) => { router.push(`/trials/${trial.id}`); }, onError: (error) => { console.error("Failed to create trial:", error); setIsSubmitting(false); }, }); const onSubmit = async (data: CreateTrialFormData) => { setIsSubmitting(true); try { await createTrialMutation.mutateAsync({ ...data, scheduledAt: new Date(data.scheduledAt), wizardId: data.wizardId || null, notes: data.notes || null, }); } catch (error) { // Error handling is done in the mutation's onError callback } }; const watchedExperimentId = watch("experimentId"); const watchedParticipantId = watch("participantId"); const watchedWizardId = watch("wizardId"); const selectedExperiment = experimentsData?.experiments?.find( exp => exp.id === watchedExperimentId ); const selectedParticipant = participantsData?.participants?.find( p => p.id === watchedParticipantId ); // Generate datetime-local input min value (current time) const now = new Date(); const minDateTime = new Date(now.getTime() - now.getTimezoneOffset() * 60000) .toISOString() .slice(0, 16); return (
{/* Header */}
Trials / Schedule New Trial

Schedule New Trial

Set up a research trial with a participant and experiment

{/* Main Form */}
Trial Details Configure the experiment, participant, and scheduling for this trial session.
{/* Experiment Selection */}
{errors.experimentId && (

{errors.experimentId.message}

)} {selectedExperiment && (

Study: {selectedExperiment.study.name}

{selectedExperiment.description}

{selectedExperiment.estimatedDuration && (

Estimated Duration: {selectedExperiment.estimatedDuration} minutes

)}
)}
{/* Participant Selection */}
{errors.participantId && (

{errors.participantId.message}

)} {selectedParticipant && (

Code: {selectedParticipant.participantCode}

{selectedParticipant.name && (

Name: {selectedParticipant.name}

)} {selectedParticipant.email && (

Email: {selectedParticipant.email}

)}
)}
{/* Scheduled Date & Time */}
{errors.scheduledAt && (

{errors.scheduledAt.message}

)}

Select when this trial session should take place

{/* Wizard Assignment */}

Assign a specific team member to operate the wizard interface

{/* Notes */}