feat(appointments): resource tabs follow their supervising doctor

Resource tabs now sit under the selected doctor and list only the resources that
doctor supervises, so moving between a doctor's own appointments and the devices
under them is one row of tabs rather than a flat list of everything.

The booking modal reads the doctor from the resource's supervisor instead of
asking again. The doctor↔resource relation is defined once, on the resource, and
repeating the question here would have made a second source of truth. A resource
whose supervisor was removed is blocked with a message pointing at the fix rather
than a silently disabled button.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
hamed
2026-08-03 12:25:10 +03:30
co-authored by Claude Opus 5
parent 4f4c396754
commit cadf18d07a
4 changed files with 66 additions and 35 deletions
+18 -5
View File
@@ -527,6 +527,19 @@ export default function AppointmentsPage() {
const selectedResourceUuid = urlState.resource;
const { resources: bookableResources } = useResources({ active: '1' });
/**
* منابعی که پزشکِ انتخاب‌شده ناظرشان است.
*
* وقتی خودِ تب منبع فعال است `selectedDoctorUuid` خالی می‌شود، پس ناظرِ همان منبع
* مبنا قرار می‌گیرد — وگرنه نوار منابع زیر پای کاربر خالی می‌شد.
*/
const supervisorFilterUuid = selectedDoctorUuid
|| bookableResources.find((r) => r.uuid === selectedResourceUuid)?.supervisor?.uuid
|| '';
const supervisedResources = supervisorFilterUuid
? bookableResources.filter((r) => r.supervisor?.uuid === supervisorFilterUuid)
: [];
const [bookingResource, setBookingResource] = useState<ClinicResource | null>(null);
const activeResource = bookableResources.find((r) => r.uuid === selectedResourceUuid) ?? null;
@@ -867,13 +880,13 @@ export default function AppointmentsPage() {
/>
)}
{/* منابع مثل پزشکان تب خودشان را دارند: نوبتِ «لیزر CO2» به دستگاه تعلق دارد،
نه به پزشکی که پشتش ایستاده. */}
{bookableResources.length > 0 && (
{/* منابعِ همین پزشک، نه همهٔ منابع: ارتباط پزشک↔منبع روی خودِ منبع تعریف شده
(پزشک ناظر)، پس کاربر بین نوبت‌های پزشک و دستگاه‌های تحت نظرش جابه‌جا می‌شود. */}
{supervisedResources.length > 0 && (
<div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '0 16px', borderBottom: '1px solid var(--border)' }}>
<span style={{ fontSize: 12, color: 'var(--text-3)', flexShrink: 0 }}>منابع</span>
<span style={{ fontSize: 12, color: 'var(--text-3)', flexShrink: 0 }}>منابعِ این پزشک</span>
<DoctorTabs
doctors={bookableResources.map((r) => ({ uuid: r.uuid, name: r.name }))}
doctors={supervisedResources.map((r) => ({ uuid: r.uuid, name: r.name }))}
selected={selectedResourceUuid}
onSelect={selectResource}
showAll={false}