14 KiB
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. |