- Created a new JSON file for the PaymentGatewayInterface.php, detailing its methods and return types. - Added a JSON file for payment.md, documenting various API endpoints and their parameters, responses, and errors. - Introduced a JSON file for fix-admin-modal-and-calendar.md, outlining issues and solutions related to admin modal and calendar functionalities.
11 KiB
ریسپانسیو کردن پنل ادمین برای موبایل (iPhone 8 / ۳۷۵px)
پروژه
clinicpro (admin frontend — React 19 + assets/admin/styles.css)
زمینه
پنل /admin روی صفحههای کوچک (مثل iPhone 8 عرض ۳۷۵px) بههم میریزد و افقی اسکرول میشود. زیرساخت ریسپانسیو تا حدی هست (viewport meta درست است، drawer سایدبار + scrim در @media (max-width: 860px)، .settings-grid/.stat-grid در media collapse میشوند)، ولی بیاثر شده چون در بیشتر صفحهها grid-template-columns بهصورت inline style={{}} روی المانها نوشته شده و inline style بر قوانین @media در CSS اولویت دارد → گریدها روی موبایل جمع نمیشوند و از عرض صفحه بیرون میزنند.
نمونهٔ واقعی: PaymentsPage.tsx → <div className="stat-grid" style={{ gridTemplateColumns: 'repeat(4,1fr)' }}>؛ روی ۳۷۵px میشود ۴ ستون ۹۰pxای که overflow میدهد. .stat-grid در CSS در @media (max-width:560px) به 1fr 1fr میرود ولی inline آن را باطل میکند.
مشکل / هدف
پنل ادمین روی ۳۷۵px بدون اسکرول افقی و خوانا شود:
- گریدهای inline ثابت که media را میشکنند اصلاح شوند (بهترین راه:
repeat(auto-fit, minmax(...))که بدون media خودکار جمع میشود، یا حذف inline و واگذاری به CSS). - breakpoint منوی موبایل (hamburger) با drawer یکسان شود.
- جدولها و محتوای عریض داخل کانتینر اسکرولشونده باشند، نه کل صفحه.
- گارد سراسری ضد-overflow افقی.
فایلهای مرتبط
| فایل | نقش |
|---|---|
clinicpro/assets/admin/styles.css |
.stat-grid auto-fit، breakpoint drawer، گارد overflow، paddingهای موبایل |
clinicpro/assets/admin/components/layout/Topbar.tsx |
هماهنگی breakpoint hamburger با CSS |
| صفحههای با گرید inline (لیست پایین) | حذف/ریسپانسیو کردن gridTemplateColumns inline |
صفحهها/کامپوننتهای دارای gridTemplateColumns inline (grep -rn "gridTemplateColumns:" assets/admin):
PaymentsPage, DoctorsPage, StaffPage, FinancialReportPage, RepresentationFinancePage, RepresentationSettlementPage, DashboardPage (چند مورد)، ClinicDetailPage (1fr 300px)، DoctorDetailPage (1fr 1fr auto)، AppointmentsPage (1fr auto)، SettingsPage (1fr auto)، ServiceTariffModal (150px 1fr auto)، DashboardPage ردیف 160px 1fr 52px. (PersianCalendar گریدهای repeat(7,1fr)/repeat(3,1fr) داخل popover کوچکاند و مشکلساز نیستند — دست نزن.)
وضعیت فعلی
CSS (assets/admin/styles.css)
:root { --sidebar-w: 252px; }
.main { flex: 1; min-width: 0; margin-right: var(--sidebar-w); }
.stat-grid { /* base بدون grid-template-columns صریح؟ inlineها آن را ست میکنند */ }
.scrim { display: none; }
@media (max-width: 1080px) {
.stat-grid { grid-template-columns: repeat(3, 1fr); }
.dash-main, .dash-3 { grid-template-columns: 1fr; }
}
@media (max-width: 860px) { /* ← drawer فقط تا 860 */
.main { margin-right: 0 !important; }
.sidebar { transform: translateX(100%); box-shadow: var(--shadow-lg); }
.app[data-mobile-open="true"] .sidebar { transform: translateX(0); width: var(--sidebar-w); }
.app[data-mobile-open="true"] .scrim { display: block; position: fixed; inset: 0; /* ... */ }
.topbar-search { display: none; }
.grid-2 { grid-template-columns: 1fr; }
}
@media (max-width: 560px) { .stat-grid { grid-template-columns: 1fr 1fr; } }
Topbar breakpoint (ناهماهنگ با CSS)
// assets/admin/components/layout/Topbar.tsx:26
onClick={typeof window !== 'undefined' && window.innerWidth < 1024 ? onMobileMenuOpen : toggleSidebar}
< 1024 منوی موبایل را باز میکند، ولی drawer CSS فقط ≤ 860 است → در بازهٔ ۸۶۱–۱۰۲۳ hamburger «باز» میکند اما سایدبار حالت drawer ندارد (منطقهٔ خراب).
نمونهٔ گرید inline (تکرارشده در ۲۰ فایل)
<div className="stat-grid" style={{ gridTemplateColumns: 'repeat(4,1fr)' }}> // PaymentsPage:116
<div className="stat-grid" style={{ gridTemplateColumns: 'repeat(5,1fr)' }}> // DoctorsPage:212
<div style={{ display: 'grid', gridTemplateColumns: '1fr 300px', gap: 'var(--gap)' }}> // ClinicDetailPage:784
وظایف
۱. .stat-grid را ذاتاً ریسپانسیو کن (CSS)
در styles.css به .stat-grid یک base با auto-fit بده تا بدون نیاز به media و بدون تأثیرپذیری از تعداد ستون خودش جمع شود:
.stat-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: var(--gap);
}
و قوانین media مربوط به .stat-grid (خطوط ۷۰۴ و ۷۲۰ فعلی) را حذف کن (دیگر لازم نیستند؛ auto-fit همه را پوشش میدهد).
۲. حذف gridTemplateColumns inline از stat-gridها
در همهٔ صفحههایی که <div className="stat-grid" style={{ gridTemplateColumns: 'repeat(N,1fr)', ... }}> دارند، فقط کلید gridTemplateColumns را از inline style حذف کن (بقیهٔ propها مثل marginBottom بمانند). با تسک ۱، خودکار ریسپانسیو میشوند.
فایلها: PaymentsPage, DoctorsPage, StaffPage, FinancialReportPage, RepresentationFinancePage, RepresentationSettlementPage, DashboardPage (خطوط ۹۵۰/۱۰۵۶/۱۰۷۲).
مثال:
// قبل
<div className="stat-grid" style={{ gridTemplateColumns: 'repeat(4,1fr)' }}>
// بعد
<div className="stat-grid">
// اگر propهای دیگری بود:
<div className="stat-grid" style={{ marginBottom: 'var(--gap)' }}>
۳. لایههای دو/سهستونهٔ inline → ریسپانسیو
برای گریدهای غیرِ stat که ستون ثابت دارند و باید روی موبایل عمودی شوند، بهجای inline از کلاس ریسپانسیو استفاده کن. یک کلاس عمومی در CSS اضافه کن:
/* لایهٔ دوستونه که زیر ۸۶۰ عمودی میشود */
.split-2 { display: grid; grid-template-columns: 1fr minmax(0, 320px); gap: var(--gap); align-items: start; }
@media (max-width: 860px) { .split-2 { grid-template-columns: 1fr; } }
/* ردیف فیلد + اکشن که زیر ۶۰۰ عمودی میشود */
.form-row { display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: end; }
@media (max-width: 600px) { .form-row { grid-template-columns: 1fr; } }
سپس:
ClinicDetailPage:784(1fr 300px) →className="split-2"(حذف inline grid).DoctorDetailPage:1107(1fr 1fr auto) وAppointmentsPage:409(1fr auto) وSettingsPage:431(1fr auto) وServiceTariffModal:95(150px 1fr auto) → ازform-rowاستفاده کن یا اگر ساختار خاص است، همان inline را با wrap در media نگهدار ولی مطمئن شو زیر ۶۰۰ تکستون میشود. (برای المانهای inline که کلاسگذاری سخت است، میتوانیgridTemplateColumnsرا باrepeat(auto-fit, minmax(140px, 1fr))جایگزین کنی تا خودکار بشکند.)DashboardPage:119(160px 1fr 52px) وDashboardPage:514(quick-gridrepeat(3,1fr)):quick-gridرا هم مثل stat به auto-fit ببر؛ ردیف ۱۶۰px را زیر ۵۶۰ به1fr autoیا wrap تبدیل کن.
۴. هماهنگی breakpoint منوی موبایل
drawer را با hamburger یکسان کن. سریعترین راه: در styles.css بلوک @media (max-width: 860px) را به @media (max-width: 1024px) تغییر بده (drawer/scrim/main-margin/topbar-search همگی زیر ۱۰۲۴). این با window.innerWidth < 1024 در Topbar همخوان میشود و منطقهٔ خرابِ ۸۶۱–۱۰۲۳ رفع میشود.
اگر ترجیح میدهی سایدبار روی تبلت بماند، بهجای آن
1024درTopbar.tsxرا به860تغییر بده. یکی از دو راه — نه هر دو. (توصیه: drawer تا ۱۰۲۴.)
۵. گارد سراسری ضد-overflow افقی + padding موبایل
در styles.css:
html, body { max-width: 100%; overflow-x: hidden; }
.main { min-width: 0; } /* اجازهٔ کوچکشدن flex child */
@media (max-width: 560px) {
.page, .main > * { padding-left: 12px; padding-right: 12px; } /* اگر padding بزرگتری دارند */
.page-head, .toolbar { flex-wrap: wrap; gap: 10px; } /* هدر/تولبار در چند خط */
}
(کلاسهای واقعی padding صفحه را از styles.css پیدا کن — اگر نام .page/.content فرق دارد، همان را هدف بگیر.)
۶. جدولها داخل کانتینر اسکرولشونده
هر <table> عریض باید داخل .table-wrap (که overflow-x: auto دارد) باشد تا فقط جدول اسکرول شود نه کل صفحه. فایلهای دارای <table> بدون wrap را بررسی و در صورت نبودِ wrapper، دور جدول <div className="table-wrap"> بگذار:
PreRegistrationsPage, UsersPage, ClinicsPage, RepresentationFinancePage, AppointmentsPage, RepresentationSettlementPage, AdminSubscriptionPage, DoctorsPage, SmsWalletPage, RepresentationProfilePage. (اگر از کامپوننت DataTable مشترک استفاده میکنند و آن خودش wrap دارد، نیازی نیست — اول بررسی کن.)
نکات مهم
- چرا inline بد است:
style={{gridTemplateColumns}}روی المان، specificity بالاتر از هر@mediaدر stylesheet دارد؛ پس یا حذف شود یا خودشauto-fit/ریسپانسیو باشد. این هستهٔ باگ است. auto-fit + minmaxبهترین انتخاب برای stat/quick گریدهاست: بدون media، با هر تعداد کارت، روی هر عرض درست جمع میشود.- RTL: از
padding-inline/margin-inlineو رفتار موجود پیروی کن؛ چیزی که RTL را بشکند اضافه نکن. - کلاس CSS جدید فقط در حد
.split-2/.form-row(یا معادل)؛ کتابخانهٔ CSS جدید نصب نکن. - بعد از تغییر:
ddev exec yarn devوddev exec npx tsc --noEmitبدون خطا؛ سپس در DevTools با عرض 375px (iPhone 8) این صفحهها را چک کن: Dashboard، Payments، Doctors، Appointments، Settings، یک Detail (Clinic/Doctor) — نباید اسکرول افقی داشته باشند و کارتها/جدولها باید درست بچینند. - تغییر فقط frontend/CSS است؛ backend و docs تغییری ندارند.
- اینها فایلهای
.tsx/CSS پنلاند؛ اگر جای دیگری همgridTemplateColumnsinline ثابت دیدی که overflow میدهد، همان الگو را اعمال کن.