---
name: redesign-page
description: بازطراحی UI/UX یک صفحه از پنل ادمین ClinicPro از روی URL آن — اسکرین‌شات گرفتن از صفحه، نگاشت URL به فایل سورس، آدیت انحراف‌ها از دیزاین‌سیستم، و بازنویسی صفحه با کامپوننت‌ها و توکن‌های موجود. استفاده کن وقتی کاربر یک URL از /admin می‌دهد و می‌گوید «این صفحه ui/ux خوبی ندارد»، «این صفحه را بازطراحی کن»، «redesign this page»، «این قسمت را درست کن»، یا «screenshot این صفحه».
---

# بازطراحی صفحه پنل ادمین ClinicPro

پنل ادمین یک SPA کلاینت‌ساید است (React 19 + Webpack Encore، سرو شده از `/admin/*`).
یعنی `curl` و فلگ `--screenshot` کروم به درد نمی‌خورند: هر دو روی فرم لاگین می‌نشینند،
چون توکن JWT در `localStorage['clinicpro-auth']` است.

درایور این skill آن کار را انجام می‌دهد: با API لاگین می‌کند، `localStorage` را seed
می‌کند، بعد ناوبری و اسکرین‌شات می‌گیرد — با CDP روی `WebSocket` نیتیو Node 22،
**بدون هیچ وابستگی npm** (نه playwright، نه puppeteer).

مسیرها نسبت به `clinicpro/` هستند.

## پیش‌نیازها

هیچ نصبی لازم نیست. فقط این دو:

```bash
ddev describe | head -3          # باید بالا باشد: https://clinic-pro.ddev.site
ls "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
```

کروم در مسیر دیگری است؟ `CHROME_BIN` را ست کن.

## گردش کار

### ۱. اسکرین‌شات صفحه فعلی

```bash
node .claude/skills/redesign-page/driver.mjs shot \
  "https://clinic-pro.ddev.site/admin/appointments" --out /tmp/before.png
```

**بعد حتماً تصویر را با ابزار Read باز کن و نگاه کن.** بدون دیدنِ صفحه، بازطراحی
یعنی حدس زدن.

فلگ‌ها: `--w 1440 --h 900` (سایز ویوپورت)، `--wait 4000` (میلی‌ثانیه صبر برای رندر)،
`--full` (کل صفحه، نه فقط ویوپورت).

موبایل هم ببین — این پنل RTL و پرجدول است و بیشتر مشکلات ریسپانسیو آنجاست:

```bash
node .claude/skills/redesign-page/driver.mjs shot \
  "https://clinic-pro.ddev.site/admin/appointments" --w 390 --h 844 --out /tmp/mobile.png
```

### ۲. نگاشت URL به سورس + آدیت

```bash
node .claude/skills/redesign-page/driver.mjs inspect \
  "https://clinic-pro.ddev.site/admin/clinics/41e325c4-e825-4067-8438-5d828ecaee09"
```

خروجی واقعی:

```
route     clinics/:uuid
component ClinicDetailPage
file      assets/admin/pages/ClinicDetailPage.tsx
components ConfirmDialog, Modal, PageHeader, SearchableSelect, NotificationMobileCard
lines     1035

AUDIT
  assets/admin/pages/ClinicDetailPage.tsx:242  hand-rolled overlay — use the shared <Modal>
```

روی هر فایل دلخواه هم مستقیم:

```bash
node .claude/skills/redesign-page/driver.mjs audit assets/admin/pages/AppointmentsPage.tsx
```

### ۳. قبل از نوشتن کد، دیزاین‌سیستم را بخوان

**منبع حقیقتِ توکن‌ها `assets/admin/styles.css` است** — نه `docs/admin-ui/ui-design-spec.md`
(آن سند قدیمی و پالت بنفشش با کد شیپ‌شده نمی‌خواند).

```bash
sed -n '/^:root/,/^}/p' assets/admin/styles.css | head -60   # توکن‌ها
ls assets/admin/components/ui/                               # کامپوننت‌های آماده
```

قانون: **اول کامپوننت موجود، بعد توسعه‌اش، در آخر ساخت کامپوننت جدید** — و دلیلش را بنویس.

### ۴. بازنویسی، سپس مقایسه

بعد از ادیت، دوباره اسکرین‌شات بگیر و با `before.png` مقایسه کن:

```bash
yarn dev   # یا: yarn watch
node .claude/skills/redesign-page/driver.mjs shot "<همان url>" --out /tmp/after.png
```

### ۵. تست + تایپ‌چک (بدون این، تسک تمام نیست)

```bash
npx tsc --noEmit -p tsconfig.json
npx vitest run assets/admin/pages/<YourPage>.test.tsx
```

توجه: سوییت کامل همین الان **۲۱ تست از پیش شکسته** دارد (`api.test.ts`، `LoginPage`،
`PatientDetailPage`، …) که ربطی به کار تو ندارند. قبل از شروع یک‌بار `npx vitest run`
بگیر و عدد پایه را یادداشت کن، وگرنه خطاهای موجود را به گردن تغییر خودت می‌اندازی.

