# Appointment Screenshot Date Handling The date in appointment screenshots sits in the top middle (e.g., "Wednesday Jun 10, 2026"). All appointments in one screenshot are for the same day. ## Current approach: User-selected date (no OCR date extraction) The user picks the date via a date picker before scanning. The date is injected into the LLM system prompt so the AI never tries to extract it from garbled OCR text. This eliminates an entire Tesseract OCR pass (~30s savings) and frees tokens for better appointment extraction. ### Date picker UI element ```html

All appointments in this screenshot are for this date.

``` Located between the model selector and upload area in `#scan-screenshot-modal`. ### Default to today When the modal opens, the date picker defaults to today if not already set: ```js const dateInput = document.getElementById('scan-appointment-date'); if (dateInput && !dateInput.value) dateInput.value = new Date().toISOString().split('T')[0]; ``` ### Reading in handleFile ```js const selectedDate = document.getElementById('scan-appointment-date')?.value || new Date().toISOString().split('T')[0]; ``` ### System prompt injection The LLM prompt includes the date explicitly so it never wastes tokens deciphering the header: ``` ### ALL APPOINTMENTS ARE FOR: 2026-06-14 ``` And rule #1 changed from "Find the date in the header..." to: ``` 1. appointmentDate: Use "2026-06-14" for EVERY appointment. Do not read dates from the text. ``` The prompt is built with string concatenation: `'...### ALL APPOINTMENTS ARE FOR: ' + selectedDate + '\n\n### COLUMN LAYOUT...'` ### Fallback in mapping The final appointment mapping uses `selectedDate` as fallback: ```js appointmentDate: /^\d{4}-\d{2}-\d{2}$/.test(a.appointmentDate) ? a.appointmentDate : selectedDate, ``` ## Removed: Two-pass OCR date extraction The previous approach (removed June 2026) used a second Tesseract pass with PSM 7 on a cropped top-20% image. This was fragile — OCR artifacts, wrong PSM, and table-row false positives made it unreliable. The user-picker approach is faster, more reliable, and simpler. ## One remaining detail The `preprocessed` object still creates a `header` blob during preprocessing (top 20% crop) but it is no longer used. It can be cleaned up in a future refactor.