import React, { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useNavigate } from 'react-router-dom'; import { EyeIcon, TrashIcon, MagnifyingGlassIcon, PlusIcon, BuildingOffice2Icon, } from '@heroicons/react/24/outline'; import { toast } from 'sonner'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { api } from '../lib/api'; import type { ApiResponse, PaginatedResponse } from '../lib/api'; import type { Clinic } from '../types'; import { useAuthStore } from '../stores/authStore'; import MobileInput from '../components/ui/MobileInput'; 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 { latinDigitsField } from '../lib/forms'; const HUES_LIST = [256, 205, 162, 295, 272]; const addSchema = z.object({ owner_mobile: iranMobileSchema, name: z.string().min(2, 'نام الزامی است'), telephone: z.string().optional(), }); type AddForm = z.infer; export default function ClinicsPage() { const navigate = useNavigate(); const qc = useQueryClient(); const primaryRole = useAuthStore(s => s.primaryRole); const isRepresentation = primaryRole === 'representation'; const [page, setPage] = useState(1); const [search, setSearch] = useState(''); const [statusFilter, setStatusFilter] = useState(''); const [deleteTarget, setDeleteTarget] = useState(null); const [addOpen, setAddOpen] = useState(false); const limit = 15; const listBase = isRepresentation ? '/api/v1/representation/clinics' : '/api/v1/admin/clinics'; const { data, isLoading } = useQuery({ queryKey: ['admin-clinics', page, search, statusFilter, isRepresentation], queryFn: () => api.get>( `${listBase}?page=${page}&limit=${limit}` + (search ? `&search=${encodeURIComponent(search)}` : '') + (!isRepresentation && statusFilter !== '' ? `&status=${statusFilter}` : ''), ), }); const deleteMutation = useMutation({ mutationFn: (c: Clinic) => api.delete>(`/api/v1/admin/clinic/${c.uuid}`), onSuccess: () => { toast.success('کلینیک حذف شد'); setDeleteTarget(null); qc.invalidateQueries({ queryKey: ['admin-clinics'] }); }, onError: (err: Error) => toast.error(err.message), }); const toggleMutation = useMutation({ mutationFn: (c: Clinic) => api.patch>(`/api/v1/admin/clinic/${c.uuid}/status`, {}), onSuccess: () => { toast.success('وضعیت کلینیک تغییر کرد'); qc.invalidateQueries({ queryKey: ['admin-clinics'] }); }, onError: (err: Error) => toast.error(err.message), }); const addForm = useForm({ resolver: zodResolver(addSchema) }); const addMutation = useMutation({ mutationFn: (d: AddForm) => api.post>( isRepresentation ? '/api/v1/representation/clinic' : '/api/v1/admin/clinic', d, ), onSuccess: (res) => { toast.success('کلینیک اضافه شد'); setAddOpen(false); addForm.reset(); qc.invalidateQueries({ queryKey: ['admin-clinics'] }); if (!isRepresentation && res?.data?.uuid) navigate(`/admin/clinics/${res.data.uuid}`); }, onError: (err: Error) => toast.error(err.message), }); const items: Clinic[] = data?.data ?? []; const total = data?.meta?.totalRecords ?? 0; return (

کلینیک‌ها

{formatNumber(total)} کلینیک ثبت‌شده
{ setSearch(e.target.value); setPage(1); }} placeholder="جستجو بر اساس نام..." />
{[ { v: '', label: 'همه' }, { v: '1', label: 'فعال' }, { v: '0', label: 'غیرفعال' }, ].map(({ v, label }) => ( ))}
{isLoading ? Array.from({ length: 8 }).map((_, i) => ( {Array.from({ length: 6 }).map((_, j) => ( ))} )) : items.length === 0 ? ( ) : items.map((c) => { const hue = HUES_LIST[(c.uuid?.charCodeAt(0) ?? 0) % HUES_LIST.length]; return ( ); })}
کلینیک مالک تلفن پزشکان وضعیت تاریخ ثبت

هیچ کلینیکی یافت نشد

{c.logo ? ( ) : (
{c.name?.[0] ?? '?'}
)}
{c.name}
{c.owner_mobile ? {c.owner_mobile} : } {c.phone ? {c.phone} : '—'} {formatNumber(c.doctors_count ?? 0)} پزشک {c.is_active ? 'فعال' : 'غیرفعال'} {formatDate(String(c.created_at))}
{/* Add Modal */} {addOpen && (
setAddOpen(false)}>
e.stopPropagation()}>
افزودن کلینیک
addMutation.mutate(d))}>
{addForm.formState.errors.owner_mobile && (
{addForm.formState.errors.owner_mobile.message}
)}
{addForm.formState.errors.name && (
{addForm.formState.errors.name.message}
)}
)} deleteTarget && deleteMutation.mutate(deleteTarget)} onCancel={() => setDeleteTarget(null)} />
); }