feat: introduce conditional steps and branching logic to the experiment wizard and designer, along with new core and WoZ plugins.

This commit is contained in:
2026-02-10 10:24:09 -05:00
parent 388897c70e
commit 0f535f6887
38 changed files with 2410 additions and 1190 deletions

View File

@@ -222,7 +222,10 @@ export default async function ExperimentDesignerPage({
: "sequential";
})(),
order: s.orderIndex ?? idx,
trigger: { type: "trial_start", conditions: {} },
trigger: {
type: idx === 0 ? "trial_start" : "previous_step",
conditions: (s.conditions as Record<string, unknown>) || {},
},
actions,
expanded: true,
};

View File

@@ -171,10 +171,27 @@ function WizardPageContent() {
const renderView = () => {
const trialData = {
...trial,
id: trial.id,
status: trial.status,
scheduledAt: trial.scheduledAt,
startedAt: trial.startedAt,
completedAt: trial.completedAt,
duration: trial.duration,
sessionNumber: trial.sessionNumber,
notes: trial.notes,
metadata: trial.metadata as Record<string, unknown> | null,
experimentId: trial.experimentId,
participantId: trial.participantId,
wizardId: trial.wizardId,
experiment: {
id: trial.experiment.id,
name: trial.experiment.name,
description: trial.experiment.description,
studyId: trial.experiment.studyId,
},
participant: {
...trial.participant,
id: trial.participant.id,
participantCode: trial.participant.participantCode,
demographics: trial.participant.demographics as Record<
string,
unknown
@@ -184,7 +201,7 @@ function WizardPageContent() {
switch (currentRole) {
case "wizard":
return <WizardView trial={trialData} />;
return <WizardView trial={trialData} userRole={currentRole} />;
case "observer":
return <ObserverView trial={trialData} />;
case "participant":
@@ -195,24 +212,8 @@ function WizardPageContent() {
};
return (
<div className="flex h-full flex-col">
<PageHeader
title={getViewTitle(currentRole)}
description={`Session ${trial.sessionNumber} • Participant ${trial.participant.participantCode}`}
icon={getViewIcon(currentRole)}
actions={
currentRole !== "participant" ? (
<Button asChild variant="outline">
<Link href={`/studies/${studyId}/trials/${trialId}`}>
<ArrowLeft className="mr-2 h-4 w-4" />
Back to Trial
</Link>
</Button>
) : null
}
/>
<div className="min-h-0 flex-1">{renderView()}</div>
<div>
{renderView()}
</div>
);
}