Files
clinicpro/assets/admin/pages/PracticeDomainSettingsPage.tsx
T

104 lines
4.7 KiB
TypeScript

import { useEffect, useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import { api, ApiError, type ApiResponse } from '../lib/api';
import SettingsLayout from '../components/layout/SettingsLayout';
import SearchableSelect from '../components/ui/SearchableSelect';
import { useAuthStore } from '../stores/authStore';
import type { PracticeDomain } from '../types';
/**
* حوزهٔ فعالیت کلینیک.
*
* تخصصِ پزشکی نیست — آن برچسبی است برای سایت عمومی. این یک کلید پیکربندی است که
* تعیین می‌کند کدام workflow درمان صدا زده شود، پس کدش پایدار می‌ماند و فقط ادمین
* پلتفرم می‌تواند حوزهٔ تازه بسازد.
*/
export default function PracticeDomainSettingsPage() {
const qc = useQueryClient();
// محیط جاری با `db_uuid` شناخته می‌شود؛ همان uuid کلینیک است.
const clinicUuid = useAuthStore((s) => s.context?.db_uuid ?? null);
const { data: domainsData, isLoading } = useQuery({
queryKey: ['practice-domains'],
queryFn: () => api.get<ApiResponse<PracticeDomain[]>>('/api/v1/practice-domains'),
staleTime: 300_000,
});
const { data: clinicData } = useQuery({
queryKey: ['clinic-practice-domain', clinicUuid],
queryFn: () => api.get<ApiResponse<{ data: { practice_domain: PracticeDomain | null } }>>(
`/api/v1/clinic/${clinicUuid}`,
),
enabled: !!clinicUuid,
});
const current = clinicData?.data?.data?.practice_domain ?? null;
const [selected, setSelected] = useState<string | null>(null);
useEffect(() => setSelected(current?.uuid ?? null), [current]);
const save = useMutation({
mutationFn: (uuid: string | null) => api.patch<ApiResponse<unknown>>(
`/api/v1/clinic/${clinicUuid}`,
{ practice_domain_uuid: uuid ?? '' },
),
onSuccess: () => {
toast.success('حوزهٔ فعالیت ذخیره شد');
qc.invalidateQueries({ queryKey: ['clinic-practice-domain', clinicUuid] });
},
onError: (e) => toast.error(e instanceof ApiError ? e.message : 'ذخیرهٔ حوزهٔ فعالیت ناموفق بود'),
});
const domains = domainsData?.data ?? [];
const options = domains.map((d) => ({ value: d.uuid, label: d.name }));
const chosen = domains.find((d) => d.uuid === selected) ?? null;
return (
// پوستهٔ تنظیمات، مثل بقیهٔ صفحات همین منو. بدون آن، این صفحه تنها صفحه‌ای بود که
// منوی تنظیمات را نشان نمی‌داد و کاربر برای رفتن به بخش بعدی باید «بازگشت» می‌زد.
<SettingsLayout active="practice-domain">
<div className="card card-pad" style={{ display: 'grid', gap: 14, maxWidth: 560 }}>
<h1 className="section-title" style={{ margin: 0 }}>حوزهٔ فعالیت</h1>
<p style={{ margin: 0, fontSize: 12.5, color: 'var(--text-3)', lineHeight: 1.9 }}>
حوزهٔ فعالیت تعیین می‌کند سیستم چه فرآیند درمانی برای کلینیک شما اجرا کند. این با
«تخصص» فرق دارد: تخصص برچسبی است که در سایت عمومی دیده می‌شود، این یک تنظیم است.
انتخاب‌نکردنش خطا نیست و کلینیک مثل امروز کار می‌کند.
</p>
{isLoading ? (
<span style={{ fontSize: 13, color: 'var(--text-3)' }}>در حال بارگذاری...</span>
) : (
<>
<SearchableSelect
options={options}
value={selected}
onChange={(v) => setSelected(v === null ? null : String(v))}
placeholder="حوزه‌ای انتخاب نشده"
isClearable
ariaLabel="حوزهٔ فعالیت کلینیک"
/>
{chosen && !chosen.has_workflow && (
<span style={{ fontSize: 12.5, color: 'var(--warning)' }}>
برای این حوزه هنوز فرآیند اختصاصی تعریف نشده است؛ رفتار پیش‌فرض اعمال می‌شود.
</span>
)}
<button
type="button"
className="btn primary"
disabled={save.isPending || !clinicUuid}
onClick={() => save.mutate(selected)}
style={{ justifySelf: 'start' }}
>
{save.isPending ? 'در حال ذخیره...' : 'ذخیره'}
</button>
</>
)}
</div>
</SettingsLayout>
);
}