Commit Graph
4 Commits
Author SHA1 Message Date
hamedandClaude Opus 5 250e0b0813 feat(treatment): filter treatment cases by patient record
The list could be narrowed by status, search and open-date, but not by patient
— so a patient's own file had no way to ask which courses belong to them.
`?record=` adds that bound.

patientRecord is joined once and shared with the search branch; joining it twice
under the same alias is a DQL error, and search already needed it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 16:05:35 +03:30
hamedandClaude Opus 5 b78f7311cf feat(treatment): per-case operators, shown on the list and searchable
A treatment case said which doctor supervised it but never who actually did the
work, so the list could not answer the first question a manager asks about a
course: who performed it.

Two separate things now travel with the case. `performed_by` is history —
derived from the sessions' performedBy, so it only ever reports what happened.
`assigned_staff` is plan — a new treatment_case_staff table, editable from the
modal, saying who is meant to handle this patient's course. The card shows the
first and falls back to the second while nothing has been performed yet.

Search matches both. A manager typing an operator's name wants that person's
work, and work already done is part of it.

Assignment also narrows the operator queue: a case with assigned staff shows its
sessions only to those people, because a patient who started a multi-session
course with one operator should keep them. An unassigned case keeps the existing
protocol rule, and an empty list means "anyone the protocol allows" rather than
"nobody" — the same "no rows is not a restriction" convention used elsewhere.

Unlike areas, removing an operator erases nothing: a finished session carries its
real operator on itself and never consults this list.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 14:55:01 +03:30
hamedandClaude Opus 5 73963020e2 feat(treatment): date-range filter on treatment cases, and time on the start stamp
The list could be narrowed by status and by search but not by when a case
opened, which is the one axis a clinic actually reports on. `from` and `to`
(YYYY-MM-DD) now bound `opened_at`, using the same strtotime day-boundary
convention the appointment date filters already use under the app's global
Tehran timezone. A malformed value is ignored rather than erroring — this is a
filter, not a form field.

Both bounds live in the URL via useUrlState, so back and refresh keep the range.
The two date inputs and the "تا" between them are one nowrap unit; letting them
wrap separately orphaned the word from its field on a 390px screen.

The card's "شروع" showed only the Jalali date, so several cases opened on the
same day were indistinguishable on that line too. It now uses formatDateTime.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 13:57:14 +03:30
hamedandClaude Opus 5 952e09bd6a feat(treatment): search and edit for treatment cases
The list had no way to tell two cases apart. TreatmentCase::toArray() carried
no patient, so four cases of the same service rendered as four identical
cards — same service, same supervisor, same date, same areas. Search would have
been meaningless without fixing that first, so the payload now carries the
patient (name, mobile, record number) and the card leads with the name.

Search: `?q=` on the list endpoint, matching patient name, mobile, national
code, record number and service name — the same keys a secretary already types
into the booking form. It lives in the URL via useUrlState, debounced, so back
and refresh keep the view.

Edit: PATCH /api/v1/treatment-case/{uuid} covering status, supervising doctor,
areas and session count, driven from a modal on the list. Rules live in
TreatmentCaseEditor, not the controller, around one boundary: no edit may
overwrite work already done. An area with session records cannot be removed, and
the session count cannot drop below the sessions that are booked or finished —
both 409, both tested. Reopening a closed case clears closed_at.

`areas[]` now also exposes `category_uuid`; the edit form selects catalog
categories, while `uuid` identifies the snapshot row.

Page fixes from the redesign checklist: the status filter was a hand-rolled
primary/secondary button pair, now `.seg` with `.on`; the raw `<progress>` bar
took the browser's own appearance and ignored the theme tokens, now a token-
styled bar with an explicit progressbar role; session counts go through
formatNumber; a failed request rendered as "no cases found", which reads as an
empty clinic rather than a broken one, and an empty search now says so in its
own words.

Adds the test files neither the page nor the case editor had.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 13:48:57 +03:30