Commit Graph

61 Commits

Author SHA1 Message Date
754efdee09 feat(frontend): let the clinician pick the tooth from the candidates
An under-specified tooth was a dead end: the sheet said what was missing
and the clinician had to leave and hunt for it on the chart. The readings
are enumerable, so the review sheet now renders them as chips — the one
interactive part of an otherwise read-only confirmation step.

A pick is folded into the result by withChosenTeeth() rather than tracked
alongside it, so the rows, the mini chart, the prosthesis warning and
applyVoiceResult all keep reading a single VoiceExtractionResult and none
of them has to know the chips exist. It unions rather than toggles: a
candidate can coincidentally be a tooth the recording already produced, and
tapping it must not deselect that one.

Two things that would otherwise make the chips look functional while
applying nothing: the teeth row is ticked on the first pick (it starts
unticked when the recording produced no teeth of its own), and the apply
count is now intersected with row availability so it cannot promise to
apply a row with nothing in it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 23:05:30 +03:30
3f97940a16 feat: wire voice entry into the treatment workspace
Makes the feature reachable end to end: availability is fetched alongside the
catalogs, the capture hook drives the segmented control, and confirming the
review sheet appends a new detail.

Confirm always appends — it never edits an existing detail and never calls
onAddDetail. Ticked rows land on top of the seeded defaults, so unticking the
type row leaves the appointment-purpose default rather than a blank. Lab-side
rows ride on a lab case draft keyed by the detail's *client* id, so a brand-new
unsaved detail can carry a lab, due date and per-tooth prosthesis map.

Availability comes from the API rather than a NEXT_PUBLIC_* var, since those are
baked in at build time; a failure fetching it degrades to no microphone rather
than taking the treatment tab down.

From review of this commit:

- Unticking "teeth" while leaving "prosthesis" ticked attached prosthesis rows
  for teeth the detail does not contain. Nothing downstream filters them —
  assertCompleteToothProsthesisMap only checks detail-teeth ⊆ map, never the
  reverse — so they would have reached task generation as lab work for teeth
  nobody is treating. The map is now filtered to the detail's own teeth.
- The microphone was gated on the URL locale while the server resolved
  everything from req.user.language. Those diverge (a bookmarked /fa/ URL, a
  language toggle whose save failed), which would transcribe Persian with an
  English hint and anchor "next Thursday" to a Monday week instead of a Saturday
  one — or 403 from a visibly-enabled button. The client now sends the locale the
  microphone was offered in, so the gate and the request agree by construction.

Also fixed from the previous review: a civil YYYY-MM-DD date rendered a day
early west of Greenwich (parsed as UTC midnight); the missing-teeth list
hardcoded the Arabic comma for all locales; and voiceApply had no ICU plural, so
the common single-field case read "Apply 1 fields".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 23:05:30 +03:30
c07f550e00 feat(frontend): split Add detail into a segmented control with voice
The microphone becomes the second segment of the Add detail button, built like
the detail chip's trash affordance in the same file — an overflow-hidden rounded
wrapper holding two raw <button>s divided by border-s — rather than two shared
Buttons, which each hardcode their own rounding and would fight a segmented
control. border-s puts the mic at the logical end: visually right in en/nl,
visually left in fa, on the same side as the chip's trash in both directions.

The two halves share a wrapper and nothing else. Add keeps its exact behaviour.

The control never changes size while recording; the timer and level meter live
in a bar between the header row and the chip strip, because the header is
sm:justify-between and growing the button would shove the row on every start and
stop. The meter exists to prove the microphone is actually hearing something —
silence and a dead mic look identical otherwise.

Voice reaches the editor as one optional `voice` prop, so its absence *is* the
unavailable state and the two cannot disagree.

Fixes from review of this commit:

- mountedRef was set false on unmount and never re-armed, so under StrictMode
  the hook was permanently "unmounted" in dev and recording silently never
  started.
- onStart guarded only on `phase`, which does not change until getUserMedia
  resolves; a second click during the permission prompt orphaned the first
  MediaStream, leaving the mic indicator lit.
- Week start is now per locale. "Next Thursday" is week-relative, and hardcoding
  Saturday put an en/nl clinician's deadline a week out.
- A missing `which` on a weekday intent is read as "this" rather than failing —
  a bare weekday carries no qualifier, and rejecting it discarded a real
  deadline.
- durationMs is client-reported and so is a claim, not enforcement; the cap is
  now also checked against the vendor's own usage.seconds.
- Blob type falls back to the recorder's actual mimeType before webm, so old
  Safari's mp4/aac clips are not mislabelled.

