- Add Settings > Advanced > Procedure Duration/Time Slot page with three sections:
1. Procedure Duration: CDT codes with durations (editable table, save per section)
2. Doctor Time Slot: drag-to-block visual grid (A/B/C columns, 8 AM–9 PM, edit/delete slots)
3. Hygienist Time Slot: procedure descriptions with durations
- Backend: ProcedureTimeslot Prisma model, storage, and GET/PUT /api/procedure-timeslot route
- DB migration: procedure_timeslot table
- Appointment form: when type is "Other", show a free-text input for custom description; saved as other:<description> and decoded for display on the schedule card
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Schedule columns default to labels A–F (localStorage, per-browser, click to rename)
- Settings → Advanced → Office Hours: configure Doctors (A-C) and Hygienists (D-F) AM/PM hours per weekday
- Gray out schedule slots outside office hours; override dialog for manual exceptions
- Override Office Hours toggle: select specific dates where all slots are open
- Fix appointment move: send only real DB fields to avoid Zod strict-mode rejection of computed fields (hasProcedures, hasClaimWithNumber)
- Fix backend PUT /appointments: safe error logging to prevent Prisma error crashing Node inspect
- Add OfficeHours Prisma model and GET/PUT /api/office-hours route
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix dateOfBirth default from empty string to null (caused Invalid date error)
- Add noValidate to form to prevent browser native email validation blocking submit
- Reset form when switching from edit to add mode
- Export API_BASE_URL from queryClient; switch patient table to raw fetch (prevents token wipe on 401)
- Add Authorization header forwarding in Vite proxy (was stripped by nginx Connection:upgrade)
- Make only firstName, lastName, dateOfBirth, phone required; gender optional
- Add +1 prefix to phone number input (stores as 1XXXXXXXXXX)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Filter patient list by userId so each user sees only their own patients
- Sort patients by updatedAt DESC so recently checked patients appear first
- Add updatedAt field to Patient model (DB migration via raw SQL + db:generate)
- Fix DDMA name extraction: read from detail page "Name:" label, not search
results row text which included appended dates
- Fix PDF capture: use driver.get() instead of click() to avoid race condition
that was saving the search results page instead of the patient detail page
- Strip trailing bare dates from extracted names (e.g. "Rodriguez 04/27/2026")
- Handle "Last, First" comma format and single-word last names in splitName
- Normalize insuranceId consistently in createOrUpdatePatientByInsuranceId
- Fix OTP persistent session: stop clearing LocalStorage/IndexedDB on startup
(these hold the DDMA device trust token that skips OTP on subsequent logins)
- Increase post-navigation wait time for full page render before PDF generation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add 'Select Procedures' right-click option on appointment page (separate from Claims/PreAuth)
- Select Procedures form saves CDT codes + NPI provider to AppointmentProcedure storage
- Remove Save button from insurance claim form; Claims/PreAuth opens for insurance submission only
- Claims/PreAuth auto-prefills from saved procedures including NPI provider
- Batch-column: procedures npiProviderId takes priority over stale claim npiProviderId
- Batch-column: auto-save PDF to patient Documents after successful submission (no socket needed)
- Add npiProviderId column to AppointmentProcedure table (prisma db push)
- Fix 'invalid db creation invocation': guard staffId, npiProviderId, procedureDate as Date object, totalBilled NaN guard
- Add full error logging to batch-column catch block
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix status enum in browser.ts (uppercase → lowercase values)
- Fix date validation (z.string → z.coerce.date) so form accepts Date objects
- Add missing type/userId/title fields to browser.ts appointment schema
- Replace nested PatientSearch Select with simple inline Input to fix patient selection
- Fix mutationFn to throw on non-ok responses so backend errors surface correctly
- Connect socket.io directly to backend (port 5000) instead of Vite proxy to fix AggregateError on startup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add PLAN_NOT_ACCEPTED to PatientStatus enum (prisma schema + db push)
- Selenium: return "plan not accepted" eligibility text instead of collapsing to inactive
- Backend processor: map "plan not accepted" → PLAN_NOT_ACCEPTED, fix insuranceProvider label
- _shared.ts: save DOB for existing patients when field is currently empty
- Frontend: show amber "Plan Not Accepted" badge in patient table and detail panel
- patient-form.tsx: display "Plan Not Accepted" label in status dropdown
- BullMQ: set attempts=1 (no retry on selenium failure)
- DDMA: remove first/last name from search (member ID + DOB only)
- patient-types.ts: allow alphanumeric insurance IDs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use useAuth() in CredentialTable instead of a separate /api/users/ fetch
that was failing silently and hiding the entire credentials section
- Add migration for autoBackupEnabled/usbBackupEnabled columns on User
that were in the Prisma schema but missing from the database, causing
a 500 error on login
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>