Skip to content

feat: Add/Edit Family tool + Google Places provider#10

Merged
chriskehayias merged 2 commits into
mainfrom
feat/add-edit-family-tool
May 20, 2026
Merged

feat: Add/Edit Family tool + Google Places provider#10
chriskehayias merged 2 commits into
mainfrom
feat/add-edit-family-tool

Conversation

@chriskehayias
Copy link
Copy Markdown
Contributor

Summary

  • New Add/Edit Family tool at /tools/addeditfamily modeled on MP's cloud Add/Edit Family but built on this project's MP REST + service pattern. Search, edit, or create households end-to-end (household + main/alt addresses + members + donor + envelope).
  • New Google Places provider/service that any tool can consume. Server-side only — API key never reaches the browser. Wired into the family tool's Address Line 1 with a graceful plain-input fallback when no key is configured.

What landed

Tool (commit 281c7ee)

  • DTOs, Zod schemas, FamilyService singleton, server actions, full UI
  • recordID resolution honors pageData.Contact_ID_Field so the tool works from any MP page whose metadata exposes the path back to a Contact_ID
  • Save flow tracks per-step progress and patches local state with real IDs even on partial failure, so a retry after an error doesn't duplicate
  • Envelope assignment is race-hardened: on save, re-checks Donors.Envelope_No uniqueness and bumps to MAX+1 if taken (up to 5 attempts); the bumped number is surfaced back to the UI via a warning toast
  • Donor checkbox is locked (with explanatory tooltip) once a Donor record exists; envelope # remains editable
  • Dirty-check on Close via AlertDialog; save → reload + sonner toast; no navigation away after save
  • Lookups wired through DTO/service/UI: Congregations, Sources, Household Positions, Participant Types, Marital Statuses, Prefixes, Suffixes, Genders, Contact Statuses, Primary Languages, Faith Backgrounds, Countries (+ hard-coded US States, since MP has no States table)

Google Places provider (commit 0dba1d5)

  • GooglePlacesProvider wraps Places API v1 REST endpoints with session-token billing
  • GooglePlacesService singleton, .isEnabled() for graceful degradation
  • .env.example notes the key, which API to enable, and the IP/service restriction guidance (calls are server-side, not referrer-bound)

Test plan

  • Search "Kehayias" → load household, see all members, address, dropdowns populate
  • Toggle Alt Address tab → Season Start/End/Repeats Annually visible
  • Expand More on a member → Prefix, Nickname, DOB, Contact Status, Primary Language, Faith Background, Donor toggle all rendered and populated
  • Create a new family via search → "+ New Family" → fill First Name → Save → toast + form reloads with persisted data
  • Edit existing family → make a change → Close without saving → confirm prompt appears
  • Toggle Donor on a new member → Assign Next Envelope # → number populates → save → reload shows envelope persisted
  • Donor on an existing donor record → checkbox is disabled with tooltip
  • Add GOOGLE_PLACES_API_KEY to .env.local, restart dev server → Address Line 1 becomes a typeahead; selecting a result populates Line 1/City/State/Zip/Country

🤖 Generated with Claude Code

chriskehayias and others added 2 commits May 20, 2026 09:43
Adds a reusable Google Places integration following the existing
provider/service pattern (mirrors MP). All calls run on the server so
the API key never leaves the host.

Provider (src/lib/providers/google-places/)
  - GooglePlacesProvider class wrapping the Places API v1 REST endpoints
    (places:autocomplete, places/{id})
  - Uses session tokens per autocomplete -> details cycle so Google bills
    a single suggestion-session instead of per-keystroke
  - X-Goog-FieldMask trims response payloads to only what the client uses

Service (src/services/googlePlacesService.ts)
  - Singleton matching the existing service pattern
  - isEnabled() returns true only when GOOGLE_PLACES_API_KEY is set; the
    consumer should fall back gracefully when missing
  - Lazy provider instantiation on first call

Config
  - Adds GOOGLE_PLACES_API_KEY to .env.example with notes on which API
    to enable (Places API New / v1) and that keys should be restricted
    by IP/service rather than HTTP referrer since calls are server-side

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A new tool for creating and editing MP households end-to-end: search
existing families, edit household + members + addresses, or start fresh
from the search bar. Modeled on MP's own cloud Add/Edit Family but built
on this project's MP REST + service pattern.

DTOs (src/lib/dto/family.ts)
  - Household, FamilyMember, FamilyAddress + Zod schemas
  - SaveProgress / SavedMemberId for partial-failure tracking
  - emptyHousehold/emptyMember factories with defaults seeded

Service (src/services/familyService.ts)
  - Singleton matching the existing service pattern
  - searchContacts: typeahead against Contacts joined to household address
  - getHousehold: single round-trip with FK-joined main + alt address
    columns and member rows (Participant_Record + Donor_Record joined for
    Participant_Type_ID and Envelope_No)
  - resolveContactIdFromPage: honors ToolParams.pageData.Contact_ID_Field
    so the tool works from any MP page whose metadata exposes the path
    back to a Contact_ID (donors, participants, custom pages, etc.)
  - getLookups: parallel fetch of every dropdown (congregations, sources,
    household positions, participant types, marital statuses, prefixes,
    suffixes, genders, contact statuses, primary languages, faith
    backgrounds, countries) + a hard-coded US states list (MP has no
    States table; MP's cloud tool also ships its own)
  - getNextEnvelopeNumber: MAX(Envelope_No) + 1 against Donors
  - saveHousehold: progress-aware multi-step upsert with race-hardened
    envelope assignment. Throws PartialSaveError carrying the progress
    so the UI can patch local state with real IDs even on partial failure
    -- retries don't duplicate

Server actions (src/app/(web)/tools/addeditfamily/actions.ts)
  - Thin wrappers around the service with auth gating and unified
    ActionError shape that includes optional progress for the partial-
    failure path
  - placesEnabled/placeAutocomplete/placeDetails for Google Places

UI (src/app/(web)/tools/addeditfamily/add-edit-family.tsx)
  - Single screen: search bar, household panel, address tabs (main/alt
    with season fields), member cards (compact + More toggle), Add Member
    button, Save/Close in ToolContainer footer
  - Donor toggle locks (with tooltip) when a Donor record exists; envelope
    # appears when Donor is on, with an "Assign Next Envelope #" button
    that fetches MAX+1 from the server
  - AddressLine1Autocomplete (Google Places) auto-enables when the key
    is configured server-side; falls back to a plain Input otherwise
  - Dirty-check on Close: snapshot the household on load/save, compare
    via JSON equality, show an AlertDialog before discarding
  - Save flow: applies progress (real contact/participant/donor/address
    IDs replace temp negatives) on both success and partial failure;
    re-loads from MP after success to show the normalized server view;
    surface errors via sonner toast. Envelope bumps from the race-
    hardening loop emit a separate warning toast naming the new number

Page wiring (src/app/(web)/tools/addeditfamily/page.tsx)
  - Resolves recordID -> Contact_ID server-side using pageData metadata
    so launching the tool from a non-Households page lands on the right
    family without a round-trip

Homepage
  - Adds an Add/Edit Family card to src/app/(web)/page.tsx

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@chriskehayias chriskehayias merged commit 17b94d7 into main May 20, 2026
1 check passed
@chriskehayias chriskehayias deleted the feat/add-edit-family-tool branch May 20, 2026 13:55
@codecov
Copy link
Copy Markdown

codecov Bot commented May 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant