# "+ New Letter" Modal Flow *Created: 2026-07-08 — added to `/var/www/internal/letter-queue.html`* ## Overview A two-screen modal that replaces the static default claim with a full client-selection → stage-appropriate-template flow. When the user clicks "New Letter" (button with `id="newLetterBtn"`), the modal opens on the client selection screen. ## Screen 1 — Client Selection ### Modal Structure | Element | Details | |---------|---------| | Title | "New Letter" | | Subtitle | "Select a client/claim to get started" | | Search bar | Filter input with search icon, placeholder "Search by debtor name, claim #, or client..." | | Body | Scrollable list of client rows | ### Client Data Model (JS `clients[]`) ```js { claim: String, // "DRE-2026-0142" debtor: String, // "Marcus Bellweather" amount: Number, // 12840.00 client: String, // "ABC Construction" stage: String // "soft-touch" | "formal-demand" | "lien-threat" | "escalation" | "legal-action" } ``` ### Client Row Rendering Each row shows: - **Left (flex-1, truncate):** Debtor name (white, medium) + claim # (amber, mono) on line 1. Client name + amount on line 2 (gray-500, xs). - **Right (shrink-0):** Stage badge (colored pill). Search filter is case-insensitive and matches against `debtor`, `claim`, or `client` fields. ### Stage Badge CSS ```css .stage-badge { display: inline-flex; align-items: center; gap: 0.25rem; padding: 2px 10px; border-radius: 9999px; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.02em; border: 1px solid; } .stage-soft-touch { background: rgba(59,130,246,0.15); color: #93c5fd; border-color: rgba(59,130,246,0.3); } .stage-formal-demand { background: rgba(245,158,11,0.15); color: #fcd34d; border-color: rgba(245,158,11,0.3); } .stage-lien-threat { background: rgba(251,146,60,0.15); color: #fdba74; border-color: rgba(251,146,60,0.3); } .stage-escalation { background: rgba(239,68,68,0.15); color: #fca5a5; border-color: rgba(239,68,68,0.3); } .stage-legal-action { background: rgba(168,85,247,0.15); color: #d8b4fe; border-color: rgba(168,85,247,0.3); } ``` | Stage | Color | Semantic | |-------|-------|----------| | soft-touch | Blue | Initial contact | | formal-demand | Amber | First formal notice | | lien-threat | Orange | Lien warning | | escalation | Red | Final warning | | legal-action | Purple | Referred to counsel | ### Demo Clients (10 claims) | Claim | Debtor | Amount | Client | Stage | |-------|--------|--------|--------|-------| | DRE-2026-0142 | Marcus Bellweather | $12,840 | ABC Construction | soft-touch | | DRE-2026-0098 | Sylvia Chen | $8,750 | Chen & Sons Roofing | formal-demand | | DRE-2026-0105 | James Kowalski | $22,340 | Kowalski Framing LLC | lien-threat | | DRE-2026-0081 | Patricia Okafor | $5,400 | Okafor Drywall Inc. | escalation | | DRE-2026-0157 | Angela Torres | $16,780 | Torres Electric Co. | formal-demand | | DRE-2026-0062 | Linda Harper | $9,200 | Harper Painting & More | lien-threat | | DRE-2026-0074 | Robert Nguyen | $31,500 | Nguyen Construction LLC | legal-action | | DRE-2026-0118 | Derek Simmons | $6,400 | Simmons Brick & Block | soft-touch | | DRE-2026-0123 | Maria Gonzalez | $19,450 | Gonzalez Landscaping | escalation | | DRE-2026-0135 | Tom Fletcher | $11,000 | Fletcher Plumbing LLC | soft-touch | ## Screen 2 — Template Selection ### Header Change When a client is selected, the modal header updates: - **Title:** Debtor's name (e.g. "Marcus Bellweather") - **Subtitle:** `"{claim} · ${amount} · Current Stage: {stageLabel}"` ### Stage-to-Template Progression Templates always progress *forward* — you never offer a template at or below the current stage. The mapping: ```js const stageTemplates = { 'soft-touch': ['formal-demand'], 'formal-demand': ['lien-threat', 'escalation'], 'lien-threat': ['escalation', 'legal-action'], 'escalation': ['legal-action'], 'legal-action': [] // referred to counsel — no templates }; ``` ### Template Display Each template is rendered as a button with: - **Icon** (colored Font Awesome icon, w-6 text-center) - **Name** (white, medium, sm): e.g. "Formal Demand Letter" - **Description** (gray-500, xs): e.g. "Generate a Soft Touch → Formal Demand Letter" - **Arrow right** (gray-500, ml-auto) Icons per template: | Template | Icon | |----------|------| | Formal Demand | `fa-regular fa-file-lines` | | Lien Threat | `fa-regular fa-triangle-exclamation` | | Escalation / Final Notice | `fa-regular fa-bell` | | Legal Action Referral | `fa-regular fa-gavel` | ### Legal-Action Stage (Disabled State) When a client is already at legal-action stage, the template screen shows: - Purple gavel icon centered - "Legal Action Stage" heading - "This claim has been referred to legal counsel. No letter templates are available." - "Back to client list" button ### Template Content (4 templates) Each template uses `[CLAIM]`, `[DEBTOR]`, `[AMOUNT]`, `[CLIENT]` placeholders that get replaced at selection time. **Formal Demand** — Standard escalation from soft-touch. 14-day payment window. References previous notice. Lists collection measures (lawsuit, liens, litigation referral). Includes payment URL. **Lien Threat** — Texas Property Code mechanic's lien warning. 10-day payment window. Explains that a filed lien attaches to title and affects sale/refinance. Construction-focused language. **Escalation / Final Notice** — Strongest pre-legal notice. 10-day ultimatum before lawsuit referral. Lists post-judgment remedies (garnishment, levy, seizure). Mentions court costs and attorney's fees. **Legal Action Referral** — Confirms referral to legal counsel. States that a civil petition will be filed. Includes claim/amount/legal reference. Lists what the lawsuit will seek (judgment, interest, costs, fees). Each template gets appended with: ``` Sincerely, Anita Rodriguez Collections Specialist Debt Recovery Experts ``` ### Selection → Draft Creation When a template is selected: 1. **Replace placeholders** in the template raw content 2. **Append signature block** (Anita Rodriguez) 3. **Reset composer** — textarea gets the new content, status badge set to Draft, claim info bar updated with client data and stage badge 4. **Create new letter entry** — pushed to `letters[]` with a new auto-incremented `id`, status `draft`, authoredBy `Anita Rodriguez`, tier set to current stage label 5. **Select the new letter** via `selectLetter(newId)` — updates the table with the row highlighted 6. **Close modal** 7. **Scroll to composer** — `document.querySelector('.grid-layout').scrollIntoView(...)` 8. **Toast** — "New {templateLabel} drafted for {debtor}" ## Modal CSS ```css .modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.7); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 60; } .modal-overlay.hidden { display: none; } .modal-panel { background: #1e293b; border: 1px solid #374151; border-radius: 16px; width: 100%; max-width: 42rem; margin: 0 1rem; max-height: 80vh; display: flex; flex-direction: column; box-shadow: 0 25px 60px -15px rgba(0,0,0,0.4); } .client-row { display: flex; align-items: center; gap: 0.75rem; padding: 10px 14px; border-radius: 10px; cursor: pointer; transition: background 0.15s; } .client-row:hover { background: #334155; } .client-row.selected { background: rgba(245,158,11,0.1); border: 1px solid rgba(245,158,11,0.25); } .template-btn { display: flex; align-items: center; gap: 0.75rem; width: 100%; padding: 12px 16px; border-radius: 10px; cursor: pointer; transition: all 0.15s; text-align: left; background: #0f172a; border: 1px solid #334155; color: #e2e8f0; } .template-btn:hover { background: #1e293b; border-color: #f59e0b; } .template-btn + .template-btn { margin-top: 6px; } .templates-grid { display: grid; grid-template-columns: 1fr; gap: 6px; } .back-btn { display: inline-flex; align-items: center; gap: 0.375rem; color: #94a3b8; font-size: 0.8125rem; cursor: pointer; transition: color 0.15s; } .back-btn:hover { color: #f59e0b; } ``` ## JS Functions (key) | Function | Purpose | |----------|---------| | `openNewLetterModal()` | Resets state, clears search, shows modal, renders client list, focuses search | | `closeNewLetterModal()` | Hides modal | | `renderModalClientList()` | Filters `clients[]` by `modalSearchQuery`, renders rows or empty state | | `showTemplatesForClient(client)` | Updates title/subtitle, renders available templates or legal-action disabled state | | `selectTemplate(client, templateKey)` | Replaces placeholders, appends signature, creates draft letter, selects it, closes modal, scrolls to composer | ## Edge Cases - **Empty search results:** Centered exclamation icon + "No clients match `{query}`" message - **Legal-action clients:** Disabled template screen with "referred to counsel" message, no templates offered - **Modal close on overlay click:** Clicking the blurred backdrop closes the modal (same as the X button) - **Search while on templates screen:** Input is only active when `modalState === 'clients'` — typing during template selection does nothing