diff --git a/detect_fields.py b/detect_fields.py index a1db0d0..965c323 100644 --- a/detect_fields.py +++ b/detect_fields.py @@ -85,6 +85,30 @@ def detect_underscores(pno, page): return fields +def detect_checkboxes(pno, page): + """Find checkbox glyphs (U+F0A8) and their labels. Type 'checkbox'.""" + fields = [] + words = page.get_text("words") + groups = {} + for w in words: + x0, y0, x1, y1, word = w[0], w[1], w[2], w[3], w[4] + key = int(y0 / 5) * 5 + groups.setdefault(key, []).append((x0, x1, y0, word)) + for y in sorted(groups): + ws = sorted(groups[y], key=lambda t: t[0]) + for i, (x0, x1, y0, word) in enumerate(ws): + if "\uf0a8" in word: + label_words = [] + for wx0, wx1, _, w in ws[i + 1:]: + if "\uf0a8" in w: + break + label_words.append(w) + label = " ".join(label_words).strip() + fields.append({"page": pno, "x": x0, "y": y0, "type": "checkbox", + "label": label}) + return fields + + def main(): all_fields = {} for fn in sorted(os.listdir(FORMS_DIR)): @@ -99,9 +123,9 @@ def main(): continue fields = [] seen_keys = set() - for pno in range(min(len(d), 3)): # caption + first 2 pages - lines = lines_with_pos(d[pno]) + for pno in range(min(len(d), 12)): # caption + all pages if pno == 0: + lines = lines_with_pos(d[pno]) for f in detect_caption(lines): f["page"] = 0 if f["key"] not in seen_keys: @@ -110,6 +134,9 @@ def main(): for f in detect_underscores(pno, d[pno]): f["key"] = "f_" + str(len(fields)) fields.append(f) + for f in detect_checkboxes(pno, d[pno]): + f["key"] = "cb_" + str(len(fields)) + fields.append(f) d.close() all_fields[fid] = fields out = "/opt/astraea/forms/fieldmap.json" diff --git a/forms.py b/forms.py index 1abb33e..eff52ac 100644 --- a/forms.py +++ b/forms.py @@ -72,12 +72,21 @@ def fill_form(form_id, values): f = fmap.get(key) if not f or not text: continue - text = str(text).strip() - if not text: - continue page = doc[f.get("page", 0)] - page.insert_text((f["x"], f["y"]), text, fontsize=f.get("size", 11), - fontname="helv", color=(0, 0, 0)) + if f.get("type") == "checkbox": + v = str(text).strip().lower() + if v in ("x", "true", "yes", "1", "checked", "check", "on"): + x, y = f["x"], f["y"] + page.draw_line(pymupdf.Point(x + 1, y + 1), pymupdf.Point(x + 9, y + 9), + color=(0, 0, 0), width=1.3) + page.draw_line(pymupdf.Point(x + 9, y + 1), pymupdf.Point(x + 1, y + 9), + color=(0, 0, 0), width=1.3) + else: + text = str(text).strip() + if not text: + continue + page.insert_text((f["x"], f["y"]), text, fontsize=f.get("size", 11), + fontname="helv", color=(0, 0, 0)) out = os.path.join("/tmp", f"filled_{form_id}_{uuid.uuid4().hex[:8]}.pdf") doc.save(out) doc.close() diff --git a/templates/index.html b/templates/index.html index f8005e9..0ab9fcd 100644 --- a/templates/index.html +++ b/templates/index.html @@ -344,19 +344,25 @@ }catch(e){ pv.textContent='Upload failed'; pv.style.color='#f87171'; } } const INTAKE=[ - {label:"My name", q:"What's your full name?", p:"Jane Marie Doe"}, - {label:"Spouse's name", q:"What's your spouse's full name?", p:"John Robert Doe"}, - {label:"Married", q:"When and where did you get married?", p:"June 15, 2011, Seattle, WA"}, - {label:"Separated", q:"When did you separate?", p:"June 2025"}, - {label:"Children", q:"How many children do you share, and their names and ages?", p:"Two — Emma (12) and Liam (9)"}, + {label:"My full legal name", q:"What's your full legal name (first, middle, last)?", p:"Jane Marie Doe"}, + {label:"My mailing address", q:"What's your current mailing address (street, city, state, ZIP)?", p:"123 Main St, Everett, WA 98201"}, + {label:"Spouse's full legal name", q:"What's your spouse's full legal name?", p:"John Robert Doe"}, + {label:"Spouse's mailing address", q:"What's your spouse's mailing address?", p:"456 Oak Ave, Everett, WA 98201"}, + {label:"Marriage date & place", q:"When and where did you get married (exact date + city/county/state)?", p:"June 15, 2011, Seattle, WA"}, + {label:"Separation date", q:"When did you separate (exact date)?", p:"June 1, 2025"}, + {label:"Case number", q:"Has a case been filed? What's the case number (if you know it)?", p:"Not yet / 24-3-01234-31"}, + {label:"Children (names, ages, DOBs)", q:"List each child's full name, age, and date of birth.", p:"Emma Grace Doe, 12, born 01/15/2013; Liam James Doe, 9, born 03/22/2016"}, {label:"Current custody", q:"Where do the children live now, and what's the current schedule?", p:"They live with me; dad has them every other weekend"}, - {label:"Home", q:"Do you own a home or other real estate? Address, when bought, whose name is on the title/mortgage?", p:"House at 123 Main St, bought 2012, both names on title"}, + {label:"Home / real estate", q:"Do you own a home or other real estate? Address, when bought, whose name is on the title/mortgage?", p:"House at 123 Main St, bought 2012, both names on title"}, {label:"Assets", q:"What are your main assets? (bank accounts, retirement, vehicles, business, investments)", p:"Joint savings ~$20k, my 401k ~$85k, two cars"}, {label:"Debts", q:"What are your main debts? (mortgage, credit cards, loans)", p:"Mortgage $280k remaining, $9k credit card, $12k car loan"}, - {label:"Income", q:"What's your employment and income? And your spouse's?", p:"I make $72k/yr as a nurse; spouse makes $95k as an engineer"}, - {label:"Case status", q:"Has either of you filed for divorce yet, and what does each side want?", p:"Spouse filed; wants full custody and to keep the house"}, - {label:"Safety", q:"Is there any domestic violence, abuse, or safety concern? Any protection orders?", p:"No / Yes — details"}, - {label:"Goals", q:"What outcome matters most to you? What are you most worried about?", p:"Keeping the kids with me and keeping the house"}, + {label:"My income & employer", q:"What's your job, employer, and annual gross income?", p:"Registered nurse, Providence, $72k/yr"}, + {label:"Spouse's income & employer", q:"What's your spouse's job, employer, and annual gross income?", p:"Software engineer, Amazon, $95k/yr"}, + {label:"Children's health insurance", q:"Who provides health insurance for the children, and through which employer?", p:"My employer (Providence) covers the kids"}, + {label:"Case status", q:"Has either of you filed for divorce yet, and what does each side want (custody, support, property)?", p:"Spouse filed; wants full custody and to keep the house"}, + {label:"Safety / DV", q:"Is there any domestic violence, abuse, or safety concern? Any protection orders in place?", p:"No / Yes — details"}, + {label:"Other cases", q:"Are there any other court cases involving you, your spouse, or the children (criminal, CPS, other family law)?", p:"None"}, + {label:"Goals & worries", q:"What outcome matters most to you? What are you most worried about?", p:"Keeping the kids with me and keeping the house"}, ]; let intakeIdx=0; const intakeAnswers={}; function openIntake(){ intakeIdx=0; for(const k in intakeAnswers) delete intakeAnswers[k]; closeModal('profileModal'); renderIntake(); document.getElementById('intakeModal').classList.add('open'); }