đŸ“±

Vet app

vetvisits.fredmorin.dev/vet

The phone app a vet actually carries into the field: today's visits, a capture form for notes/photos/voice/video, and a shared invoice + prescription lookup. Built to keep working with no signal and catch up once it has one.

Signing in

This demo link skips the staff gate entirely — vet, dispatch, and admin are all directly reachable, no passphrase needed. (A real deployment would sit all three behind one shared gate passphrase instead, with no individual staff logins at that layer — the mechanism's still there, just switched off for this public demo.)

The vet section adds one more step on top: a dropdown of active vets, no password. Pick a name and you're in for 30 days; Sign out in the header signs out and drops you back on that dropdown.

Today's Visits

The home screen defaults to Today, with This week and All alongside it — same underlying list, just filtered differently, so planning ahead doesn't require opening Dispatch's calendar. Each row shows the client, animal (or "Herd visit" for a farm-level stop), time, and a status:

Synced ✓ — done, tap to review Resume / Open — tap to open the capture form

Working a visit

Opening a dispatched visit lands on the capture form, with a link back to Today's Visits at the top in case it was opened by mistake or something else needs checking first. Everything on it autosaves a couple of seconds after you stop typing — a status line above the form reads Saving
 / Saved / Offline so you always know where you stand.

Two note fields, on purpose

Visit notes

Staff only. Never leaves the building — not on an invoice, not in an email.

Customer notes

The one note field that reaches the client — it's what actually gets dropped into their visit-summary email once the visit is finalized. Use it for the friendly wrap-up, not the internal flag.

Photos

Tap Add to take or pick a photo. It drops straight into a simple annotator — draw on it if useful, or just tap Save to accept it as-is. Photos upload in the background the moment they're captured; if one fails, a small red retry badge appears on its thumbnail.

Voice notes

Tap Record a voice note to start recording, tap again to stop. Playable immediately, uploads in the background. A failed upload shows an inline "Didn't upload yet" message with its own retry link.

Video

Tap Record a video — it opens a full-screen recorder using the rear camera by default (a vet is filming an animal, not a selfie). Use the flip button beforehand to switch to the front camera if that's what's actually needed. Recording auto-stops at 60 seconds and uploads in the background, same retry pattern as photos and voice notes.

Prescriptions & other animals treated

The prescriptions panel writes a prescription against the visit's primary animal. For a herd visit — or any visit where more than one animal got treated — use + Add an animal to log each additional animal's own diagnosis, notes, and prescriptions separately; all of it rolls into the same invoice.

Template questions & extra items

Whatever questions the visit's template defines (vaccine given, symptoms observed, head count
) show up as a normal form — required ones are marked. Below that, Add anything else is a free quantity picker over the full price catalog, for anything not already covered by a template answer.

Finishing up

Three buttons, pinned to the bottom of the screen so they're always in reach:

  • Save Visit — finalizes the visit, generates the invoice, and (if the client has an email on file) sends the summary email with the customer notes.
  • Continue Later — saves the draft immediately and returns to the visit list. Nothing is lost; the visit stays exactly where it was.
  • Start Over — asks for confirmation, then wipes everything captured so far for this visit: both note fields, diagnosis, template answers, extra items, and every already-uploaded photo, voice note, and video. The visit itself stays open, ready for a clean take.
Irreversible

Start Over deletes real uploaded content the moment it's confirmed. There's no undo.

Working offline

The top-right of every screen shows a connection dot and a sync summary. Photos, voice notes, and videos each try to upload the instant they're captured — if that fails (or there's genuinely no signal), they're held locally and retried automatically the next time the app can reach the server, with no action needed. A visit saved while offline queues the same way; a Sync Now button is there if you'd rather not wait.

After the visit: the summary dashboard

Once a visit is marked done, tapping it opens a read-only summary instead of the capture form — a card for the visit's basics, then one card per thing actually captured (photos, voice notes, video, prescriptions, treated animals, template answers). Nothing shows up empty.

One thing still isn't frozen: both note fields stay editable here, each with its own Save button, so a follow-up thought after the fact doesn't need a whole new visit.

Vet Questions

Vet Questions lists two queues: customer questions the bot escalated because it wasn't confident answering, and pending prescription renewal requests. Everything here is answered or decided as whichever vet is currently signed in — there's no "answering as" picker anymore.

Approving a renewal isn't a rubber stamp: the medication, quantity, and expiration date are all editable right there, defaulting to the original prescription's own values, plus an optional note to the client. Denying, like approving, is final — both move the request into the handled list below.

