refactor(resource): drop the branch domain from resources
Resources never needed a branch: devices and rooms belong to the clinic itself, and the picker always had exactly one option — a mandatory click that decided nothing. - `address_uuid` is now optional on resource and pool creation; when it is missing the environment's own address is used. Clients still sending it keep working. - The panel no longer asks for or displays a branch anywhere: resource form, list column and filter, pool form and column, detail row, and the resource-first booking page. - Availability no longer gates on `doctor_addresses.active`. That gate shut down every device of a clinic whose address row happened to be inactive, with a message no page in the panel could act on — no endpoint writes that column at all. `address_id` stays on the resource: the timezone and the tenant pair are derived from it. It is simply no longer the user's decision. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@ import Modal from '../ui/Modal';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import SearchableSelect from '../ui/SearchableSelect';
|
||||
import { api, type ApiResponse } from '../../lib/api';
|
||||
import type { Branch, ClinicResource, ResourcePayload, ResourceType } from '../../types';
|
||||
import type { ClinicResource, ResourcePayload, ResourceType } from '../../types';
|
||||
import { useResourceDetail } from '../../hooks/useResources';
|
||||
import { formatNumber } from '../../lib/utils';
|
||||
|
||||
@@ -15,7 +15,6 @@ type AttributeRow = { key: string; value: string };
|
||||
interface Props {
|
||||
open: boolean;
|
||||
resource: ClinicResource | null;
|
||||
addresses: Branch[];
|
||||
types: ResourceType[];
|
||||
saving: boolean;
|
||||
onClose: () => void;
|
||||
@@ -23,7 +22,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function ResourceFormModal({
|
||||
open, resource, addresses, types, saving, onClose, onSave,
|
||||
open, resource, types, saving, onClose, onSave,
|
||||
}: Props) {
|
||||
// شمار نوبتهای آینده فقط برای منبعِ موجود معنا دارد و فقط وقتی مودال باز است.
|
||||
const { upcomingAppointments: upcoming } = useResourceDetail(open ? resource?.uuid : undefined);
|
||||
@@ -39,7 +38,6 @@ export default function ResourceFormModal({
|
||||
const doctorsLoading = doctorsQuery.isLoading;
|
||||
|
||||
const [name, setName] = useState('');
|
||||
const [addressUuid, setAddressUuid] = useState<string | null>(null);
|
||||
const [typeUuid, setTypeUuid] = useState<string | null>(null);
|
||||
const [supervisorUuid, setSupervisorUuid] = useState<string | null>(null);
|
||||
const [capacity, setCapacity] = useState('1');
|
||||
@@ -51,7 +49,6 @@ export default function ResourceFormModal({
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
setName(resource?.name ?? '');
|
||||
setAddressUuid(resource?.address_uuid ?? null);
|
||||
setTypeUuid(resource?.type_uuid ?? null);
|
||||
setSupervisorUuid(resource?.supervisor?.uuid ?? null);
|
||||
setCapacity(String(resource?.capacity ?? 1));
|
||||
@@ -68,7 +65,7 @@ export default function ResourceFormModal({
|
||||
const invalid =
|
||||
name.trim() === '' ||
|
||||
!supervisorUuid ||
|
||||
(!isEdit && (!addressUuid || !typeUuid)) ||
|
||||
(!isEdit && !typeUuid) ||
|
||||
!Number.isFinite(parsedCapacity) ||
|
||||
parsedCapacity < 1;
|
||||
|
||||
@@ -88,10 +85,10 @@ export default function ResourceFormModal({
|
||||
supervisor_doctor_uuid: supervisorUuid!,
|
||||
};
|
||||
|
||||
// شعبه و نوع فقط هنگام ساخت فرستاده میشوند؛ جفت محیطِ منبع از آدرس مشتق شده و
|
||||
// جابهجا کردنش یعنی همان منبع در محیط دیگری ظاهر شود.
|
||||
// نوع فقط هنگام ساخت فرستاده میشود؛ جفت محیطِ منبع از آدرسِ محیط مشتق میشود و
|
||||
// جابهجا کردنش یعنی همان منبع در محیط دیگری ظاهر شود. آدرس پرسیده نمیشود:
|
||||
// منابع دامنهٔ شعبه ندارند و سرور آدرسِ خودِ کلینیک را برمیدارد.
|
||||
if (!isEdit) {
|
||||
payload.address_uuid = addressUuid!;
|
||||
payload.type_uuid = typeUuid!;
|
||||
}
|
||||
|
||||
@@ -106,16 +103,6 @@ export default function ResourceFormModal({
|
||||
</Field>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: 12 }}>
|
||||
<Field label="شعبه">
|
||||
<SearchableSelect
|
||||
options={addresses.map((b) => ({ value: b.uuid, label: b.name || 'بدون نام' }))}
|
||||
value={addressUuid}
|
||||
onChange={(v) => setAddressUuid(v ? String(v) : null)}
|
||||
placeholder="شعبه را انتخاب کنید"
|
||||
isDisabled={isEdit}
|
||||
height={38}
|
||||
/>
|
||||
</Field>
|
||||
<Field label="نوع منبع">
|
||||
<SearchableSelect
|
||||
options={types.map((t) => ({ value: t.uuid, label: t.name }))}
|
||||
@@ -126,8 +113,8 @@ export default function ResourceFormModal({
|
||||
height={38}
|
||||
/>
|
||||
</Field>
|
||||
{/* ناظر برخلاف شعبه و نوع در ویرایش هم قابل تغییر است: پزشکِ مسئولِ یک
|
||||
دستگاه عوض میشود، ولی محیطِ منبع نه. */}
|
||||
{/* ناظر برخلاف نوع در ویرایش هم قابل تغییر است: پزشکِ مسئولِ یک دستگاه
|
||||
عوض میشود، ولی محیطِ منبع نه. */}
|
||||
<Field label="پزشک ناظر">
|
||||
<SearchableSelect
|
||||
options={doctors.map((d) => ({ value: d.uuid, label: d.name }))}
|
||||
@@ -142,7 +129,7 @@ export default function ResourceFormModal({
|
||||
|
||||
{isEdit && (
|
||||
<p style={{ fontSize: 12, color: 'var(--text-3)', margin: 0 }}>
|
||||
شعبه و نوع منبع پس از ساخت تغییر نمیکنند؛ برای جابهجایی، منبع تازه بسازید.
|
||||
نوع منبع پس از ساخت تغییر نمیکند؛ برای تغییرش، منبع تازه بسازید.
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user