FCI theming refresh, contact identity fields, Amplify secrets fix
- Remap globals.css tokens to FCI brand palette (Eggplant #801d7f, Spring Pea #96bc33, Seed Grant #679038, Squash #c9ad2d, FCI gray #4b5657). Existing leaf-* / clay-* class names preserved. - Switch body font to Open Sans (FCI's free fallback for Museo Sans). Headings keep Fraunces. - Add contact identity (first name, last name, email) as readonly fields at the top of Stage 0. /api/data fetches via APIv4 Contact.get with email_primary.email join; values flow through FormDataPayload.contact and into the form's evalState so the readonly renderer displays them. Draft restore re-applies them so a stale local draft can't override. - amplify.yml: fetch Amplify Secrets from SSM Parameter Store when they don't arrive as build-shell env vars (the common failure mode behind "Refusing to run in production without CIVI_*"). Adds a length-only diagnostic echo and a hard-fail guard so a missing required var stops the build with a clear message instead of bundling empty strings and crashing the SSR Lambda at runtime.
This commit is contained in:
@@ -76,13 +76,22 @@ export function EngagementForm({ config, cid, cs }: EngagementFormProps) {
|
||||
(useWatch({ control, name: "current_stage" }) as string | undefined) ?? "";
|
||||
|
||||
// State map passed to the conditional engine and to FieldRenderer for
|
||||
// readonly display values. Only fields referenced by visibility rules or
|
||||
// by readonly displays need to be here — currently just current_stage,
|
||||
// which gates every Stage 1–5 visibleWhen rule and is shown as a readonly
|
||||
// field in the Stage 0 header.
|
||||
// readonly display values. Includes:
|
||||
// - current_stage: gates every Stage 1–5 visibleWhen rule and renders
|
||||
// as a readonly field in Stage 0.
|
||||
// - contact_first_name / contact_last_name / contact_email: readonly
|
||||
// identity fields in Stage 0, sourced from /api/data (the cid contact).
|
||||
// Static after load, so we read straight from load.data.contact rather
|
||||
// than subscribing through react-hook-form.
|
||||
const readyContact = load.kind === "ready" ? load.data.contact : undefined;
|
||||
const evalState = useMemo(
|
||||
() => ({ current_stage: currentStageValue }),
|
||||
[currentStageValue],
|
||||
() => ({
|
||||
current_stage: currentStageValue,
|
||||
contact_first_name: readyContact?.firstName ?? "",
|
||||
contact_last_name: readyContact?.lastName ?? "",
|
||||
contact_email: readyContact?.email ?? "",
|
||||
}),
|
||||
[currentStageValue, readyContact],
|
||||
);
|
||||
|
||||
// ── Initial load ───────────────────────────────────────────────────────
|
||||
@@ -107,17 +116,28 @@ export function EngagementForm({ config, cid, cs }: EngagementFormProps) {
|
||||
const data: FormDataPayload = await res.json();
|
||||
if (cancelled) return;
|
||||
|
||||
// Build defaults: server prefill + current stage. Then check if a
|
||||
// local draft exists newer than the server data; if so, layer it on top.
|
||||
// Build defaults: server prefill + current stage + readonly contact
|
||||
// identity. Then check if a local draft exists newer than the server
|
||||
// data; if so, layer it on top. Contact-identity fields are never
|
||||
// user-editable, so a draft can't override them — they're force-set
|
||||
// again after the draft merge below.
|
||||
const contactDefaults: Record<string, unknown> = {
|
||||
contact_first_name: data.contact?.firstName ?? "",
|
||||
contact_last_name: data.contact?.lastName ?? "",
|
||||
contact_email: data.contact?.email ?? "",
|
||||
};
|
||||
const defaults: Record<string, unknown> = {
|
||||
[config.stageField]: data.currentStage,
|
||||
...contactDefaults,
|
||||
...data.prefill,
|
||||
};
|
||||
const draft = loadDraft(cid);
|
||||
if (draft && Object.keys(draft.values).length > 0) {
|
||||
Object.assign(defaults, draft.values);
|
||||
// Re-set the stage from server (draft can never override the org's actual stage).
|
||||
// Re-set the stage and contact identity from server (drafts can
|
||||
// never override the org's actual stage nor the cid's contact).
|
||||
defaults[config.stageField] = data.currentStage;
|
||||
Object.assign(defaults, contactDefaults);
|
||||
setDraftRestored(true);
|
||||
setDraftSavedAt(draft.savedAt);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user