An answered question — bot- or vet-answered — can also be featured on the public FAQ, a deliberate opt-in rather than anything automatic. Featuring one opens editable question/answer fields pre-filled from the original, since the public page needs anything identifying the client or animal rewritten out before it goes live.

Calendar sync

Each vet has their own subscribe-by-URL calendar feed — set up from Admin → Vets — that Outlook, Apple Calendar, or Google Calendar can follow directly. It's one-way: the calendar app displays the schedule, nothing written there comes back into VetVisits. If a link is ever compromised, regenerating it from Admin issues a fresh one without touching the vet's own record.

Also on this app

  • Invoices — every invoice this vet's visits have generated.
  • Prescriptions — a lookup across every prescription written, visit-linked or a standalone phone-in refill; writing one here attributes it to whichever vet is signed in.
đŸ—“ïž

Dispatch

vetvisits.fredmorin.dev/dispatch

Where a visit gets turned from "someone called" into "a vet is on their way" — booking, assigning, and a full drag-and-drop calendar. Same sign-in as the other staff apps — see the Vet app page.

The board

The home screen lists every visit in one of five buckets, in this order: Unscheduled, Needs Dispatch, Dispatched, In Progress, Completed. A Dispatch button appears only on rows waiting to go out — tapping it is the actual "send it to the vet's phone" action; the visit then shows up on that vet's own Today's Visits list.

