Wire real CiviCRM DEV custom fields and dynamic option fetching

This commit is contained in:
Joel Brock
2026-05-09 20:42:35 -07:00
parent 54555c74d2
commit c58a49be6d
7 changed files with 663 additions and 213 deletions

View File

@@ -1,7 +1,7 @@
"use client";
import { useId, useState } from "react";
import type { StageSectionConfig } from "@/types/form";
import type { StageSectionConfig, SelectOption } from "@/types/form";
import type { UseFormRegister, FieldValues, FieldErrors } from "react-hook-form";
import { FieldRenderer } from "./fields/FieldRenderer";
import { evaluate } from "@/lib/conditional";
@@ -16,6 +16,8 @@ interface StageSectionProps {
isCurrent: boolean;
/** Whether the section starts open. */
defaultOpen: boolean;
/** Option groups fetched from CiviCRM, keyed by option_group_id. */
options: Record<number, SelectOption[]>;
}
/**
@@ -30,6 +32,7 @@ export function StageSection({
formValues,
isCurrent,
defaultOpen,
options,
}: StageSectionProps) {
const [open, setOpen] = useState(defaultOpen);
const headingId = useId();
@@ -89,19 +92,24 @@ export function StageSection({
<p className="text-sm italic text-stone-500">No fields are visible at this stage.</p>
) : (
<div className="grid grid-cols-1 gap-x-6 gap-y-5 md:grid-cols-2">
{visibleFields.map((f) => (
<div
key={f.name}
className={f.type === "textarea" || f.type === "boolean" ? "md:col-span-2" : ""}
>
<FieldRenderer
field={f}
register={register}
errors={errors}
readonlyValue={formValues[f.name]}
/>
</div>
))}
{visibleFields.map((f) => {
const resolvedOptions = f.optionGroupId ? options[f.optionGroupId] : undefined;
const wide =
f.type === "textarea" ||
f.type === "boolean" ||
f.type === "multiselect";
return (
<div key={f.name} className={wide ? "md:col-span-2" : ""}>
<FieldRenderer
field={f}
register={register}
errors={errors}
readonlyValue={formValues[f.name]}
resolvedOptions={resolvedOptions}
/>
</div>
);
})}
</div>
)}
</div>