160 lines
10 KiB
Markdown
160 lines
10 KiB
Markdown
# پیکسلبهپیکسل کردن منوی تنظیمات + ریشهگرفتن رنگها از شخصیسازی
|
|
|
|
## پروژه
|
|
|
|
`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 (
|
|
<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` (محتوا داخل پنل سفید)
|
|
|
|
```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` را بهکار ببر:
|
|
|
|
```tsx
|
|
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` بخش محتوا:
|
|
|
|
```tsx
|
|
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.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/*` نیست.
|