Files
ERP/docs/mobile-responsive.md
T
whqreza 9e2089e853 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
2026-09-03 19:26:40 +03:30

8.3 KiB
Raw Permalink Blame History

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

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ها از منوی همبرگری به آن می‌رسند).