Files
clinicpro/.claude/prompt/settings-menu-pixel-perfect.md
T

10 KiB

پیکسل‌به‌پیکسل کردن منوی تنظیمات + ریشه‌گرفتن رنگ‌ها از شخصی‌سازی

پروژه

clinicpro (فقط پنل ادمین React — تغییر backend ندارد).

اپ دسکتاپ clinic-pro-tauri فقط مرجع بصری است، نه هدف تغییر. صفحه‌ی مرجع: http://127.0.0.1:5170/setting/purchase-subscription (کد آن: clinic-pro-tauri/src/components/setting/listMenu/purchaseSubscription/PurchaseSubscriptionSidebar.jsx)

زمینه

پنل ادمین clinicpro یک ناحیه‌ی «تنظیمات» دارد که کنار محتوا یک ساید‌منوی مشترک (PurchaseSubscriptionSidebar) نمایش می‌دهد. این منو در همه‌ی صفحات تنظیمات از طریق SettingsLayout رندر می‌شود.

  • صفحه‌ی /admin/subscription (SubscriptionPage.tsx) درست و پیکسل‌به‌پیکسل است — مرجع درون‌پروژه‌ای.
  • صفحه‌ی /admin/appointment-settings (AppointmentSettingsPage.tsx) خراب است: محتوا روی زمینه‌ی خاکستری #fafafa نشسته، پنل سفید ندارد و فاصله‌ها با مرجع فرق دارد.

مشکل / هدف

سه اصلاح مشخص:

  1. رنگ‌ها باید از شخصی‌سازی ریشه بگیرند. رنگ ردیف فعال منو در PurchaseSubscriptionSidebar.tsx به‌صورت هاردکد #f17732 است. باید از متغیر برند شخصی‌سازی (var(--accent)) استفاده کند تا با «رنگ اصلی» انتخاب‌شده در پنل شخصی‌سازی (Topbar.tsxsetBrandHue) هماهنگ شود.

  2. محتوای appointment-settings باید روی پنل سفید #ffffff بنشیند، نه #fafafa. مرجع (tauri و نیز SubscriptionPage.tsx) محتوا را داخل یک پنل با background: var(--surface) (سفید) می‌گذارد. در appointment-settings محتوا مستقیم روی --bg صفحه (#fafafa) است. #fafafa رنگِ ناحیه‌ی منو است، نه محتوا.

  3. منو باید چسبیده به نوارِ کناری اصلی (سمت راست) باشد. در مرجع tauri منوی تنظیمات فلاش به ساید‌بار اصلی می‌چسبد؛ در clinicpro به‌خاطر padding محتوا فاصله افتاده.

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

فایل نقش
assets/admin/components/layout/PurchaseSubscriptionSidebar.tsx ساید‌منوی مشترک تنظیمات — رنگ ردیف فعال اینجاست
assets/admin/pages/AppointmentSettingsPage.tsx صفحه‌ی خراب که باید پیکسل‌به‌پیکسل شود
assets/admin/pages/SubscriptionPage.tsx مرجع درست — الگوی wrap محتوا در پنل سفید
assets/admin/components/layout/SettingsLayout.tsx شل تنظیمات (grid: [248px_minmax(0,1fr)] gap-5) — محل اصلاح فلاش‌شدن
assets/admin/styles.css تعریف متغیرها: --surface:#ffffff، --bg:#fafafa، --accent:#f0682a، --gap:20px، .content{padding:var(--gap);max-width:1480px;margin:0 auto}
clinic-pro-tauri/.../PurchaseSubscriptionSidebar.jsx مرجع بصری (تغییر نده)

وضعیت فعلی

۱) رنگ هاردکد در ساید‌منو — PurchaseSubscriptionSidebar.tsx

const rowStyle: React.CSSProperties = {
  borderRadius: 12, height: 44, marginBottom: 8,
  display: 'flex', alignItems: 'center', justifyContent: 'flex-start',
  padding: '0 14px', fontSize: 16, fontWeight: isActive ? 700 : 500,
  lineHeight: 1, textAlign: 'right',
  background: isActive ? '#f17732' : 'transparent',   // ← هاردکد
  color: isActive ? '#FFFFFF' : 'var(--text-2)',
  cursor: item.to ? 'pointer' : 'not-allowed',
  transition: 'background .14s',
};
// ...
onMouseEnter={(e) => { if (!isActive) (e.currentTarget as HTMLElement).style.background = 'var(--surface-2)'; }}
onMouseLeave={(e) => { if (!isActive) (e.currentTarget as HTMLElement).style.background = 'transparent'; }}

۲) صفحه‌ی خراب — AppointmentSettingsPage.tsx (بازگشت فعلی)

return (
  <SettingsLayout active="appointment">
    <div className="fade-in">   {/* ← fade-in تکراری؛ SettingsLayout خودش fade-in دارد */}
      <h1 className="section-title" style={{ marginBottom: 16 }}>مدیریت نوبت دهی</h1>
      <FreeVisitPrice />
      {!uuid ? (
        <div className="card" style={{ padding: 32, textAlign: 'center', ... }}>این بخش فقط برای پزشک در دسترس است.</div>
      ) : isLoading ? (
        <div style={{ padding: 16, ... }}>در حال بارگذاری...</div>
      ) : (
        <WeeklyScheduleTab doctorUuid={uuid} addresses={addresses} />   {/* ← مستقیم روی #fafafa */}
      )}
    </div>
  </SettingsLayout>
);

