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

## پروژه

`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/*` نیست.
