import React, { useState, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import { useQuery, useMutation } from '@tanstack/react-query'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { ArrowRightIcon, UserPlusIcon } from '@heroicons/react/24/outline'; import { toast } from 'sonner'; import { api } from '../lib/api'; import type { ApiResponse } from '../lib/api'; import { formatNumber } from '../lib/utils'; // ── Types ──────────────────────────────────────────────────────────────── interface SpecialtyOption { id: number; uuid: string; name: string } // ── Schema ─────────────────────────────────────────────────────────────── const schema = z.object({ mobile: z.string().min(10, 'شماره موبایل معتبر نیست').max(15), name: z.string().min(2, 'نام حداقل ۲ کاراکتر'), gender: z.enum(['man', 'woman']).optional().or(z.literal('')), degree: z.string().optional().or(z.literal('')), medical_system_code: z.string().max(30).optional().or(z.literal('')), info: z.string().max(2000).optional().or(z.literal('')), specialties: z.array(z.number()).optional(), }); type FormValues = z.infer; // ── Constants ───────────────────────────────────────────────────────────── const DEGREE_OPTIONS = [ { value: 'general', label: 'عمومی' }, { value: 'specialist', label: 'متخصص' }, { value: 'expert', label: 'فوق تخصص' }, { value: 'subspecialistplus', label: 'فلوشیپ' }, ]; const GENDER_OPTIONS = [ { value: 'man', label: 'مرد' }, { value: 'woman', label: 'زن' }, ]; // ── Specialty Picker ────────────────────────────────────────────────────── function SpecialtyPicker({ selected, onChange, specialties }: { selected: number[]; onChange: (ids: number[]) => void; specialties: SpecialtyOption[]; }) { const [q, setQ] = useState(''); const filtered = useMemo(() => specialties.filter(s => s.name.includes(q)), [specialties, q]); const toggle = (id: number) => onChange(selected.includes(id) ? selected.filter(x => x !== id) : [...selected, id]); return (
setQ(e.target.value)} placeholder="جستجوی تخصص..." className="cp-input text-sm h-8" />
{selected.length > 0 && (
{selected.map(id => { const s = specialties.find(x => x.id === id); if (!s) return null; return ( {s.name} ); })}
)}
{filtered.slice(0, 60).map(s => ( ))} {filtered.length === 0 &&

نتیجه‌ای یافت نشد

}
); } // ── Page ────────────────────────────────────────────────────────────────── export default function DoctorFormPage() { const navigate = useNavigate(); const [selectedSpecialties, setSelectedSpecialties] = useState([]); const specialtiesQ = useQuery({ queryKey: ['specialties-list'], queryFn: () => api.get>('/api/v1/specialties'), staleTime: 300_000, }); const specialties: SpecialtyOption[] = useMemo( () => (specialtiesQ.data?.data as any)?.data ?? specialtiesQ.data?.data ?? [], [specialtiesQ.data] ); const { register, handleSubmit, formState: { errors } } = useForm({ resolver: zodResolver(schema), defaultValues: { specialties: [] }, }); const createMut = useMutation({ mutationFn: (values: FormValues) => api.post>('/api/v1/admin/doctors', { mobile: values.mobile, name: values.name, gender: values.gender || undefined, degree: values.degree || undefined, medical_system_code: values.medical_system_code || undefined, info: values.info || undefined, specialties: selectedSpecialties, }), onSuccess: (res) => { const uuid = (res?.data as any)?.uuid ?? res?.data?.uuid; toast.success('پزشک با موفقیت اضافه شد'); if (uuid) navigate(`/admin/doctors/${uuid}`); else navigate('/admin/doctors'); }, onError: (e: Error) => toast.error(e.message), }); const onSubmit = (values: FormValues) => createMut.mutate({ ...values, specialties: selectedSpecialties }); return (
{/* Breadcrumb */}
/ افزودن پزشک جدید
{/* Header card */}

افزودن پزشک جدید

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

{/* Form */}
{/* Account info */}

اطلاعات حساب

{/* Mobile */}
{errors.mobile &&

{errors.mobile.message}

}

اگر کاربر با این شماره وجود داشته باشد، پروفایل پزشک به آن متصل می‌شود

{/* Name */}
{errors.name &&

{errors.name.message}

}
{/* Professional info */}

اطلاعات حرفه‌ای

{/* Gender */}
{/* Degree */}
{/* Medical system code */}
{/* Bio */}