import { useEffect, useState } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { toast } from 'sonner'; import { api } from '../../lib/api'; import type { ApiResponse } from '../../lib/api'; import Modal from './Modal'; import Switch from './Switch'; import { usePermissionCatalog } from '../../hooks/usePermissionCatalog'; /** envelope کامل — همان چیزی که بک‌اند برمی‌گرداند، بدون flatten. */ export interface PermissionEnvelope { version: number; resources: Record>; } export interface ClinicDoctorPermissionPayload { uuid: string; clinic_uuid: string; doctor_uuid: string; doctor_name: string; active: boolean; permissions: PermissionEnvelope; } /** ستون‌های ثابتِ جدول؛ هر منبع فقط ستون‌هایی را پر می‌کند که کاتالوگ برایش داده. */ const ACTION_COLUMNS = ['view', 'create', 'update', 'delete', 'cancel', 'update_status']; const ACTION_HEADERS = ['مشاهده', 'ایجاد', 'ویرایش', 'حذف', 'لغو', 'تغییر وضعیت']; export default function DoctorPermissionsModal({ clinicUuid, doctorUuid, doctorName, onClose }: { clinicUuid: string; doctorUuid: string; doctorName: string; onClose: () => void; }) { const qc = useQueryClient(); const catalog = usePermissionCatalog(); const [resources, setResources] = useState({}); const [active, setActive] = useState(true); const permQ = useQuery({ queryKey: ['clinic-doctor-permissions', clinicUuid, doctorUuid], queryFn: () => api.get>( `/api/v1/admin/clinic/${clinicUuid}/doctor/${doctorUuid}/permissions`, ), }); useEffect(() => { const payload = permQ.data?.data; if (!payload) return; setResources(payload.permissions?.resources ?? {}); setActive(payload.active); }, [permQ.data]); const saveMut = useMutation({ mutationFn: () => api.patch>( `/api/v1/admin/clinic/${clinicUuid}/doctor/${doctorUuid}/permissions`, { permissions: { resources }, active }, ), onSuccess: () => { toast.success('دسترسی‌های پزشک ذخیره شد'); qc.invalidateQueries({ queryKey: ['clinic-doctor-permissions', clinicUuid, doctorUuid] }); qc.invalidateQueries({ queryKey: ['clinic-doctors', clinicUuid] }); onClose(); }, onError: (e: Error) => toast.error(e.message), }); const toggle = (resource: string, action: string) => { setResources(prev => ({ ...prev, [resource]: { ...prev[resource], [action]: !prev[resource]?.[action] }, })); }; return ( } > {permQ.isLoading || catalog.isLoading ? (

در حال بارگذاری...

) : catalog.isError ? (

فهرست دسترسی‌ها خوانده نشد. صفحه را دوباره باز کنید.

) : ( <>
{ACTION_HEADERS.map(h => ( ))} {catalog.resources.map(resource => { const available = new Set(resource.actions.map(a => a.key)); return ( {ACTION_COLUMNS.map(action => { if (!available.has(action)) { return ; } return ( ); })} ); })}
بخش{h}
{resource.label} {/* سوییچ در سلول جدول: بدون برچسبِ دیداری، پس نامِ دسترسی‌پذیر از ترکیب بخش و ستون ساخته می‌شود. */}
toggle(resource.key, action)} ariaLabel={`${resource.label} — ${ACTION_HEADERS[ACTION_COLUMNS.indexOf(action)]}`} />

این دسترسی‌ها فقط داخل همین کلینیک اعمال می‌شوند؛ مطب شخصی پزشک تحت تأثیر قرار نمی‌گیرد.

)}
); }