feat(admin): table/card views for treatment cases, matching the patients list

The list was cards only, so comparing courses across patients meant reading four
stacked blocks instead of scanning columns. It now has the same table/card
toggle the patients page uses, reusing that page's toggle icons and keeping the
choice in the URL so back and refresh hold it. Table is the default here: the
operator, status and session progress are the columns a manager scans.

Both views derive the operator the same way, through one helper — history
(performed_by) when a session has been done, otherwise the plan
(assigned_staff), labelled as not yet performed.

Also fixes a three-states slip in the operator picker I added last time: it
rendered "no staff defined" while the staff list was still loading, which is
what an empty list looks like from the user's side. Loading now says so.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
hamed
2026-08-07 15:13:27 +03:30
co-authored by Claude Opus 5
parent 9cabb28355
commit d3f7812d15
3 changed files with 158 additions and 13 deletions
@@ -67,6 +67,7 @@ export default function TreatmentCaseEditModal({ caseUuid, onClose }: {
doctors={doctorsQ.data?.data?.data ?? []}
doctorsLoading={doctorsQ.isLoading}
staff={staffQ.data?.data ?? []}
staffLoading={staffQ.isLoading}
onSaved={() => {
qc.invalidateQueries({ queryKey: ['treatment-cases'] });
qc.invalidateQueries({ queryKey: ['treatment-case', caseUuid] });
@@ -79,11 +80,12 @@ export default function TreatmentCaseEditModal({ caseUuid, onClose }: {
);
}
function EditForm({ detail, doctors, doctorsLoading, staff, onSaved, onClose }: {
function EditForm({ detail, doctors, doctorsLoading, staff, staffLoading, onSaved, onClose }: {
detail: TreatmentCaseDetail;
doctors: DoctorRow[];
doctorsLoading: boolean;
staff: StaffRow[];
staffLoading: boolean;
onSaved: () => void;
onClose: () => void;
}) {
@@ -208,7 +210,11 @@ function EditForm({ detail, doctors, doctorsLoading, staff, onSaved, onClose }:
<div className="field-block">
<label>اپراتور</label>
{staff.length === 0 ? (
{/* «در حال خواندن» با «تعریف نشده» یکی نیست؛ بدون این تفکیک، فهرستِ هنوز
نیامده به‌صورت «پرسنلی ندارید» خوانده می‌شد. */}
{staffLoading ? (
<span className="field-hint">در حال خواندن فهرست پرسنل</span>
) : staff.length === 0 ? (
<span className="field-hint">پرسنلی در این محیط تعریف نشده است.</span>
) : (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>