14 Commits

Author SHA1 Message Date
Joel Brock
ba88eb0165 Add /report — read-only activity history view
Mirrors the form's IA and Field Almanac aesthetic; same auth (cid/cs
checksum) so the org owner who can fill the form can also view its
history.

New routes:
- GET /api/report — verifies checksum, resolves the org via the
  Primary Contact relationship, fires Contact.get + Activity.get +
  OptionValue.get in parallel. For every form field with a civiField,
  walks all the org's Check-in (organizing) activities and collects
  every non-empty value into a sorted-DESC history list. Returns
  ReportPayload (orgName, currentStage, activities, fieldHistory,
  options). Has stub-mode payload for env-less local dev.
- /report — page entry; same layout shell (SiteHeader + SiteFooter,
  3xl page width). Eyebrow "Activity report - Co-op organizing".

ReportView component:
- ReportContextHeader: large org name, progress dots + uppercase
  "Current stage" eyebrow + the Civi option *label* on its own line
  at display-font xl/2xl leaf-800 (matches the form's header). Below
  it a 3-up stat band: total check-ins, fields tracked, date span.
- One accordion card per stage section, in stage-rank order. Only
  sections that have at least one field-with-entries render — past,
  current, or "future-with-data" all welcome; truly empty stages stay
  hidden so the page is calm.
- Same journey rail (md+) and mobile stem (md-) with past =
  check-filled-leaf, current = filled-leaf-with-ring, future = dashed
  hollow ring; solid leaf line vs dashed muted between markers.
- Within each card: divide-y rows. Field label and help on the left,
  most-recent value on the right in display-font lg leaf-800, dated
  beneath with an "{N} earlier entries" disclosure that expands a
  small vertical timeline (date on left, value on right).
- FormattedValue handles currency (Intl), percent, number (tabular
  nums), date (long, timezone-safe for YYYY-MM-DD), boolean (Yes/No),
  select/readonly (resolved via option group), multiselect (handles
  array or delimited string), file (filename), text-like (as-is).
- Loading / empty / error states match the form's treatments.

types/form.ts: new FieldHistoryEntry, ActivitySummary, ReportPayload.
The fieldHistory map keys by FieldConfig.name and only includes fields
that have at least one non-empty entry.
2026-05-13 12:33:26 -07:00
Joel Brock
b4e80517a7 Derive current stage from most-recent stage-bearing activity
Stage authority moves from Organization.Food_Co_op_Organizing.Stage to the
most recent Check-in (organizing) activity whose Stage custom field is set.
Staff create these activities manually to mark transitions; org-owner form
submissions no longer write the Stage field at all, so they cannot override
a staff-set transition.

- /api/data: removed the Contact.get for org-side Stage; added an
  Activity.get filtered to ACTIVITY_TYPE_NAME + ACTIVITY_STAGE_FIELD IS
  NOT EMPTY, ordered by activity_date_time DESC, id DESC, limit 1.
  Fallback when no such activity exists: Inquiry (rank 0). Org-name
  lookup, stage activity, prefill, and option-group fetch all run in
  parallel via Promise.all.
- /api/submit: removed the stageAtSubmission read + the
  [ACTIVITY_STAGE_FIELD] write on the activity record. The form's
  activities are stage-null by design now.
- config/form.ts: dropped the stage_at_submission readonly field (no
  longer being set or displayed). Kept ACTIVITY_STAGE_FIELD export — it's
  now used by /api/data to find stage-bearing activities. Updated the
  current_stage field comment to reflect the new source.
- components/EngagementForm.tsx: dropped stage_at_submission from
  evalState (no longer referenced by any visibility rule or readonly
  display).

Org.Food_Co_op_Organizing.Stage remains in CiviCRM for staff list views;
the middleware no longer reads or writes it. No backfill required —
orgs without a stage-bearing activity simply read as Inquiry.
2026-05-13 11:41:25 -07:00
Joel Brock
e452fbb15f Email delivery: /api/preview-link admin endpoint + EMAIL_DELIVERY.md guide 2026-05-09 22:31:51 -07:00
Joel Brock
dcdf315244 Production hardening: CSP, rate limit, env validation, health gating, Render blueprint, DEPLOYMENT.md 2026-05-09 21:43:43 -07:00
Joel Brock
082238d884 Fix Activity.create payload: pass values as object not array 2026-05-09 21:15:56 -07:00
Joel Brock
1655c485d9 Fix APIv4 relationship_type_id join: use dot syntax not colon 2026-05-09 21:10:56 -07:00
Joel Brock
da830af533 Health probe: dump all relationships for a given contact, flag direction issues 2026-05-09 21:08:30 -07:00
Joel Brock
2e9d3855ba Use existing 'Primary Contact' relationship type via FORM_CONTACT_RELATIONSHIP constant 2026-05-09 20:57:29 -07:00
Joel Brock
e132789a3e Sharper health probes: resolve stage option group via CustomField metadata; list near-match relationship types 2026-05-09 20:52:06 -07:00
Joel Brock
82d7849a30 Support webserver-level HTTP Basic Auth in front of CiviCRM 2026-05-09 20:49:37 -07:00
Joel Brock
234bec5766 Add /api/health diagnostic route; remove stale .js route duplicates 2026-05-09 20:45:14 -07:00
Joel Brock
c58a49be6d Wire real CiviCRM DEV custom fields and dynamic option fetching 2026-05-09 20:42:35 -07:00
Joel Brock
54555c74d2 Build standalone CiviCRM check-in middleware 2026-05-09 20:08:15 -07:00
google-labs-jules[bot]
0899e6ae9a Implement CiviCRM middleware form with stage-based visibility
- Initialize Next.js project with Tailwind CSS
- Create CiviCRM APIv4 integration layer
- Implement stage-based form visibility (stages 0-5)
- Add field mapping configuration for CRM-to-form linking
- Create API routes for data retrieval and submission
- Record form submissions as CiviCRM activities
- Support dynamic contactId and orgId via URL parameters
- Ensure robust form state management with react-hook-form

Co-authored-by: joelbrock <52835+joelbrock@users.noreply.github.com>
2026-05-09 08:12:39 +00:00