Skip to main content

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:

  1. Today — daily schedule + quick stats.
  2. Patients — recently scanned + search.
  3. 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/redeem and 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_remaining on the line.
  • Cancel an Rx (audited).

Inventory + dispense

  • Medicine search (across medicines for the active tenant).
  • Dispense from prescription — pre-fills a stock_movement of type dispense from 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 /reminders with the right reminder_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.