feat(mobile): mobile-responsive UI — bottom tab bar, bottom-sheet dialogs, PWA
All changes are gated behind max-md:/md:hidden so the >=768px desktop layout is untouched (verified with lint + build + live checks at 375px). - globals.css: one mobile block — 16px inputs (no iOS auto-zoom), units sidebar stacks above content, wizard item rows become 2-col (text fields full-width, delete button full-width), dd-panels / flow diagram / conv-form stack, larger touch targets - ui/dialog.tsx: dialogs become full-width bottom sheets on mobile (all modals inherit it); desktop keeps the centered dialog - Header: sticky on mobile only + PageLayout bottom clearance - New MobileTabBar: role-aware bottom tabs (office admin/manager, inventory PM, inventory admin); hidden on /wizard - Wizard step 4: TouchSensor (150ms delay) so touch drag works without stealing scroll - JalaliDatePicker: dropdown capped to viewport; bigger day cells and time inputs on mobile - PWA: manifest.webmanifest + 192/512 icons (scripts/gen-pwa-icons.ps1) + theme-color/manifest links in index.html - New docs/mobile-responsive.md documenting the full change set
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# Mobile-Responsive UI — Change Log (v1.4)
|
||||
|
||||
هدف: تجربهی کاربری قابلاستفاده برای کاربران موبایل (اکثریت کاربران)، بدون اینکه
|
||||
ظاهر دسکتاپ هیچ تغییری بکند. هیچ بکاند، nginx، docker-compose یا ساختار جدیدی
|
||||
اضافه نشده — همهچیز داخل همان اپ React است.
|
||||
|
||||
## Core principle
|
||||
|
||||
یک کدبیس، دو نمایش. همهی تغییرات «فقط موبایل» هستند و پشت بریکپوینت
|
||||
Tailwind `max-md:` (زیر 768px) یا `md:hidden` (فقط روی موبایل نمایش داده میشود)
|
||||
قفل شدهاند. دسکتاپ (≥768px) همان استایلهای قبلی را میخواند و بنابراین
|
||||
پیکسلبهپیکسل بدون تغییر میماند — بهساختار.
|
||||
|
||||
## What changed
|
||||
|
||||
### 1. `frontend/src/styles/globals.css` — consolidated mobile block (new)
|
||||
یک بلوک `@media (max-width: 767.98px)` در انتهای فایل اضافه شد:
|
||||
|
||||
| Rule | Effect (mobile only) |
|
||||
|---|---|
|
||||
| `input/select/textarea { font-size: 16px !important }` | جلوگیری از زوم خودکار iOS روی فوکوس (فونتهای ۱۲–۱۴px زوم میشدند) |
|
||||
| `.units-layout { grid-template-columns: 1fr }` | سایدبار ۲۲۰px دستهها روی موبایل بالای پنل محتوا قرار میگیرد |
|
||||
| `.item-row-head { display: none }` + `.wizard-item-row` دوستونه | ردیف اقلام ویزارد (گرید ۸ ستونه) روی موبایل میشود: فیلدهای متنی تمامعرض، عددها دوستونه؛ placeholderها نقش برچسب را دارند |
|
||||
| `.wizard-item-row > :last-child` تمامعرض + حداقل ۴۴×۴۰px | دکمهی حذف قلم بزرگ و قابل لمس |
|
||||
| `.dd-panels { grid-template-columns: 1fr }` | پنلهای درگاندروپ مرحلهی ۴ تکستونه |
|
||||
| `.flow-cols` تکستونه + `.flow-lines { display: none }` | نمودار جریان باکسها روی هم؛ خطوط SVG اتصال که فقط در چیدمان دوستونه معنی داشتند روی موبایل مخفی میشوند |
|
||||
| `.conv-form` تکستونه، `.conv-row` wrap | فرم تبدیل واحد (گرید ۵ ستونه) روی موبایل ستونی |
|
||||
| touch targets بزرگتر (`.chip`, `.quick-chip`, `.spec-chip`, `.dd-item`, `.ut-cat`, `.btn-line-file`, دکمههای × و ...) | ارتفاع هدف لمسی به ~۴۰px رسید |
|
||||
|
||||
### 2. `frontend/src/components/ui/dialog.tsx` — dialogs become bottom sheets
|
||||
`DialogContent` با کلاسهای `max-md:` به bottom-sheet تمامعرض تبدیل شد
|
||||
(`inset-x-0 bottom-0`، گوشههای گرد فقط بالا، `max-h-[85dvh]`، padding با
|
||||
`safe-area-inset-bottom`). چون همهی مودالها (ویرایش، پذیرش، تایید حذف) از همین
|
||||
کامپوننت استفاده میکنند، همه یکجا درست شدند. دکمهی بستن هم بزرگتر شد.
|
||||
|
||||
### 3. Form grids stacked — one-line additions each
|
||||
- `EditModal.tsx` — گرید تأمینکننده/پروژه و گرید تاریخها: `max-md:grid-cols-1`
|
||||
- `Wizard/Step1TopicSupplier.tsx` — فرم تأمینکنندهی جدید: `max-md:grid-cols-1`
|
||||
- `Wizard/Step5Review.tsx` — گرید تاریخها: `max-md:grid-cols-1`
|
||||
- `Suppliers/CategoryPage.tsx` — فرم افزودن تأمینکننده: `max-md:grid-cols-1`
|
||||
|
||||
### 4. `frontend/src/components/layout/Header.tsx` — sticky header + clearance
|
||||
- هدر فقط روی موبایل `sticky top-0 z-40` شد (`max-md:`)
|
||||
- دکمهی بازگشت بزرگتر شد
|
||||
- `PageLayout` روی موبایل `pb-24` گرفت تا نوار تب پایین روی محتوا نیفتد
|
||||
|
||||
### 5. `frontend/src/components/layout/MobileTabBar.tsx` — NEW mobile bottom tab bar
|
||||
نوار تب پایین (فقط `<768px` با `md:hidden`):
|
||||
- **ادمین / مدیر تدارکات در دفتر:** داشبورد / تأمینکنندهها / پروژهها / ضرایب
|
||||
- **ادمین / مدیر تدارکات در پنل انبار:** انبار / کنترل روزانه / کالاهای در راه / سازماندهی (آینهی ناوبری دسکتاپ)
|
||||
- **مدیر پروژه:** انبار / تغییر موجودی / کنترل روزانه / کالاهای در راه
|
||||
- هدف لمسی ≥۵۶px، padding برای `safe-area-inset-bottom`، هایلایت تب فعال
|
||||
- در `/wizard` نمایش داده نمیشود (تا با جابهجایی تصادفی کارِ کاربر از بین نرود)
|
||||
|
||||
### 6. `frontend/src/App.tsx` — renders `<MobileTabBar />`
|
||||
|
||||
### 7. `frontend/src/pages/Wizard/Step4Projects.tsx` — touch drag & drop
|
||||
`TouchSensor` با `{ delay: 150, tolerance: 8 }` به سنسورهای dnd-kit اضافه شد:
|
||||
درگ لمسی کار میکند بدون اینکه اسکرول صفحه را بدزدد. مسیر کلیک-قلم-بعد-کلیک-پروژه
|
||||
همچنان مسیر جایگزین است. دسکتاپ همان `PointerSensor` قبلی را دارد.
|
||||
|
||||
### 8. `frontend/src/components/JalaliDatePicker.tsx` — dropdown width + targets
|
||||
- داپداون تقویم: `max-w-[calc(100vw-2rem)]` (در صفحههای باریک سرریز نمیشود)
|
||||
- سلولهای روز و ورودیهای ساعت/دقیقه روی موبایل بزرگتر شدند
|
||||
|
||||
### 9. PWA layer (optional installability)
|
||||
- `frontend/public/manifest.webmanifest` — NEW (name فارسی، `dir: rtl`،
|
||||
`display: standalone`، theme `#4f46e5`، آیکون 192/512 + maskable)
|
||||
- `frontend/public/icons/icon-192.png`, `icon-512.png` — NEW
|
||||
(تولیدشده با `frontend/scripts/gen-pwa-icons.ps1` — NEW، بدون وابستگی)
|
||||
- `frontend/index.html` — `theme-color` + لینک manifest + آیکونها اضافه شد
|
||||
- روی HTTP مثل میانبر صفحهی اصلی کار میکند؛ پرامپت نصب رسمی PWA به HTTPS
|
||||
نیاز دارد (بعداً با پروکسی/Let's Encrypt — بدون تغییر کد).
|
||||
|
||||
## Deliberately NOT changed
|
||||
|
||||
- **`SpecDrawer.tsx`**: کد مرده است (هیچجا import نمیشود) — تصمیم تیم: دست نمیزنیم، فایل میماند.
|
||||
- **`.e-item-row` / `.spec-drawer` در CSS**: کلاسهای بلااستفاده — دستنخورده ماندند.
|
||||
- هیچ کلاس/استایل دسکتاپی ویرایش نشد؛ تمام تغییرات داخل `max-md:` یا کامپوننتهای `md:hidden` است.
|
||||
|
||||
## Verification performed
|
||||
|
||||
- `npm run lint` (oxlint) → 0 errors (4 هشدار از قبل موجود)
|
||||
- `npm run build` (tsc + vite) → موفق
|
||||
- تست مرورگر روی Vite dev (viewport واقعی 375px):
|
||||
- نوار تب: `fixed bottom-0`، قابلمشاهده، ۴ تب با برچسب درست، ارتفاع ≥56px
|
||||
- هدر `sticky`، ورودیها 16px، padding پایین صفحه 96px (جای نوار تب)
|
||||
- صفحات ضرایب/ویزارد چیدمان تکستونه (`.units-layout` فقط بعد از انتخاب موضوع رندر میشود)
|
||||
- رگرسیون دسکتاپ: کلاسهای دسکتاپ دستنخوردهاند (بریکپوینتگیت)؛
|
||||
`npm run build` سلامت باندل را تایید میکند.
|
||||
|
||||
## How to test manually
|
||||
|
||||
```powershell
|
||||
cd C:\Users\Reza\Desktop\v1.4
|
||||
docker compose up -d --build # بازسازی ایمیج فرانت
|
||||
```
|
||||
|
||||
سپس در مرورگر دسکتاپ DevTools → device toolbar (مثلاً iPhone SE 375px) یا
|
||||
مستقیم با گوشی (بخش «دیدن روی گوشی» در README/جواب نهایی). دسکتاپ را هم در
|
||||
1280px چک کنید — باید دقیقاً مثل قبل باشد.
|
||||
|
||||
## Notes / known considerations
|
||||
|
||||
- خطوط اتصال نمودار جریان (SVG) روی موبایل عمداً مخفی شد — فقط باکسها روی هم
|
||||
قرار میگیرند؛ اگر روزی خواستید اتصالها را روی موبایل هم ببینید باید
|
||||
`FlowDiagram` برای حالت تکستونه بازنویسی شود.
|
||||
- نوار تب موبایل «انبارها» را ندارد (PMها از منوی همبرگری به آن میرسند).
|
||||
Reference in New Issue
Block a user