diff --git a/assets/admin/components/ChangeLoginMobileModal.tsx b/assets/admin/components/ChangeLoginMobileModal.tsx new file mode 100644 index 00000000..6b2587ca --- /dev/null +++ b/assets/admin/components/ChangeLoginMobileModal.tsx @@ -0,0 +1,81 @@ +import { useEffect, useState } from 'react'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { toast } from 'sonner'; +import { api } from '../lib/api'; +import { digitsOnly } from '../lib/utils'; +import Modal from './ui/Modal'; + +interface Props { + /** `null` یعنی مودال بسته است. */ + target: { uuid: string; name: string; mobile_number?: string | null } | null; + /** `doctors` → /api/v1/admin/doctors/{uuid}/mobile · `clinic` → /api/v1/admin/clinic/{uuid}/mobile */ + resource: 'doctors' | 'clinic'; + /** کلید کوئریِ لیستی که بعد از تغییر باید invalidate شود. */ + queryKey: unknown[]; + onClose: () => void; +} + +/** + * تغییر شمارهٔ **ورود** پزشک/کلینیک توسط مدیر کل. شماره هویتِ ورود کاربر است، پس + * سرور یکتا بودن را کنترل می‌کند و اینجا فقط قالبِ ۰۹ + ۱۱ رقم اعتبارسنجی می‌شود. + */ +export default function ChangeLoginMobileModal({ target, resource, queryKey, onClose }: Props) { + const qc = useQueryClient(); + const [mobile, setMobile] = useState(''); + + useEffect(() => { + setMobile(target?.mobile_number ?? ''); + }, [target]); + + const save = useMutation({ + mutationFn: () => api.patch(`/api/v1/admin/${resource}/${target!.uuid}/mobile`, { mobile_number: mobile }), + onSuccess: () => { + toast.success('شماره موبایل تغییر کرد'); + qc.invalidateQueries({ queryKey }); + onClose(); + }, + onError: (e: Error) => toast.error(e.message), + }); + + const invalid = !/^09\d{9}$/.test(mobile); + + return ( + + + + + } + > +

+ این شماره، شمارهٔ ورود به پنل است. پس از تغییر، ورود فقط با شمارهٔ جدید ممکن + خواهد بود و شماره باید در کل سامانه یکتا باشد. +

+ +
+ + setMobile(digitsOnly(e.target.value, 11))} + /> + {mobile !== '' && invalid &&

شماره باید با ۰۹ شروع شود و ۱۱ رقم باشد

} +
+
+ ); +} diff --git a/assets/admin/pages/ClinicsPage.tsx b/assets/admin/pages/ClinicsPage.tsx index 76dd11a8..192379bc 100644 --- a/assets/admin/pages/ClinicsPage.tsx +++ b/assets/admin/pages/ClinicsPage.tsx @@ -7,6 +7,7 @@ import { MagnifyingGlassIcon, PlusIcon, BuildingOffice2Icon, + DevicePhoneMobileIcon, } from '@heroicons/react/24/outline'; import { toast } from 'sonner'; import { useForm } from 'react-hook-form'; @@ -21,6 +22,7 @@ import Portal from '../components/ui/Portal'; import { formatDate, formatNumber, iranMobileSchema } from '../lib/utils'; import Pagination from '../components/ui/Pagination'; import ConfirmDialog from '../components/ui/ConfirmDialog'; +import ChangeLoginMobileModal from '../components/ChangeLoginMobileModal'; import { latinDigitsField } from '../lib/forms'; const HUES_LIST = [256, 205, 162, 295, 272]; @@ -41,6 +43,7 @@ export default function ClinicsPage() { const [search, setSearch] = useState(''); const [statusFilter, setStatusFilter] = useState(''); const [deleteTarget, setDeleteTarget] = useState(null); + const [mobileTarget, setMobileTarget] = useState<{ uuid: string; name: string; mobile_number?: string | null } | null>(null); const [addOpen, setAddOpen] = useState(false); const limit = 15; @@ -217,6 +220,13 @@ export default function ClinicsPage() { > + +