initial commit
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# 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
|
||||
<div class="mb-4">
|
||||
<label for="scan-appointment-date" class="...">Appointment Date</label>
|
||||
<input type="date" id="scan-appointment-date" class="...">
|
||||
<p class="text-xs text-purple-500 mt-1">All appointments in this screenshot are for this date.</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
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.
|
||||
Reference in New Issue
Block a user