Two review findings were rejected as incorrect, both re-verified against live
sources: google/gemini-3.7-flash does exist on OpenRouter (1M context,
$0.375/$1.875 per M), and base64 JSON input_audio is the documented primary
path for /audio/transcriptions, with multipart as the OpenAI-compatible
alternative. The spec's stale "unverified" note is corrected, and the provider
now has unit tests covering the request shape, usage parsing, and that a vendor
error body never reaches the thrown message.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 23:05:30 +03:30
8d34def001 improvement: the last flow improved a little. 2026-08-22 20:33:11 +03:30
7f02a84ebf improvement: a flow added to create treatment plan for searched patients with no treatment history. 2026-08-22 20:25:11 +03:30
b1405b22b1 improvement: patient search moved to the top of treatment feature. 2026-08-22 20:11:43 +03:30
50725b7b3f bugfix: no-detail treatment ui made some confusion. it is improved. at least to a degree. 2026-08-22 19:36:37 +03:30
f52ad6b84a bugfix: Treatment detail auto-fill bug fixed. 2026-08-22 18:51:57 +03:30
de46da216f bugfix: FDI tooth chart is now compatible with RTL direction. 2026-08-22 17:49:38 +03:30
d2f07c0ed3 improvement: treatments UI/UX updated again to minimize clicking and scrolling. 2026-08-19 23:59:37 +03:30
96f698be98 improvement: UI/UX improved for v1 standalone treatments/cases feature. 2026-08-19 16:07:32 +03:30
8bfa8c88fe improvement: v1 standalone treatment/case creation made possible. 2026-08-19 15:05:58 +03:30
80167c622c bugfix: appointment hours now use the client timezone on UTC servers.
Logical API errors throw stable codes so users see translated messages instead of a generic bad request.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 01:43:50 +03:30
6d90787c13 improvement: FDI tooth chart overhauled. 2026-08-19 00:06:21 +03:30
9f6ec193d2 feature: version one notification feature implemented. 2026-07-18 01:09:54 +03:30
0740493384 improvement: fdi tooth chart selection modes polished. bugs related to teeth selecyion fixed. 2026-07-18 00:02:40 +03:30
4b2349228a improvement: treatment preview wizard optimized. comments component updated and unified accross the app. 2026-07-17 12:30:43 +03:30
58676f702e improvement: FDI chart tool selection modes updated. shift+ and crtl+ both are assigned with a selection mode. 2026-07-17 11:36:02 +03:30
d2ad1fd7b6 improvement: loading state added to buttons who interact with backend. 2026-07-17 10:58:04 +03:30
68fc9d5d6d improvement: treatment plan turned into a wizard. shift+click control added to FDI tooth chart for cunnected prosthesises. 2026-07-17 00:39:32 +03:30
cf07b4d8a8 improvement: delete action added for unsent treatment details. some edit controls added to details and shipments. 2026-07-16 22:45:37 +03:30
b7682a2d1c fix(treatment): show only past plans in history rail and refresh after lab send.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-14 15:09:10 +03:30
d383a4abc3 improvement: some new gadgets added to dashboard. some new functionality added to existed gadgets. 2026-07-14 03:06:56 +03:30
ec2b23f4b1 improvement: rtl direction, solar calendar and persian formatting added for persian users. 2026-07-14 01:27:11 +03:30
27eae25f61 improvement: lab/clinic commiunication flow completely overhauled. no more shit. 2026-07-13 22:53:23 +03:30
2ad572f4c8 improvement: notify counter badge added to treatment and tasks tabs for upadted and edited cases. 2026-07-13 17:44:44 +03:30
547457d637 improvement: tasks UI responsivness improved for mobile devices. 2026-07-13 16:49:24 +03:30
08a1f34c4f improvement: duedate added for shipped cases. cases and tasks ui and ux updated accordingly. 2026-07-13 16:30:36 +03:30
f28cd06615 improvement: treatment UX fully overhauled. 2026-07-13 01:03:26 +03:30
53b43f2cdb improvement: updated toasts. no invisible toast anymore. 2026-07-12 21:30:28 +03:30
0d3fb0a51d improvement: some files replaced, lots of them i shall say. AGENT.MD file created. some rules and skills added for cursor agent. 2026-07-12 21:08:29 +03:30
fab5111aa8 improvement: error handeling structure changed and unified all across the app. user no longer sees inappropriate messages. 2026-07-12 18:27:38 +03:30
732565b7b4 Merge branch 'master' into feature/mobile-responsive 2026-07-12 10:02:58 +03:30
d79aab907c Some functionality added to dashboard gadgets. 2026-07-12 00:28:43 +03:30
2f7df312c1 app now responsive for mobile and small devices. 2026-07-11 17:10:02 +03:30
ed8ff61205 Shitty gadgets removed. Some useful gadgets added. 2026-07-11 03:12:56 +03:30
be4ac3426e Merge branch 'master' into feature/cases 2026-07-10 15:26:36 +03:30
8d334833ff improvement: all demo bugs fixed. give me more baby. 2026-07-08 02:53:47 +03:30
86b1e3afff improvement: attachment selection for lab dispatch added. attachment preview added to cases feature. 2026-07-07 18:43:10 +03:30
b2d40b3e97 improvement: users can now comment on a case and it's details and have an option to make it visible for clinics too. 2026-07-07 17:14:31 +03:30
cb63ced4e3 improvement: tasks and cases feature updated based on the new prosthesis types and their steps. the whole assignment proccess removed from the flow. 2026-07-07 15:31:09 +03:30
ed7e7b1d8f improvement: all clinic side ui components related to treatment types updated based on the new real world data. 2026-07-07 13:13:04 +03:30
667b08ed0c TreatmentType and ProsthesisType database shcema and data updated. Lab dispatch wired through new data. 2026-07-06 20:40:19 +03:30
feb0b26ad0 improvement: treatment preview and treatment history components overhauled. draft & completed status for treatment plan completely removed from the flow. 2026-06-28 21:45:33 +03:30
94b97aa0fa improvement: lab case dispatch UI improved. 2026-06-28 18:48:06 +03:30
7b8ed48fa0 improvement: treatment plan now save on debounce. save treatment button removed. 2026-06-28 18:08:29 +03:30
7b19d6953c feature: Phase4 - Clinic two-step treatment UI 2026-06-28 17:14:02 +03:30
8b4ef6195d feature: Phase 2- splitting the treatment schema into TreatmentDetail and LabCase. 2026-06-28 15:34:56 +03:30
db4803d463 fix sidebar width change during toggling between tabs. 2026-06-24 17:09:06 +03:30
b2f4dfa4ca feature: localization's first implmentation done. all frontend hardcoded text is now localized. 2026-06-20 14:51:43 +03:30