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