From 13fb94fee99bef7175f9ebc706d05f8dd671a94e Mon Sep 17 00:00:00 2001 From: Randall Stillwell Date: Wed, 8 Apr 2026 20:22:36 -0500 Subject: [PATCH] Make survey fields editable and improve OCR option normalization - Replace read-only badge chips with toggleable multi-select chips for messageTopics, nextStep, campusPreference, and howHeard on card detail page - Add editable Switch toggles for all boolean fields (prayerForTeam, prayerConfidential, iSaidYesBookSent, ftGuestLetterSent) - Change edits state to Record to support array and boolean values alongside strings - Update OCR prompts to normalize visitType variations (e.g., "I am a first or second time guest at Echo Life" -> "First/Second Time Guest") - Update message topics list in OCR schema to match actual survey form options (Stress/Anxiety, Hearing God's Voice, Dealing With Doubt, etc.) Made-with: Cursor --- src/app/cards/[id]/page.tsx | 185 +++++++++++++++++++++++++----------- src/lib/ai-ocr.ts | 4 +- src/lib/ollama.ts | 4 +- 3 files changed, 133 insertions(+), 60 deletions(-) diff --git a/src/app/cards/[id]/page.tsx b/src/app/cards/[id]/page.tsx index be635b9..7b79189 100644 --- a/src/app/cards/[id]/page.tsx +++ b/src/app/cards/[id]/page.tsx @@ -42,8 +42,25 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; +import { Switch } from "@/components/ui/switch"; import { cn } from "@/lib/utils"; +const MESSAGE_TOPIC_OPTIONS = [ + "Stress/Anxiety", "Marriage", "Hearing God's Voice", "Dealing With Doubt", + "Parenting", "Grief & Loss", "Forgiveness", "Finances", "Purpose/Calling", + "Prayer", "Healthy Boundaries", "Understanding The Bible", "Emotional Health", + "Sharing My Faith", "Decision Making", "Spiritual Disciplines", "Spiritual Gifts", +]; + +const NEXT_STEP_OPTIONS = ["Baptism", "Next Steps"]; + +const CAMPUS_OPTIONS = ["Beulah", "Pace/Milton", "Gulf Breeze", "Warrington"]; + +const HOW_HEARD_OPTIONS = [ + "This is my church home", "Regular Attender", "Drove by", + "Social Media", "Google", "Personal Invite", +]; + type CardData = { id: string; name: string | null; @@ -106,7 +123,7 @@ export default function CardDetailPage() { const [loading, setLoading] = React.useState(true); const [saving, setSaving] = React.useState(false); const [reprocessing, setReprocessing] = React.useState(false); - const [edits, setEdits] = React.useState>({}); + const [edits, setEdits] = React.useState>({}); const [showRawOcr, setShowRawOcr] = React.useState(false); const [showActivity, setShowActivity] = React.useState(false); const [activityLog, setActivityLog] = React.useState([]); @@ -152,13 +169,25 @@ export default function CardDetailPage() { }, [card?.ocrStatus, id]); const getValue = (field: keyof CardData): string => { - if (field in edits) return edits[field]; + if (field in edits) return String(edits[field] ?? ""); const val = card?.[field]; if (val === null || val === undefined) return ""; return String(val); }; - const setField = (field: string, value: string) => { + const getArrayValue = (field: keyof CardData): string[] => { + if (field in edits) return (edits[field] as string[]) ?? []; + const val = card?.[field]; + if (Array.isArray(val)) return val; + return []; + }; + + const getBoolValue = (field: keyof CardData): boolean => { + if (field in edits) return Boolean(edits[field]); + return Boolean(card?.[field]); + }; + + const setField = (field: string, value: unknown) => { setEdits((prev) => ({ ...prev, [field]: value })); }; @@ -411,11 +440,15 @@ export default function CardDetailPage() {