vetdoctor — Vet/Clinic Mobile App
A Flutter (Dart) clinician's pocket companion. Lives at vetdoctor/ in the repo. Targets iOS, Android, web (Flutter web), macOS, Windows, Linux.
See audit §8 for the security and UX punch-list. This page is the feature catalogue.
Top-level navigation
The home shell carries three tabs:
- Today — daily schedule + quick stats.
- Patients — recently scanned + search.
- Profile — settings, tenant switcher, sign out.
Auth
Same pattern as vetty (vetdoctor/lib/core/auth/). Tokens live in
flutter_secure_storage (keychain / encrypted SharedPreferences).
Release builds refuse to boot without VETDOCTOR_API_BASE_OVERRIDDEN=true
at build time — see Env.assertReleaseOverride() in
config/env.dart.
The app supports the staff tenant_user model — a user assigned to multiple clinics can switch between them from the profile tab; current_tenant_id updates on switch and the home tab reloads.
BiometricLock wraps the entire authenticated tree so every
backgrounding event re-locks the app — patient PII never sits visible
on a counter while the phone is unattended.
Features by domain
Today / dashboard
- Today's appointments (
GET /tenant/{tenant}/appointments?from=today&to=today). - Receptionist's queue / kanban view (
/appointments/queue) — appointments grouped by workflow column (scheduled/checked_in/with_vet/completed). - Stat cards — patients seen today, low-stock alerts, due-vaccination cohorts.
Patient lookup
- Search — name / phone / pet name across
clients+pets. - QR scan — opens the camera; redeems a pet share token via
POST /shares/redeemand surfaces the patient briefing (GET /patients/{pet}returns pet basics + active Rx + last visit + allergies in one round-trip). - Recent — locally cached list of recently opened patients.
Patient profile
The same SOAP-rich tabbed view the web admin shows, scoped down for mobile:
- Profile — pet basics + medical flags + allergies.
- Visits — list of past visits with the SOAP narrative + vitals.
- Prescriptions — Rx history; tap into a single Rx to see line items + refills remaining.
- Lab results — by panel, with the flag color-coding.
- Vaccinations — clinic + owner sources mixed.
- Health journal — owner-written entries (read) + clinic-write button (e.g. record check-in weight).
- Attachments — list + download (X-rays, lab PDFs).
Visit creation
- New visit form with SOAP narrative, vitals, optional prescription envelope (with line items via the medicine search), optional lab results.
- On save, single round-trip writes everything + dispatches the post-visit reminder if the operator ticks the box.
- Discharge summary PDF on completion.
Prescriptions
- View pet's active prescriptions.
- Mark refill as fulfilled — increments
refills_remainingon the line. - Cancel an Rx (audited).
Inventory + dispense
- Medicine search (across
medicinesfor the active tenant). - Dispense from prescription — pre-fills a
stock_movementof typedispensefrom a Rx line. (Audit P2: this is currently a manual flow; auto-prefill from Rx is on the roadmap.) - Low-stock + expiry-alert badges visible on the home tab.
Reminders
- Send a reminder from the patient profile (Vaccination due, follow-up, payment due).
- Hits
POST /reminderswith the rightreminder_type+ template slug.
Lab / Surgery / Boarding / Telemedicine (Phase 2)
Each of the four screens accepts an optional petId prefilter and
optional focus*Id for a deeplinked-row highlight. Opening any of
them from the patient-detail action menu passes widget.petId
automatically — the vet lands on that patient's rows only, no
second pick. Notification tap on (say) a "lab result ready" message
extracts order_id from the deeplink payload and opens LabScreen
with that row selected + status filter unlocked so it's guaranteed
visible.
In-app notifications
Two icons in the dashboard AppBar:
- Megaphone — compose flow to broadcast an announcement to clients, specific pets, recent visitors, or internal staff. See Notifications.
- Bell — personal inbox for the logged-in staff user. Polls unread-count every 60 s. Opening the inbox marks messages read on tap; swipe-to-delete removes from the user's inbox only.
Internationalization
Foundation lives at lib/core/i18n/i18n.dart (English + Hindi
seed). Same shape as vetyy's. main() calls
await Vi18n.init() before render.
State management
Same provider + setState pattern as vetty. Same audit findings.
Known gaps (selected)
- No queue / waitlist UI for the day's patient flow (today, just a list).
- No daily calendar grid view.
- No biometric guard before showing PII.
- No chart-note dictation (voice → text).
- No prescription autocomplete from condition / breed.
- No lab-result file upload from mobile (must use web).
- Recent-scans list doesn't persist across app restarts.
See AUDIT.md §8 for the full list.