## چک‌لیست بازطراحی

درایور موارد گرپ‌شدنی را می‌گیرد؛ این‌ها را باید خودت با چشم ببینی:

- **`.field` در مقابل `.field-block`** — `.field` یک باکس افقی بوردردار است که لیبل
  *داخلش* می‌نشیند. اگر `<label>` داخل `.field` بگذاری، لیبل کنار اینپوت می‌چسبد؛ و اگر
  `SearchableSelect` داخلش بگذاری، دو باکس تودرتو می‌شود. برای «لیبل بالای فیلد» از
  `.field-block` استفاده کن.
- **`className="btn"` بدون واریانت** بی‌رنگ و بدون بوردر رندر می‌شود — عملاً نامرئی.
  همیشه `btn primary` / `btn ghost` / `btn soft` / `btn danger`.
- **دکمه‌های فقط-آیکون** → `mini-btn`، نه `btn ghost sm` با پدینگ دستی.
- **توکن مرده** — مثلاً `var(--error)` وجود ندارد (`--danger` درست است). درایور این را می‌گیرد.
- **سلسله‌مراتب** — عنوان صفحه در `PageHeader` بیاید و در کارت زیرش تکرار نشود.
- **RTL/جلالی** — رشته‌های جدید فارسی، تاریخ‌ها جلالی، اعداد با `formatNumber`/`formatRial`.
- **دارک‌مود** — چون توکن استفاده می‌کنی خودکار درست است؛ هگز هاردکد آن را می‌شکند.

## Gotchas

- **ریدایرکت خاموش نقش‌ها.** `RoleRoute` کاربری که نقشش اجازه ندارد را بی‌صدا به
  `/admin/dashboard` می‌برد. یعنی یک اسکرین‌شات کاملاً سالم از **صفحهٔ اشتباه** می‌گیری.
  درایور مسیر نهایی را با مسیر درخواستی مقایسه می‌کند و هشدار می‌دهد:

  ```
  ⚠ WRONG PAGE: asked for /admin/clinics/…, landed on /admin/dashboard
  ```

  کاربر پیش‌فرض (`09390039833`) نقش **doctor** دارد. صفحات ادمین/کلینیک با آن باز نمی‌شوند.
  برای آن‌ها `CLINICPRO_USER` / `CLINICPRO_PASS` را ست کن.

- **کاربران تستی ممکن است seed نشده باشند.** `TEST_USERS.md` ادمین `09100000001` با رمز
  `Test@1234` را مستند می‌کند، ولی روی این دیتابیس وجود نداشت و لاگین `ERR_AUTH_005` داد.
  ساختنشان: `ddev exec php create_test_users.php` (دیتابیس را می‌نویسد — اول بپرس).

- **مودال نصب PWA جلوی صفحه را می‌گیرد.** درایور `localStorage['pwa-dismissed']='1'` را
  seed می‌کند. اگر با کروم خام اسکرین‌شات بگیری، این مودال وسط تصویر است.

- **کپچا (altcha) لوکال اجباری نیست.** `POST /api/v1/user/login` بدون فیلد `altcha` هم
  توکن می‌دهد؛ درایور به همین تکیه می‌کند. اگر روی محیطی که کپچا را اجبار می‌کند اجرا شود، می‌شکند.

- **سرت ddev را Node رد می‌کند** (`UNABLE_TO_VERIFY_LEAF_SIGNATURE`). درایور فقط برای
  هاست‌های `*.ddev.site` / `localhost` تأیید TLS را خاموش می‌کند، نه برای هر مبدأ.

- **صفحهٔ نوبت‌ها خودش اسکرول می‌شود** به ساعت جاری، پس ویوپورت وسط تایم‌لاین می‌افتد.
  برای دیدن هدر از `--full` استفاده کن.

- **بیلد CSS داخل ddev خطای نیتیو `lightningcss` می‌دهد** — از قبل وجود دارد و جلوی
  کامپایل JS/TS را نمی‌گیرد. خطاهای TypeScript همچنان در خروجی `tsc` می‌آیند.

## Troubleshooting

| علامت | علت / راه‌حل |
|---|---|
| `Chrome did not expose CDP on :9333` | نمونهٔ کروم قبلی زنده مانده. `CDP_PORT=9444` بده یا پروسه را بکش. |
| `login failed: … ERR_AUTH_005` | کاربر seed نشده یا رمز فرق دارد. `TEST_USERS.md` را ببین. |
| `⚠ redirected to /login` | توکن رد شد؛ معمولاً یعنی JWT منقضی شده — دوباره اجرا کن. |
| `⚠ page text is only N chars` | صفحه خالی رندر شده. `--wait 8000` بده یا کنسول را چک کن. |
| اسکرین‌شات تغییرات را نشان نمی‌دهد | باندل قدیمی است. `yarn dev` بزن (یا `yarn watch` روشن باشد). |