Booking a new appointment

  1. Open + New Appointment from the board.
  2. Pick the client (a farm's own record), then the animal — or check the herd-visit toggle to skip picking one specific animal (used for a farm-level stop like a routine monthly checkup).
  3. Pick a visit type. Choosing one auto-fills the usual duration for that type.
  4. Assign a vet, and optionally an assistant and any equipment the visit needs.
  5. Set the date/time and duration, or check the unscheduled toggle to skip a slot entirely — it'll land in the calendar's Unscheduled Pool for later placement.
  6. Submit with Create Appointment.
Conflict warning, not a block

As soon as a vet, assistant, equipment, time, and duration are all set, the form checks for anything already booked in that window — and for any of them marked unavailable in Admin (time off, equipment out of service) — and shows exactly who or what overlaps. It's advisory — the form still submits even with a conflict showing, in case it's intentional.

The calendar

Toggle between Day (one column per vet) and Week (one column per day, every vet mixed in) — click a day header in Week view to jump straight into Day view for that date. A third toggle, Map, plots that same day's visits as pins on a map — useful for a big territory where drive time between farms is a real cost, at a glance rather than by reading times off a grid. Pins only, no route line or reordering; tap one for the client, animal, time, and vet.

  • Unscheduled Pool — a strip above the grid listing every unscheduled visit as a small card. Drag one onto a vet's column at any time to schedule it in one motion.
  • Drag to move — any visit that hasn't started yet (unscheduled, scheduled, or dispatched — never once a vet has actually begun it) can be dragged to a new time or a different vet. Drops snap to 15 minutes.
  • Resize — drag the handle on a visit block's bottom edge to stretch or shrink its duration right on the grid.
  • Double-click to edit — opens a modal with template, vet, assistant, equipment, time, duration, and the visit's internal notes, with the same unavailability warning as the booking form above.
Send confirmation?

Any drag, resize, or modal save that changes the time or duration prompts a yes/no: send the client a reschedule confirmation email? It's a deliberate per-change choice, not automatic — declining just applies the change silently.

If two people edit the same visit at nearly the same moment, the second save is rejected with a reload prompt rather than silently overwriting the first.

What lives in Admin instead

Clients, animals, vets, assistants, equipment, and visit templates are all managed in the Admin app — Dispatch only reads those lists to populate its own dropdowns.

đŸ—‚ïž

Admin

vetvisits.fredmorin.dev/admin

The back office — a dashboard for at-a-glance status, a place to review any visit in depth, order fulfillment, and every configuration screen the other three apps quietly depend on.

Dashboard

Ten independent widgets — recent visits, the unscheduled pool count, needs-dispatch count, today's schedule, a 7-day upcoming chart, campaign reminder counts, pending orders, prescriptions issued this week, revenue this week, and a system health card (mail sending, active staff counts).

Tap Customize to remove, reorder, or re-add any widget — the layout is remembered per browser. Every row in Recent visits is a link: a completed one shows the actual date and time it closed and opens straight into that visit's full summary.

Reviewing a visit

Opening any visit from the dashboard (or anywhere else it's linked) shows the same dashboard-style summary a vet sees once their own visit is done: a summary card, then one card per thing actually captured. Both the internal and customer note fields are editable right there, each saving independently.

Orders

Every order a client has placed through the Customer Portal — supplies or a prescription refill — lands here as Submitted, along with any note the customer left at checkout. There's no automatic notification to a vet; a staff member reviews the queue and marks each one Fulfilled once it's ready.

Everything else, by nav group

đŸ‘€

Customer Portal

portal.fredmorin.dev

The one app a client uses directly — no staff passphrase, no account to create. A client can only sign in once their email is already on file (set from Admin → Clients).

Signing in

  1. Enter the email on file for the client record.
  2. A 6-digit code arrives by email, valid 10 minutes.
  3. Enter it to sign in — the session lasts 30 days.

There's no password to set or forget, and no self-registration — if a client's email isn't already in Admin, this screen has nothing to log them into.

Try the demo

Sign in with [email protected] and code 123456 — no real email gets sent for this one account, so there's nothing to wait for.

Home

A welcome, quick links to booking / prescriptions / orders, and a list of the client's own upcoming appointments.

Booking a visit

Pick a visit type first — for one that doesn't need a specific animal named up front (a general farm visit, say), the animal checklist doesn't even appear; for anything that does, it shows right after. Then a date, then a real available time slot — the grid only shows what's actually open. If someone else takes that exact slot in the few seconds before submitting, the page says so and refreshes the options rather than double-booking.

Prescriptions

Every prescription across the client's animals: medication, which animal, instructions, "X of Y remaining," and an expiry date where one applies. An expired one is flagged clearly — and see Prescription Renewal for what a client can (and can't) still do with one.

Order History

A running history of everything the client has ordered — date, a Submitted/Fulfilled status pill, line items, and the total.

Asking a vet a question

A floating chat bubble sits on every portal page once signed in — opening it shows the Ask a vet panel. Routine questions (clinic hours, how to book, deworming/vaccination cadence, billing basics, reordering a prescription) get an instant reply from a simple bot; anything about a specific animal's health goes straight to a vet's queue instead, and the reply shows up back in this same window once it's answered — no need to keep it open and wait.

FAQ

A public page — no sign-in needed — of client questions a vet has chosen to feature, each rewritten to strip out anything that would identify who asked or which animal it was about. Not every answered question ends up here: featuring one is a deliberate step a vet takes from Vet Questions, not something that happens automatically.

💊

Prescription Renewal

portal.fredmorin.dev/portal/order

Two different paths, depending on whether there's still quantity left. A prescription that isn't expired and has quantity remaining is refilled by placing an order against it, on the same Order page a client uses to buy ordinary supplies. One that's expired gets a distinct Request renewal button instead — see below.

How a client actually does it

  1. From Prescriptions, tap Order this on anything still valid with quantity left — this is the only place that button appears. It lands directly on that exact medication, highlighted, in the Order page's Medications list, rather than a generic order screen you'd have to scroll through to find it again.
  2. The Order page's Medications section lists every prescription the client's animals still have remaining authorization on, each showing "X of Y remaining" for its animal.
  3. Set a quantity — the field itself won't let you exceed what's actually left — and add it to the cart. Adding the same item again bumps that line's quantity rather than creating a second one.
  4. Add any ordinary supplies the same way, an optional note for the clinic if there's anything they should know, then tap Review order.
  5. A review screen recaps every line, the note, and the total — Back to change anything, or Confirm order to actually place it.

What happens on submit

The server checks everything again independently before accepting the order: the quantity is at least 1, a medication line has a matching prescription (a supply line must not), that prescription belongs to that client's own animal, isn't expired, and the amount requested doesn't exceed what's genuinely still remaining — computed fresh from every order ever placed against it, not a counter that could drift. Any violation comes back as a specific, readable error and returns to the cart to fix it, instead of a generic failure.

A successful order is created as Submitted straight into the Admin Orders queue, note included.

No approval step

Nothing here notifies a vet or asks for sign-off — placing the order is the whole client-side action. Fulfillment is purely an Admin-side staff task from that point on.

Requesting a renewal

Once a prescription is expired, its Order this button disappears from the Prescriptions page and Request renewal takes its place right there — not on the Order page, since there's no valid authorization left to order against.

Tapping it sets the prescription to Renewal requested — waiting on a vet. Whichever vet is currently signed in reviews the request from Vet Questions (see the Vet app's own handbook page) — approving isn't a rubber stamp there: the medication, quantity, and expiration date are all editable before it's confirmed, defaulting to the original prescription's own values. Approving issues a brand-new prescription; the client sees Renewal approved and finds it back on this same page.

A denied request shows Renewal request denied but isn't a dead end — the same button reappears immediately, ready to ask again.

VetVisits demo handbook — reflects the apps as they run today; screens and wording may move as the demo evolves.