مرجع درست — SubscriptionPage.tsx (محتوا داخل پنل سفید)

return (
  <SettingsLayout active="subscription">
    <div style={{ background: 'var(--surface)', minWidth: 0 }}>   {/* ← پنل سفید #ffffff */}
      <div dir="ltr" style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 32, paddingTop: 8 }}>
        {/* محتوا */}
      </div>
    </div>
  </SettingsLayout>
);

وظایف

۱. رنگ ردیف فعال ساید‌منو را از شخصی‌سازی بگیر

در PurchaseSubscriptionSidebar.tsx:

  • background: isActive ? '#f17732'background: isActive ? 'var(--accent)'
  • بررسی کن که در حالت hover و active در تم تیره هم درست باشد (متغیرهای --accent، --surface-2 هر دو تم را در styles.css پوشش می‌دهند — نیازی به .dark & جدا نیست).
  • رنگ متن ردیف فعال #FFFFFF بماند (روی برند خوانا است).

۲. محتوای appointment-settings را داخل پنل سفید بگذار و ساختار را مثل مرجع کن

در AppointmentSettingsPage.tsx:

  • <div className="fade-in"> تکراری را حذف کن (چون SettingsLayout خودش fade-in دارد) و به‌جای آن دقیقاً الگوی SubscriptionPage را به‌کار ببر:
return (
  <SettingsLayout active="appointment">
    <div style={{ background: 'var(--surface)', minWidth: 0 }}>
      <h1 className="section-title" style={{ marginBottom: 16 }}>مدیریت نوبت دهی</h1>
      <FreeVisitPrice />
      {!uuid ? (
        <div className="card" style={{ padding: 32, textAlign: 'center', color: 'var(--text-3)', fontSize: 14 }}>
          این بخش فقط برای پزشک در دسترس است.
        </div>
      ) : isLoading ? (
        <div style={{ padding: 16, color: 'var(--text-3)', fontSize: 13 }}>در حال بارگذاری...</div>
      ) : (
        <WeeklyScheduleTab doctorUuid={uuid} addresses={addresses} />
      )}
    </div>
  </SettingsLayout>
);
  • بعد از تغییر، چشمی چک کن که WeeklyScheduleTab و FreeVisitPrice روی سفید (--surface) بنشینند و padding/فاصله‌ها با SubscriptionPage یکی باشد. اگر WeeklyScheduleTab خودش زمینه/کارت داخلی دارد، مطمئن شو با پنل سفید بیرونی دوبار‌کارت (double-card) نمی‌شود.

۳. منوی تنظیمات را فلاش به نوار کناری اصلی بچسبان

مشکل: .content در styles.css دارای padding: var(--gap) (۲۰px) و max-width:1480px; margin:0 auto است؛ همین padding سمت راست، بین نوار کناری اصلی و منوی تنظیمات فاصله می‌اندازد.

در SettingsLayout.tsx کاری کن ستون منو تا لبه‌ی نوار کناری اصلی کشیده شود؛ گزینه‌ی پیشنهادی: یک negative margin سمت راست روی ریشه‌ی SettingsLayout برابر --gap تا padding محتوا خنثی شود، بدون شکستن max-width بخش محتوا:

return (
  <div className="fade-in" dir="rtl" style={{ width: '100%' }}>
    <div className="grid grid-cols-1 lg:grid-cols-[248px_minmax(0,1fr)] gap-5"
         style={{ marginInlineStart: 'calc(-1 * var(--gap))' /* منو تا لبه‌ی نوار کناری */ }}>
      <PurchaseSubscriptionSidebar active={active} />
      <div style={{ minWidth: 0 }}>{children}</div>
    </div>
  </div>
);
  • مهم: RTL است؛ نوار کناری اصلی سمت راست است و منوی تنظیمات هم سمت راستِ گرید. جهت negative margin را با تست چشمی درست کن (marginInlineStart/marginInlineEnd) تا منو دقیقاً به نوار کناری بچسبد و لبه‌ی چپِ محتوا از قاب بیرون نزند.
  • چون SettingsLayout مشترک است، بعد از این تغییر همه‌ی صفحات تنظیمات (subscription، appointment، tags، insurance، …) را چک کن که هم‌زمان درست بمانند.

نکات مهم

  • هیچ تغییری در tauri نده — فقط مرجع بصری است.
  • منبع رنگ‌ها = متغیرهای CSS در assets/admin/styles.css؛ رنگ برند شخصی‌سازی از --accent می‌آید (پنل Topbar.tsxsetBrandHue). هر رنگ هاردکد جدید ممنوع.
  • هر دو تم روشن/تیره باید سالم بمانند (--surface، --accent، --surface-2 در هر دو تم تعریف شده‌اند).
  • تست بصری پیکسل‌به‌پیکسل: SubscriptionPage (درست) را کنار AppointmentSettingsPage بگذار؛ عرض منو، فاصله، زمینه‌ی سفید و رنگ ردیف فعال باید یکسان باشند.
  • تست‌های موجود را نگه‌دار: PurchaseSubscriptionSidebar.test.tsx، SettingsLayout.test.tsx، AppointmentSettingsPage.test.tsx — بعد از تغییر npm test (یا ddev exec) اجرا کن. اگر تستی رنگ هاردکد #f17732 را چک می‌کند، آن را به var(--accent) به‌روزرسانی کن.
  • backend/API دست نمی‌خورد → نیازی به به‌روزرسانی docs/api/* نیست.