166 lines
9.2 KiB
Markdown
166 lines
9.2 KiB
Markdown
---
|
|
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` روشن باشد). |
|