Form: required submitter info section above the stage pathway
Captures the form-filler's name and email on every check-in. Both fields are required; values write back to Check_in_data__organizing_.Survey_completed_by and Survey_completed_by_email on the activity, giving us a per-submission record of who filled out which check-in. Implementation: - config/form.ts: new submitterInfo section (rank -1) at the head of the sections array. rank -1 keeps it out of the past/current/future stage pathway computation. - components/EngagementForm.tsx: filter the submitter section out of sectionsToRender and render it directly with FieldRenderer inside a bordered card above the stage list. The fields still flow through RHF registration, onInvalid scroll-to-error, and the onSubmit visibility filter the same as any other field. The staff report auto-discovers these fields via CustomField.get since they live in Check_in_data__organizing_, so the field history shows up in the report with no extra wiring.
This commit is contained in:
@@ -19,6 +19,7 @@ function sectionForField(
|
||||
import { evaluate } from "@/lib/conditional";
|
||||
import { STAGE_OPTION_GROUP_ID } from "@/config/form";
|
||||
import { StageSection } from "./StageSection";
|
||||
import { FieldRenderer } from "./fields/FieldRenderer";
|
||||
import { loadDraft, saveDraft, clearDraft } from "@/lib/draft";
|
||||
|
||||
interface EngagementFormProps {
|
||||
@@ -241,6 +242,26 @@ export function EngagementForm({ config, cid, cs }: EngagementFormProps) {
|
||||
|
||||
const currentRank = currentStageValue ? STAGE_RANK[currentStageValue] ?? 0 : 0;
|
||||
|
||||
// Section pathway state — past / current / future is determined entirely
|
||||
// by stage rank vs the org's current rank. Sections never hide; future
|
||||
// stages render in a locked treatment so users can preview what's ahead.
|
||||
//
|
||||
// Section-level visibleWhen is still consulted on submit to strip
|
||||
// locked-stage values from the payload (see onSubmit below), so a future
|
||||
// stage's data never gets accidentally written.
|
||||
// The submitter-info section (rank: -1) lives outside the stage pathway —
|
||||
// it renders directly above the section list (see JSX below), not inside
|
||||
// the rail/marker accordion model used for Stage 0..5. Filter it out here
|
||||
// so its rank doesn't pollute the past/current/future calculation.
|
||||
const submitterSection = useMemo(
|
||||
() => config.sections.find((s) => s.id === "submitter_info"),
|
||||
[config.sections],
|
||||
);
|
||||
const stageSections = useMemo(
|
||||
() => config.sections.filter((s) => s.id !== "submitter_info"),
|
||||
[config.sections],
|
||||
);
|
||||
|
||||
// Section pathway state — past / current / future is determined entirely
|
||||
// by stage rank vs the org's current rank. Sections never hide; future
|
||||
// stages render in a locked treatment so users can preview what's ahead.
|
||||
@@ -250,12 +271,12 @@ export function EngagementForm({ config, cid, cs }: EngagementFormProps) {
|
||||
// stage's data never gets accidentally written.
|
||||
const sectionsToRender = useMemo(
|
||||
() =>
|
||||
config.sections.map((s) => {
|
||||
stageSections.map((s) => {
|
||||
const pathwayState: PathwayState =
|
||||
s.rank < currentRank ? "past" : s.rank === currentRank ? "current" : "future";
|
||||
return { section: s, pathwayState, locked: pathwayState === "future" };
|
||||
}),
|
||||
[config.sections, currentRank],
|
||||
[stageSections, currentRank],
|
||||
);
|
||||
|
||||
// Track which sections the user has manually opened/closed so we can
|
||||
@@ -398,6 +419,38 @@ export function EngagementForm({ config, cid, cs }: EngagementFormProps) {
|
||||
}} />
|
||||
)}
|
||||
|
||||
{submitterSection && (
|
||||
<section
|
||||
aria-labelledby="submitter-info-heading"
|
||||
className="rounded-2xl border border-rule bg-paper p-4 sm:p-5"
|
||||
>
|
||||
<h2
|
||||
id="submitter-info-heading"
|
||||
className="font-display text-lg font-medium text-ink"
|
||||
>
|
||||
{submitterSection.label}
|
||||
</h2>
|
||||
{submitterSection.intro && (
|
||||
<p className="mt-1 text-sm text-ink-soft">{submitterSection.intro}</p>
|
||||
)}
|
||||
<div className="mt-3 grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
{submitterSection.fields.map((f) => (
|
||||
<FieldRenderer
|
||||
key={f.name}
|
||||
field={f}
|
||||
register={register}
|
||||
setValue={setValue}
|
||||
control={control}
|
||||
errors={errors}
|
||||
cid={cid}
|
||||
cs={cs}
|
||||
onUploadStateChange={handleUploadStateChange}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
<ol className="relative space-y-5 md:pl-12">
|
||||
{sectionsToRender.map((entry, i) => {
|
||||
const { section, pathwayState, locked } = entry;
|
||||
|
||||
Reference in New Issue
Block a user