From ffc43510381e6a64be96853e6a3b03792ea143a7 Mon Sep 17 00:00:00 2001 From: hamed <15238-genius.ha@users.noreply.drupalcode.org> Date: Wed, 15 Jul 2026 17:30:26 +0330 Subject: [PATCH] fix: update PurchaseSubscriptionSidebar and AppointmentSettingsPage for pixel-perfect alignment and color consistency --- .claude/prompt/settings-menu-pixel-perfect.md | 159 ++++++++++++++++++ .../layout/PurchaseSubscriptionSidebar.tsx | 2 +- .../components/layout/SettingsLayout.tsx | 5 +- .../admin/pages/AppointmentSettingsPage.tsx | 2 +- 4 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 .claude/prompt/settings-menu-pixel-perfect.md diff --git a/.claude/prompt/settings-menu-pixel-perfect.md b/.claude/prompt/settings-menu-pixel-perfect.md new file mode 100644 index 00000000..2056c548 --- /dev/null +++ b/.claude/prompt/settings-menu-pixel-perfect.md @@ -0,0 +1,159 @@ +# پیکسل‌به‌پیکسل کردن منوی تنظیمات + ریشه‌گرفتن رنگ‌ها از شخصی‌سازی + +## پروژه + +`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.tsx` → `setBrandHue`) هماهنگ شود. + +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` + +```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` (بازگشت فعلی) + +```tsx +return ( + +
{/* ← fade-in تکراری؛ SettingsLayout خودش fade-in دارد */} +

مدیریت نوبت دهی

+ + {!uuid ? ( +
این بخش فقط برای پزشک در دسترس است.
+ ) : isLoading ? ( +
در حال بارگذاری...
+ ) : ( + {/* ← مستقیم روی #fafafa */} + )} +
+
+); +``` + +### مرجع درست — `SubscriptionPage.tsx` (محتوا داخل پنل سفید) + +```tsx +return ( + +
{/* ← پنل سفید #ffffff */} +
+ {/* محتوا */} +
+
+
+); +``` + +## وظایف + +### ۱. رنگ ردیف فعال ساید‌منو را از شخصی‌سازی بگیر + +در `PurchaseSubscriptionSidebar.tsx`: + +- `background: isActive ? '#f17732'` → `background: isActive ? 'var(--accent)'` +- بررسی کن که در حالت hover و active در تم تیره هم درست باشد (متغیرهای `--accent`، `--surface-2` هر دو تم را در `styles.css` پوشش می‌دهند — نیازی به `.dark &` جدا نیست). +- رنگ متن ردیف فعال `#FFFFFF` بماند (روی برند خوانا است). + +### ۲. محتوای appointment-settings را داخل پنل سفید بگذار و ساختار را مثل مرجع کن + +در `AppointmentSettingsPage.tsx`: + +- `
` تکراری را حذف کن (چون `SettingsLayout` خودش `fade-in` دارد) و به‌جای آن دقیقاً الگوی `SubscriptionPage` را به‌کار ببر: + +```tsx +return ( + +
+

مدیریت نوبت دهی

+ + {!uuid ? ( +
+ این بخش فقط برای پزشک در دسترس است. +
+ ) : isLoading ? ( +
در حال بارگذاری...
+ ) : ( + + )} +
+
+); +``` + +- بعد از تغییر، چشمی چک کن که `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` بخش محتوا: + +```tsx +return ( +
+
+ +
{children}
+
+
+); +``` + +- **مهم:** RTL است؛ نوار کناری اصلی سمت راست است و منوی تنظیمات هم سمت راستِ گرید. جهت negative margin را با تست چشمی درست کن (`marginInlineStart`/`marginInlineEnd`) تا منو دقیقاً به نوار کناری بچسبد و لبه‌ی چپِ محتوا از قاب بیرون نزند. +- چون `SettingsLayout` مشترک است، بعد از این تغییر **همه‌ی صفحات تنظیمات** (subscription، appointment، tags، insurance، …) را چک کن که هم‌زمان درست بمانند. + +## نکات مهم + +- **هیچ تغییری در tauri نده** — فقط مرجع بصری است. +- منبع رنگ‌ها = متغیرهای CSS در `assets/admin/styles.css`؛ رنگ برند شخصی‌سازی از `--accent` می‌آید (پنل `Topbar.tsx` → `setBrandHue`). هر رنگ هاردکد جدید ممنوع. +- هر دو تم روشن/تیره باید سالم بمانند (`--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/*` نیست. diff --git a/assets/admin/components/layout/PurchaseSubscriptionSidebar.tsx b/assets/admin/components/layout/PurchaseSubscriptionSidebar.tsx index a3dd8385..c7c1e4e2 100644 --- a/assets/admin/components/layout/PurchaseSubscriptionSidebar.tsx +++ b/assets/admin/components/layout/PurchaseSubscriptionSidebar.tsx @@ -78,7 +78,7 @@ export default function PurchaseSubscriptionSidebar({ active }: { active: string display: 'flex', alignItems: 'center', justifyContent: 'flex-start', padding: '0 14px', fontSize: 16, fontWeight: isActive ? 700 : 500, lineHeight: 1, textAlign: 'right', - background: isActive ? '#f17732' : 'transparent', + background: isActive ? 'var(--accent)' : 'transparent', color: isActive ? '#FFFFFF' : 'var(--text-2)', cursor: item.to ? 'pointer' : 'not-allowed', transition: 'background .14s', diff --git a/assets/admin/components/layout/SettingsLayout.tsx b/assets/admin/components/layout/SettingsLayout.tsx index 99b11f38..cdcbc3b9 100644 --- a/assets/admin/components/layout/SettingsLayout.tsx +++ b/assets/admin/components/layout/SettingsLayout.tsx @@ -50,7 +50,10 @@ export function menuForRole(role: string | null | undefined): SettingsMenuItem[] export default function SettingsLayout({ active, children }: { active: string; children: React.ReactNode }) { return (
-
+
{children}
diff --git a/assets/admin/pages/AppointmentSettingsPage.tsx b/assets/admin/pages/AppointmentSettingsPage.tsx index f9247a93..f1d4be08 100644 --- a/assets/admin/pages/AppointmentSettingsPage.tsx +++ b/assets/admin/pages/AppointmentSettingsPage.tsx @@ -27,7 +27,7 @@ export default function AppointmentSettingsPage() { return ( -
+

مدیریت نوبت دهی