Files
clinicpro/.claude/prompt/new-visit-modal-ux.md
hamedandClaude Opus 4.8 59fb590d65 feat: redesign new-visit modal with insurance selects and live breakdown
Sectioned layout (insurance & price / services / payment / summary),
base+supplementary insurance selects auto-filling visit price and
discount from insurance-pricing, live cost breakdown, unified تومان unit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 15:15:12 +03:30

5.5 KiB

بازطراحی UI/UX مودال «ثبت مراجعه جدید»

پروژه

clinicpro (admin frontend)

زمینه

مودال «ثبت مراجعه جدید» در صفحه‌ی پرونده بیمار، UX ضعیفی دارد: فیلدها بدون گروه‌بندی، label و input بدون فاصله‌ی منطقی، بخش خدمات و خلاصه‌ی قیمت بی‌سازمان، و ارتباط بین «قیمت ویزیت / تخفیف بیمه پایه / تخفیف مکمل» با بیمه‌ی واقعی بیمار مشخص نیست. (تصویر فعلی توسط کاربر ارائه شده.)

مشکل / هدف

بازطراحی مودال با اصول UI/UX حرفه‌ای:

  • گروه‌بندی منطقی: «بیمه و مبلغ» / «خدمات» / «پرداخت و یادداشت» / «خلاصه»
  • انتخاب بیمه‌ی پایه و مکمل به‌صورت select (از بیمه‌های entity)، و پرکردن خودکار قیمت ویزیت و تخفیف/سهم بر اساس قیمت‌گذاری بیمه‌ی پروفایل (خروجی پرامپت insurance-visit-pricing.md)
  • نمایش زنده‌ی محاسبه: آزاد → با بیمه پایه → با بیمه مکمل → مبلغ نهایی
  • واحد پول یکدست (تومان یا ریال — یکی، نه مخلوط؛ الان «ریال» در ورودی و «تومان» در خلاصه مخلوط است)
  • فاصله‌گذاری، عنوان بخش‌ها، حالت‌های loading/disabled درست

فایل‌های مرتبط

فایل نقش
assets/admin/pages/MyPatientsPage.tsx مودال sessionModal (حدود خط ۸۰۹ به بعد) و handleSubmitSession
assets/admin/components/ui/Modal.tsx کامپوننت مودال (props: size = sm/md/lg/xl)
assets/admin/components/ui/SearchableSelect.tsx select قابل‌جستجو (برای بیمه/خدمات)
assets/admin/lib/utils.ts formatRial, formatNumber
src/Patient/Controller/PatientController.php endpoint POST /api/v1/patient/{uuid}/session
src/Patient/Service/PatientService.php محاسبه‌ی نهایی سمت سرور

وضعیت فعلی

  • اسکیمای فرم:
const sessionSchema = z.object({
    visit_price_rials: z.coerce.number().min(0),
    base_insurance_discount_percent: z.coerce.number().min(0).max(100),
    supplementary_discount_percent: z.coerce.number().min(0).max(100),
    payment_method: z.enum(["cash", "card", "insurance", "online", "pending"]),
    notes: z.string().optional(),
});
  • محاسبه‌ی قیمت سمت کلاینت:
function calcFinalPrice(visitPrice, baseDiscount, suppDiscount, servicesTotal) {
    const afterBase = visitPrice * (1 - baseDiscount / 100);
    const afterSupp = afterBase * (1 - suppDiscount / 100);
    return Math.round(afterSupp) + servicesTotal;
}
  • خلاصه‌ی پایین مودال «جمع خدمات» و «مبلغ نهایی» را با «تومان» نشان می‌دهد ولی ورودی‌ها «ریال» هستند — ناهماهنگ.
  • backend (PatientService::createSession) همین فیلدها + insurance_base_id / insurance_supplementary_id را می‌پذیرد (موجودیت PatientSession این دو ستون را دارد) اما فرم فعلی آن‌ها را ارسال نمی‌کند.

وظایف

۱. ساختار بصری مودال

مودال را به بخش‌های واضح با عنوان تقسیم کن (می‌توانی size="lg" بدهی):

  1. بیمه و مبلغ ویزیت: select بیمه‌ی پایه + select بیمه‌ی مکمل + قیمت ویزیت + تخفیف/سهم
  2. خدمات: انتخاب بخش/سرویس + chipهای انتخاب‌شده (الگوی فعلی، فقط منظم‌تر)
  3. پرداخت و یادداشت: روش پرداخت + یادداشت
  4. خلاصه: آزاد / با بیمه پایه / با بیمه مکمل / جمع خدمات / مبلغ نهایی

۲. اتصال بیمه به قیمت‌گذاری پروفایل

  • بیمه‌های entity و قیمت‌گذاری را از endpoint پرامپت insurance-visit-pricing.md (GET /api/v1/insurance-pricing) بگیر.
  • با انتخاب بیمه‌ی پایه/مکمل، قیمت ویزیت آزاد و سهم بیمار خودکار پر شود (کاربر بتواند دستی override کند).
  • insurance_base_id و insurance_supplementary_id را در body ارسال کن (backend از قبل پشتیبانی می‌کند).

۳. واحد پول یکدست

همه‌جا یک واحد. توصیه: نمایش به تومان با formatRial اگر این util تومان می‌دهد را بررسی کن؛ ورودی و خلاصه باید یکی باشند.

۴. تست

ddev exec npx tsc --noEmit و ddev exec yarn dev؛ بدون خطا.

نکات مهم

  • وابسته به insurance-visit-pricing.md؛ اگر آن endpoint هنوز نیست، حداقل ساختار UI و select بیمه‌ها از GET /api/v1/insurances را پیاده کن و auto-fill را با TODO علامت بزن.
  • فرم با React Hook Form + Zod؛ server state با TanStack Query.
  • از کامپوننت‌های ui/ موجود استفاده کن؛ کتابخانه‌ی CSS جدید اضافه نکن؛ RTL.
  • این تغییر صرفاً frontend است؛ تغییر API لازم نیست (مگر اینکه فیلد بیمه‌ی session در پاسخ کم باشد).