Files
clinicpro/.claude/skills/redesign-page/SKILL.md
T

14 KiB
Raw Blame History

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

قبل از شروع، فایل clinicpro/.claude/guidelines.md را بخوان و همهٔ بخش‌های آن را اعمال کن — از جمله §۰ Grill که قبل از هر تغییر اجباری است.

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

نقش: متخصص ارشد UI/UX. هدف بهبود تجربهٔ کاربری در چهارچوب تم فعلی است، نه ساختن هویت بصری جدید. هر تغییری که با دیزاین‌سیستم فعلی ناسازگار باشد، رد است.

پنل ادمین یک SPA کلاینت‌ساید است (React 19 + Webpack Encore، سرو شده از /admin/*). یعنی curl و فلگ --screenshot کروم به درد نمی‌خورند: هر دو روی فرم لاگین می‌نشینند، چون توکن JWT در localStorage['clinicpro-auth'] است. درایور این skill آن کار را می‌کند: با API لاگین می‌کند، localStorage را seed می‌کند، تم/تراکم را می‌نشاند، بعد ناوبری و اسکرین‌شات می‌گیرد — با CDP روی WebSocket نیتیو Node 22، بدون هیچ وابستگی npm (نه playwright، نه puppeteer).

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

پیش‌نیازها

هیچ نصبی لازم نیست:

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

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

گردش کار

۰. اول دیزاین‌سیستم را بخوان — قبل از هر چیز

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

node .claude/skills/redesign-page/driver.mjs ds            # توکن‌ها + کلاس‌ها + کامپوننت‌ها
node .claude/skills/redesign-page/driver.mjs ds tokens     # فقط توکن‌ها
node .claude/skills/redesign-page/driver.mjs ds components # فقط کامپوننت‌های مشترک با Props

خروجی واقعی: TOKENS (57) و SHARED COMPONENTS (26). قانون ترتیب: اول کامپوننت موجود، بعد توسعه/عمومی‌کردنش، در آخر ساخت کامپوننت جدید — و دلیلش را بنویس.

۱. چهار نمای اجباری

node .claude/skills/redesign-page/driver.mjs variants \
  "https://clinic-pro.ddev.site/admin/resources" --dir /tmp/clinicpro-review

چهار فایل می‌سازد: -light · -dark · -compact · -mobile. هر چهار را با ابزار Read باز کن و نگاه کن. قضاوت با یک اسکرین‌شات یعنی صفحه‌ای که در سه نمای دیگر خراب است. تم تیره و تراکم فشرده در این پنل تنظیمات واقعی کاربرند، نه فرض.

تک‌نما:

node .claude/skills/redesign-page/driver.mjs shot "<url>" --out /tmp/x.png \
  --theme dark --density compact --w 390 --h 844 --full --wait 6000

فلگ‌ها: --w/--h ویوپورت · --wait میلی‌ثانیه · --full کل صفحه · --theme light|dark · --density comfortable|compact · --context clinic|personal · --no-probe.

هر shot یک پروب رانتایم هم می‌زند که فقط روی DOM رندرشده دیدنی است:

RUNTIME
  ⚠ 2 form field(s) with no label

چه چیزهایی می‌گیرد: سرریز افقی، دکمهٔ آیکونیِ بی‌نام (بدون aria-label/title)، فیلد بدون لیبل، و کنترل کوتاه‌تر از ۳۲px (هدف لمسی ۴۴px است).

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

node .claude/skills/redesign-page/driver.mjs inspect "https://clinic-pro.ddev.site/admin/resources"

خروجی واقعی:

route     resources
component ResourcesPage
file      assets/admin/pages/ResourcesPage.tsx
components PageHeader, DataTable, ResourceBlocksModal, ConfirmDialog, SearchableSelect, …
lines     278
test      assets/admin/pages/ResourcesPage.test.tsx

AUDIT  clean

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

node .claude/skills/redesign-page/driver.mjs audit assets/admin/pages/ClinicDetailPage.tsx
# AUDIT
#   assets/admin/pages/ClinicDetailPage.tsx:242  hand-rolled overlay — use the shared <Modal>

آدیت این‌ها را می‌گیرد: <select> نیتیو، .btn بدون واریانت، هگز هاردکد، overlay دستی، <label> داخل .field، تاریخ میلادی، type="date"، دکمهٔ آیکونی بدون aria-label، توکن تعریف‌نشده، و .seg بدون کلاس on/active.

۳. گزارش — همیشه با این ۹ بخش

۱. تحلیل صفحه            چه کاری برای چه کاربری؛ جریان اصلی
۲. مشکلات UI             سلسله‌مراتب بصری، فاصله، تایپوگرافی، رنگ، انحراف از DS
۳. مشکلات UX             جریان کار، تعداد کلیک، حالت‌های Loading/Empty/Error، ریسپانسیو، دسترسی‌پذیری
۴. پیشنهادهای بهبود      برای هر مشکل، یک راه‌حل مشخص و قابل اجرا
۵. ساختار جدید صفحه      چیدمان پیشنهادی، در چهارچوب همین تم
۶. کامپوننت‌های قابل استفادهٔ مجدد   از components/ui که همین حالا جواب می‌دهند
۷. کامپوننت‌های نیازمند بهبود        کدام Props/API باید عمومی‌تر شود و چرا
۸. کامپوننت‌های جدید      فقط در صورت ضرورت، با دلیل نبودِ جایگزین
۹. دلیل هر تغییر         چرا این تغییر تجربه را بهتر می‌کند

هر یافته باید به file:line وصل باشد یا به یکی از اسکرین‌شات‌ها. یافتهٔ بی‌ارجاع، حدس است.

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

ddev exec yarn dev
node .claude/skills/redesign-page/driver.mjs variants "<همان url>" --dir /tmp/clinicpro-review-after

before/after را کنار هم بگذار. اگر تفاوتی دیده نمی‌شود، باندل قدیمی است.

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

ddev exec npx tsc --noEmit --project tsconfig.json
npx vitest run                                   # روی هاست، نه داخل ddev

خط پایه در ۲۰۲۶-۰۸-۰۲: ۱۰۰ فایل، ۶۶۰ تست، همه سبز. هر شکستی مالِ توست. (نسخهٔ قبلی این سند از «۲۱ تست از پیش شکسته» می‌گفت — دیگر درست نیست.)

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

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

  • .field در مقابل .field-block.field خودش باکسِ بوردردار اینپوت است. لیبل داخلش یعنی لیبل چسبیده به اینپوت؛ SearchableSelect داخلش یعنی دو باکس تودرتو. «لیبل بالای فیلد» → .field-block.
  • .card پدینگ نداردcard-pad آن را می‌دهد.
  • className="btn" بدون واریانت بی‌رنگ و بی‌بوردر رندر می‌شود، عملاً نامرئی. همیشه btn primary / btn secondary / btn ghost / btn danger.
  • دکمهٔ فقط-آیکونmini-btn، نه btn ghost sm با پدینگ دستی.
  • .seg فقط button و a را می‌شناسد و کلاس فعالش on است (active هم alias شد). تبِ فعالِ بی‌کلاس یعنی هیچ نشانه‌ای ندارد.
  • سلسله‌مراتب — عنوان در PageHeader بیاید و در کارت زیرش تکرار نشود.
  • صفحهٔ زیرمجموعه حتماً backTo یا <BackButton fallback=…> دارد.
  • وضعیت لیست در URL — جستجو/فیلتر/صفحه با useUrlState، نه useState؛ وگرنه «بازگشت» نما را می‌پراند.
  • RTL/جلالی — رشته‌های جدید فارسی، تاریخ‌ها جلالی، اعداد با formatNumber/formatRial.
  • دارک‌مود — با توکن خودکار درست است؛ یک هگز هاردکد آن را می‌شکند.
  • سه حالت داده — Loading / Empty / Error هر سه باید طراحی داشته باشند، نه فقط حالت پر.

Gotchas

  • کاربر پیش‌فرض درایور با دیتابیس فعلی هماهنگ است، ولی دیتابیس عوض می‌شود. پیش‌فرض 0912000201 / QaTest@1234 (پزشکِ مالک کلینیک) است. اگر لاگین ERR_AUTH_005 داد، دیتابیس دوباره seed شده: ddev exec php bin/console app:seed-scenarios --reset -n. در اجرای ۲۰۲۶-۰۸-۰۲ کاربر 0912000301 (مالک غیرپزشک) رمز نداشت و لاگینش رد شد؛ از 0912000201 یا 0912000101 استفاده کن.

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

    ⚠ WRONG PAGE: asked for /admin/clinics/…, landed on /admin/dashboard
    
  • محیط کاری، نه نقش. کاربری که هم مطب شخصی دارد هم کلینیک، پیش‌فرض روی مطب می‌نشیند و صفحهٔ منابع/سرویس‌های کلینیک خالی می‌آید. این باگ نیست: --context clinic بده.

  • مودال نصب PWA جلوی صفحه را می‌گیرد. درایور pwa-dismissed=1 را seed می‌کند. با کروم خام، این مودال وسط تصویر است.

  • تم فقط با صفت data-theme نمی‌ماند — بعد از hydrate از localStorage['clinicpro-ui'] دوباره خوانده می‌شود. درایور هر دو را می‌نویسد و بعد از رندر یک بار دیگر صفت را می‌گذارد.

  • موبایل بدون Emulation.setDeviceMetricsOverride فقط «پنجرهٔ باریک» است — مدیا کوئری‌های pointer: coarse خاموش می‌مانند و ارتفاع لمسی ۴۴px دیده نمی‌شود. درایور برای عرض ≤۴۸۰ خودش این را روشن می‌کند.

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

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

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

  • منوی تنظیمات دو مصرف‌کننده داردsettingsMenu.ts منبع واحد است؛ سایدبار دسکتاپ و فهرست موبایل هر دو از آن می‌خوانند. در موبایل کل منو بالای محتوا می‌نشیند، پس صفحهٔ تنظیماتی در نمای ۳۹۰px یعنی ۱۵ آیتم منو قبل از رسیدن به محتوا. در نقد موبایل حتماً ببینش.

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

Troubleshooting

علامت علت / راه‌حل
login failed for 0912000201: … ERR_AUTH_005 دیتابیس دوباره seed شده. ddev exec php bin/console app:seed-scenarios --reset -n یا CLINICPRO_USER/CLINICPRO_PASS را ست کن.
Chrome did not expose CDP on :9333 نمونهٔ کروم قبلی زنده مانده. CDP_PORT=9444 بده یا پروسه را بکش.
⚠ redirected to /login توکن رد شد؛ معمولاً JWT منقضی شده — دوباره اجرا کن.
⚠ WRONG PAGE نقشِ کاربر اجازه ندارد، یا محیط اشتباه است (--context clinic).
⚠ page text is only N chars صفحه خالی رندر شده. --wait 8000 بده یا کنسول را چک کن.
اسکرین‌شات تغییرات را نشان نمی‌دهد باندل قدیمی است. ddev exec yarn dev (یا yarn watch روشن).
صفحهٔ کلینیک خالی است ولی خطا ندارد محیط روی مطب شخصی است. --context clinic.