Files
hedena_gold/docs/PWA-PORT-PLAN.md
T
s.esmaeiliandCursor d613d16c82 fix: rename the henza brand to montzar
اپ: اصلاح نام برند به منتزر

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-10 17:17:14 +03:30

53 KiB
Raw Blame History

پلن پورت اپ کاربر کلاسیک — henza_pwa → apps/user-app-classic

سند برنامه‌ریزی. قبل از تأیید شما هیچ کدی نوشته نمی‌شود.

مرجع پین‌شده: henza_pwa در کامیت b171fff (2026-09-02، «fee in bonakdar removed»). هر ارجاع path:line در این سند به همین نسخه است و نسبت به henza_pwa/ نوشته شده. منبع اصلی شواهد: docs/parity/_inv-ref-pwa.md (سیاهه‌ی کامل مرجع) به‌علاوه‌ی راستی‌آزمایی مستقیم روی کد. اگر مرجع عوض شد، این سند باید دوباره راستی‌آزمایی شود.


خواسته

  1. یک اپ کاربر سوم در مونوریپو، کنار user-app و user-app-v2.
  2. طراحی آن = طراحی قبلی همین سیستم، یعنی henza_pwa.
  3. همه‌ی صفحه‌ها، کارکردها، عملیات، انیمیشن‌ها و ناوبری دقیقاً مثل مرجع.
  4. با تکنولوژی جدید و کد بهتر.
  5. هیچ چیزی از بین نرود.

قرارداد «دقیقاً مثل مرجع»

لایه قاعده
آنچه کاربر می‌بیند و انجام می‌دهد عیناً مرجع. چیدمان و ابعاد، رنگ‌ها، فونت، آیکون‌ها، متن‌های فارسی (بایت‌به‌بایت — حتی فاصله‌ی دوتایی بعد از «لطفا» و غلط املایی «کارکتر»)، ارقام، ترتیب و برچسب تب‌ها، پیام‌های اعتبارسنجی، رنگ و مدت toast ها، پارامترهای انیمیشن، مسیرها و نام route ها، رفتار guard ها، محاسبه‌ها و گرد کردن‌ها.
زیر کاپوت بازنویسی‌شده و بهتر. TypeScript با strict، Pinia، composable ها، یک لایه‌ی HTTP تایپ‌شده، تنظیمات از env، حذف کد مرده و تکراری، تست.
کوییرک بصری بی‌خطر عیناً تکرار می‌شود — مثلاً notify ورود که حتی برای موفقیت قرمز است، یا تشدید سرگردان در «ّکاربر فعال شود؟».
استثنا فقط خرابی‌های کارکردی مرجع، طبق D4. هر کدام شماره دارد، در §تنش ۴ و §چیزی که پورت نمی‌شود فهرست شده، و هیچ‌کدام بی‌صدا نیست.

«هیچ چیزی از بین نرود» دو معنا دارد و هر دو تعهد این پلن است:

  1. هیچ صفحه، کارکرد، انیمیشن یا متنی از مرجع جا نمی‌ماند — با سرشماری خودکار اثبات می‌شود (§معیار تمام شد).
  2. هیچ چیز موجود در مونوریپو آسیب نمی‌بیند — user-app، user-app-v2 و admin-panel دست نمی‌خورند؛ تغییرات apps/api فقط افزایشی است.

قواعد حاکم (ارث‌برده از پروژه)

  1. henza_pwa/، henza_server/ و henza_admin/ فقط خواندنی‌اند. برای اجرای مرجع یک کپی بیرون از آن‌ها ساخته می‌شود؛ حتی node_modules هم داخلشان نصب نمی‌شود.
  2. D4 — رفتار تکرار می‌شود، خرابی نه. هر عدم‌تکرار عمدی در ماتریس: «عمداً تکرار نشد — ISSUE #n».
  3. D2 — چیزی که مرجع ندارد ساخته نمی‌شود. یعنی اپ کلاسیک صفحه‌ی اعلان‌ها، تنظیمات ظاهر و تب پنجم ناوبری را ندارد، چون مرجع ندارد.
  4. PROTECTED.md — user-app و user-app-v2 دست نمی‌خورند. حتی بازساختاردهی (مثلاً بیرون کشیدن کد مشترک) تأیید جدا می‌خواهد.
  5. D13 — سطوح فروشگاه تک‌فروشی (کیف پول، cashback، قیمت محصول طبق D16) دست نمی‌خورند.
  6. D12 — ماتریس فیلد به فیلد، و تست رفت‌وبرگشت برای هر موجودیتی که endpoint نوشتنی تازه می‌گیرد.
  7. D18 — تأیید دائمی برای شکاف‌های بی‌ابهام؛ توقف فقط برای موارد فهرست D18.
  8. T1 / D21 — مشتری همیشه از توکن، هرگز از بدنه یا URL؛ ادعای typ؛ تست توکن متقابل.
  9. D25 — خواندن env فقط با envOr / envOrNull.
  10. D15 — تست‌هایی که ورودی فارسی دارند، ورودی را از فایل UTF-8 می‌خوانند.

⚠️ CLAUDE.md در این مخزن نیست. اسناد parity مدام به §2، §3، §4 و §6 آن ارجاع می‌دهند، ولی فایل در ریشه‌ی workspace قبلی بوده. قواعدش از روی همین ارجاع‌ها بازسازی شده: §2 منطق اپ‌های کاربر باید یکسان باشد و فقط طراحی فرق کند؛ §3 باگ مرجع تکرار و ثبت شود، مگر حفره‌ی امنیتی در جریان پول — آنجا توقف و سؤال؛ §4 PROTECTED فقط افزایشی؛ §6 هر حذف داده در CHANGELOG ثبت شود. پیشنهاد: نسخه‌ی اصلی را به مخزن برگردانید تا متن اصلی جای این بازسازی را بگیرد.


دامنه‌ی واقعی کار (اعداد راستی‌آزمایی‌شده)

سنجه عدد نحوه‌ی راستی‌آزمایی
route 22 (۲۱ واقعی + catch-all) _inv-ref-pwa.md §3
فایل .vue غیر vendored 77 فایل، 12,445 خط find src -name '*.vue' بدون دو پوشه‌ی DatePicker
فایل‌های views/ 34 — سه‌تا مرده: login.vue (کل فایل کامنت)، user/src/components/report.vue (صفحه‌ی دیباگ)، NotificationList.vue (سوار نشده) §6.1
کامپوننت اپ 40 §9
store ۹ singleton دست‌ساز + ۱ Pinia §7
endpoint یکتا 44 در ۵۸ محل فراخوانی → ۳۹ ردیف کارکردی زنده بعد از کنار گذاشتن مرده‌ها §2.4 + §نقشه‌ی endpoint در همین سند
پوشش API هدف از آن ۳۹ ردیف ✅ 12 · 🟡 9 · ❌ 18 §نقشه‌ی endpoint
@keyframes 8 grep
محل <transition> ۷ زنده + ۲ کامنت‌شده (از جمله انتقال بین صفحه‌ها) grep
GSAP / useTransition ۱ / ۱ — هر دو در ناوبری پایین navigation.vue:83,110
overlay ۲۰ Drawer، ۳ Modal، ۲ van-action-sheet grep
asset ۲۴ svg، ۹ png، ۱ jpg، ۱ ico، فونت Yekan Bakh FaNum (۸ وزن × ۳ فرمت)، icons.json find src/assets public
نقص شناخته‌شده‌ی مرجع 20 §13

«تکنولوژی جدید» — چه چیزی عوض می‌شود و چه چیزی نه

کتابخانه‌های UI روی نسخه‌ی lockfile مرجع قفل می‌شوند

یافته: yarn.lock مرجع خودش Vue 3.5.40 را resolve کرده. پس «تکنولوژی جدید» در کتابخانه‌های UI معنایی ندارد — و نباید داشته باشد، چون ظاهر پیکسلی دقیقاً به همین نسخه‌ها وابسته است. مثلاً ant-design-vue 4 استایل را به CSS-in-JS برده و ظاهر عوض می‌شود.

بسته نسخه‌ی دقیق (بدون ^)
ant-design-vue 3.2.20
vant 4.10.0 — v1/v2 روی 4.10.2 هستند؛ اپ کلاسیک نسخه‌ی مرجع را می‌گیرد
swiper 7.4.1
gsap 3.15.0
tailwindcss 3.0.18
@vueuse/core 9.13.0
moment-jalaali 0.10.4
@lottiefiles/dotlottie-vue 0.4.18
vue3-lazyload 0.2.5-beta
vue / vue-router 3.5.x / 4.x — همان خانواده‌ی lockfile

ارقام فارسی از فونت می‌آیند، نه از تبدیل. مرجع هیچ تبدیل رقمی ندارد (§8.1)؛ ارقام به‌خاطر فونت FaNum فارسی دیده می‌شوند. اپ کلاسیک هم تبدیل رقم اضافه نمی‌کند.

آنچه واقعاً نو می‌شود

مرجع اپ کلاسیک چرا
Vite 3 + plugin-vue 2، TS 4.4 بدون strict، vue-tsc 0.29 Vite 5، TS 5 با strict، vue-tsc 2 — همان زنجیره‌ی v1/v2 ابزار نگهداری‌شده؛ خطا در زمان build
axios 0.25 با سه instance؛ interceptor خطا promise را برنمی‌گرداند؛ response interceptor ندارد یک client تایپ‌شده؛ توکن در هر درخواست؛ رفتار 401 مرجع (myStore.init()) به‌صورت سراسری نقص #1 و #2
۹ singleton کلاسی دست‌ساز Pinia — با همان شکل state و همان getter های readonly یکدستی با v1/v2
Mixin ها (getProducts، product، favorite، ...) composable های تایپ‌شده با تست واحد قابل تست
URL و کلید هاردکد در ۵ فایل متغیرهای VITE_* پیکربندی محیط‌ها
دو درخت vendored از DatePicker (fork از ant-design-vue) generatePicker عمومی ant-design-vue 3 با config جلالی — به شرط اثبات ظاهر یکسان در Phase 0 حذف هزاران خط کد شخص ثالث
۵ کتابخانه‌ی تاریخ moment-jalaali برای فرمت‌ها (خروجی یکسان) + dayjs/jalaliday فقط برای picker کمتر، با تست خروجی
۴ کامپوننت تقریباً یکسان ScrollFetch* یک کامپوننت با prop تکرار
addTransaction.vue و addFindoc.vue تکراری یک فرم، دو پوسته (صفحه و drawer) تکرار
کد مرده (§چیزی که پورت نمی‌شود) پورت نمی‌شود —
PWA در mode: "development" production نقص #17
بدون تست تست واحد (adapter، formatter، validator، موتور تخفیف) + e2e و مقایسه‌ی تصویری با Playwright اثبات «دقیقاً»

تنش‌هایی که قبل از شروع باید تصمیمشان را بدانید

تنش ۱ — ۱۸ endpoint مرجع در API هدف نیست

از ۳۹ ردیف زنده، ۱۸ تا در هدف معادل ندارند و ۹ تا ناقص‌اند (§نقشه‌ی endpoint). بدون آن‌ها «دقیقاً مثل مرجع» ممکن نیست. وضعیت امروز v1/v2 این را نشان می‌دهد:

  • ثبت‌نام هیچ چیزی ذخیره نمی‌کند — کامنت خود RegisterView.vue:17 این را می‌گوید.
  • علاقه‌مندی‌ها فقط محلی‌اند (favoritesStore.ts:1-3).
  • ثبت سند، سفارش ساخت، مدیریت مشتری توسط کارشناس، ویرایش سفارش مشتری، آنالیتیکس و فاکتور اصلاً وجود ندارند.

ساختن این‌ها در apps/api افزایشی است (route و جدول/ستون جدید). ولی با CLAUDE.md §2 تعارض دارد: منطق اپ‌های کاربر باید یکسان باشد. به محض اینکه اپ کلاسیک ثبت‌نام و علاقه‌مندی واقعی داشته باشد، v1 و v2 عقب می‌افتند.

پیشنهاد: بک‌اند یک بار، افزایشی و تست‌شده ساخته شود. وصل کردن v1/v2 به آن یک کار جدا و ثبت‌شده باشد — نه بخشی از این پروژه. تصمیم شما لازم است که §2 شامل اپ کلاسیک هم می‌شود یا نه.

تنش ۲ — «انتخاب مشتری»: کار کردن به‌جای مشتری

در مرجع: کارشناس فروش (type 1) روی یک مشتری می‌زند → toggleActiveUser توکن خود آن مشتری را به‌عنوان activeChildToken ذخیره می‌کند، و این توکن روی همه‌ی درخواست‌ها اولویت دارد (store/tokenManage.ts:8-10، store/myDataStore.ts:159-169). از آن لحظه کل اپ به‌جای مشتری کار می‌کند: میز کار موجودی مشتری را نشان می‌دهد، سفارش سبد روی حساب مشتری با from_parent: true ثبت می‌شود تا پیامک به کارشناس برسد (views/cart.vue:162-164)، و دکمه به «خروج از حساب مشتری» تبدیل می‌شود.

در هدف: D21 سازوکار را رد کرد — ساختن توکن مشتری برای کارشناس یک ابزار ربودن نشست است. CustomerChoiceView در v1 با لمس کارت فقط یک drawer جزئیات باز می‌کند (openDetail). پس خود این قابلیت امروز در هدف وجود ندارد.

پیشنهاد: همان قابلیت، با سازوکار امن:

  • توکن خود کارشناس + هدر X-Acting-As: <customerId>.
  • سرور در هر درخواست چک می‌کند referredByAgentId آن مشتری = همین کارشناس.
  • موضوع همه‌ی route های مشتری = آن مشتری.
  • سفارش با پرچم from_parent ثبت می‌شود.
  • هر تعویض در لاگ ثبت می‌شود.
  • هیچ توکنی ساخته نمی‌شود و سمت کلاینت فقط شناسه‌ی مشتری انتخاب‌شده نگه داشته می‌شود.

تأیید شما لازم است، چون امنیت و جریان پول است (CLAUDE.md §3). این کار ریسک REL-03 را هم بالاتر می‌برد — §پیش‌نیازها.

تنش ۳ — نقش کارگاه (type 5) در اپ

در مرجع: سرپرست کارگاه یک ردیف مشتری با type 5 است. کاشی «سفارش ساخت» برایش مستقیم به صفحه‌ی وضعیت می‌رود و دکمه‌های «تایید سفارش» و «ارسال سفارش» را می‌بیند (makeOrderStatus.vue:68-75).

در هدف دو نامزد هست:

  • AdminUser با نقش WORKSHOP_SUPERVISOR — Workshop.supervisorId به اینجا اشاره می‌کند و PreOrder.workshopId به Workshop.
  • Customer با kind = WORKSHOP_SUPERVISOR — این مقدار در CustomerKind هست و برخلاف SALES_AGENT منسوخ اعلام نشده.

D21 فقط به SALES_EXPERT اجازه‌ی ورود به اپ‌ها را داده.

پیشنهاد: AdminUser، چون مسیر داده‌ای تمیز همین است. الگوی D21 به WORKSHOP_SUPERVISOR گسترش پیدا کند، با دامنه‌ی محدود به PreOrder های کارگاه خودش. تصمیم شما لازم است، از جمله اینکه مشتری با kind = WORKSHOP_SUPERVISOR در این صورت چه نقشی دارد.

تنش ۴ — خرابی‌های مرجع که به منطق کسب‌وکار می‌خورند

D18 برای این‌ها توقف می‌خواهد (مورد ۴). شماره‌ها از _inv-ref-pwa.md §13 است.

# خرابی در مرجع اثر برای کاربر پیشنهاد من
4 دکمه‌ی ثبت در صفحه‌ی addTransaction بیرون از <Form> است و html-type="submit" ندارد (addTransaction.vue:84-97) ثبت سند از صفحه کار نمی‌کند؛ فقط از drawer درست شود — یک فرم مشترک، هر دو پوسته کار کنند
5 کاشی «سفارش مشتریان» تابع را صدا نمی‌زند (Dashboard.vue:119) کارشناس از میز کار به آن صفحه نمی‌رسد درست شود — D3 خود صفحه را خواسته
6 کادرهای ته‌حساب طلایی و ریالی اندیس‌ها و formatter ها را جابه‌جا خوانده‌اند (Dashboard.vue:182-192) موجودی طلا و ریال در کادر اشتباه و با قالب اشتباه هر کادر مقدار درست را با قالب متناسب با برچسبش نشان دهد
8 دکمه‌ی به‌روزرسانی قیمت، فهرستی را تازه می‌کند که نمایش داده نمی‌شود (store.ts:107 در برابر Dashboard.vue:632) به‌روزرسانی بی‌اثر قبلاً تصمیم گرفته شده (D4): فهرست دیده‌شده تازه شود
9 «ارسال سفارش» همان {sts: 2} «تایید سفارش» را می‌فرستد (makeOrderStatus.vue:212,234) ارسال در سرور ثبت نمی‌شود تایید → «تایید کارگاه»، ارسال → «ساخته شده آماده ارسال». مقدار دقیق PreOrderStatus را شما تعیین کنید
12 radio «حواله به» اندیس آرایه را می‌فرستد نه متن مقصد (addTransaction.vue:50). سرور مرجع کل بدنه را بی‌تغییر ذخیره می‌کرد (ApiMobileController::setFindoc) مقصد حواله به‌صورت عدد ذخیره می‌شد سرور اندیس را به متن مقصد نگاشت کند؛ UI بی‌تغییر
14 در editUser سه آپلودر مدرک شناسه را دور می‌ریزند و دو تا یک fileList مشترک دارند (editUser.vue:65,69) آپلود «موفق» دیده می‌شود ولی چیزی ذخیره نمی‌شود عیناً تکرار شود و ثبت شود — وصل کردنش داده‌ی احراز را از صفحه‌ای عوض می‌کند که مرجع هرگز اجازه نداده بود
15 شرط infinite scroll گزارش tableData.value.count را می‌خواند که هرگز مقدار نمی‌گیرد (report/index.vue:234) فقط صفحه‌ی اول گزارش دیده می‌شود درست شود — endpoint های D24 صفحه‌بندی دارند
19 پسوند تومان روی فیلدی به نام rial_remain (filters/index.ts:13)؛ ستون هدف fiatDebtRial به ریال است اگر واحدها نخوانند، بدهی ده برابر کم یا زیاد خوانده می‌شود اول در henza_server واحد واقعی rial_remain معلوم شود؛ بعد adapter همان عدد و برچسبی را نشان دهد که مرجع برای همان بدهی نشان می‌داد
— singleProduct دکمه‌ی back را می‌رباید: history.pushState + window.onpopstate = () => history.go(1)، سراسری و هرگز برداشته نمی‌شود (singleProduct.vue:376-379) بعد از دیدن اولین محصول، back مرورگر یا گوشی در کل اپ از کار می‌افتد محدود به خود صفحه‌ی محصول — نیت ظاهری کد همین است، نشتش به کل اپ خرابی است

تنش ۵ — سرور هدف از مرجع سخت‌گیرتر است

سرور مرجع تقریباً هر چیزی را قبول می‌کرد. سرور هدف بیشتر رد می‌کند: قاعده‌ی موجودی و پیش‌سفارش (PROTECTED §C.1)، MON-05 وقتی اجرا شود، DTO های اعتبارسنجی، قیدهای یکتایی. ولی UI مرجع در بیشتر خطاها هیچ چیزی نشان نمی‌دهد — فقط console.log(e)، مثلاً در Register.vue:340-342، cart.vue:189-191 و ثبت سند. پس درخواستی که مرجع بی‌صدا قبول می‌کرد، در اپ کلاسیک بی‌صدا شکست می‌خورد و کاربر گیج می‌شود.

مورد پیشنهاد من
سقف موجودی: سبد مرجع سقف ندارد؛ قاعده‌ی موجودی هدف (capQty/maxQty در v1) وجود دارد سقف بی‌صدا در دکمه‌ی + اعمال شود — بدون هیچ عنصر یا متن تازه
خطاهای بی‌صدا هر جا مرجع بی‌صدا بوده بی‌صدا بماند، مگر جایی که سرور هدف ردی می‌کند که مرجع هرگز نداشت. آنجا نزدیک‌ترین پیام موجود مرجع نشان داده شود (مثلاً «خطا در ثبت سفارش» از makeOrder.vue:229). هیچ متن تازه‌ای ساخته نمی‌شود

تصمیم‌های کوچک‌تر

# سؤال پیشنهاد من
Q1 نام، مسیر و پورت اپ apps/user-app-classic، پورت 5183 (USER_APP_CLASSIC_PORT)، سرویس docker با همین نام. «classic» و نه «v3»، چون v3 «جدیدترین» را القا می‌کند در حالی که این قدیمی‌ترین طراحی است
Q2 کد مشترک بین سه اپ فعلاً داخل خود اپ در src/core/ (api، adapter، قواعد دامنه)، با مرز تمیز تا بعداً قابل استخراج باشد. پکیج مشترک یعنی بازساختاردهی v1/v2 → PROTECTED → تصمیم جدا
Q3 فیلتر رنگ در جست‌وجو — هدف اصلاً داده‌ی رنگ ندارد (Product و ProductVariant فقط brand دارند) مدل افزایشی Color و ارتباطش با variant؛ ویرایشش در پنل ادمین کار جداگانه است. تا آن موقع فهرست خالی — همان چیزی که مرجع با داده‌ی خالی نشان می‌داد
Q4 تابلوی قیمت میز کار: مرجع ۱۴ ردیف دارد (۸ طلا و سکه + ۶ ارز و انس، store.ts:118-119)؛ هدف فقط نرخ طلا به ازای عیار ردیف‌هایی که هدف داده‌ی واقعی برایشان دارد نمایش داده شوند؛ بقیه حذف (قاعده‌ی صداقت، مثل REP-01) تا منبع قیمت تأیید شود. منبع خارجی = تصمیم شما
Q5 ترتیب دسته‌های خانه: آرایه‌ی هاردکد [37, 45, 31, 32, 42, 26, 36, 35, 34] با شناسه‌ی عددی legacy (home/index.vue:189-204)؛ شناسه‌ی Category در هدف cuid است و نه legacyId دارد نه ستون ترتیب ستون افزایشی ترتیب روی Category و پر کردنش از نگاشت مهاجرت. پر کردن = تغییر داده‌ی موجود → D18 توقف #5 → تأیید لازم
Q6 آنالیتیکس مهمان: مرجع برای مهمان هم لاگ می‌فرستد؛ CustomerActivityLog.customerId اجباری است و ستون پایان ندارد فقط کاربر واردشده لاگ شود؛ ستون افزایشی endedAt برای معادل log/update
Q7 اعلان‌ها، FCM و پرکردن خودکار OTP — هر سه در مرجع سوار نیستند یا غیرفعال‌اند ساخته نمی‌شوند — دقیقاً مثل مرجع
Q8 اجرای مرجع برای مقایسه‌ی تصویری کپی در .parity/ref-pwa/ (gitignored) و رهگیری شبکه با Playwright؛ خود مرجع دست نمی‌خورد
Q9 وضعیت D19 (حالت تحویل) این پلن فرض می‌کند D19 تمام شده و D18 برقرار است

پیش‌نیازهای باز از کارهای قبلی

مورد چرا این اپ به آن نیاز دارد Batch
D9 قدم ۵ — جابه‌جایی filterPercentPay به اندازه‌ی آفست مشتری اسلایدر اجرت در فیلتر جست‌وجو B
شکاف یکتایی شماره بین Customer و AdminUser — هر چهار بررسی تداخل فقط adminUser را چک می‌کنند؛ در ISSUES.md ثبت نشده ثبت‌نام و «افزودن کاربر» هر دو مشتری می‌سازند A، F
MON-08 — سرور اجرت و تخفیف را خودش بسازد ثبت سفارش از سبد E
MON-05 — اجرای canPlaceOrders و verificationStep مرجع فقط در کلاینت چک می‌کند (sts_verify_step_two === 2) E
REL-03 — مقدار جدای JWT_CUSTOMER_SECRET کار به‌جای مشتری (تنش ۲) ریسک آن را بیشتر می‌کند قبل از F

نقشه‌ی endpoint ها — مرجع ↔ هدف

✅ موجود (فقط adapter شکل) · 🟡 ناقص · ❌ وجود ندارد

# مرجع هدف امروز وضعیت Batch
1 POST /web/auth POST /customer/auth/request-otp ✅ A
2 POST /user-verfiy POST /customer/auth/verify-otp ✅ — رد ورود برای sts_verify_step_one == 3 بررسی شود A
3 POST /major/register — ❌ A
4 POST /major/complete POST /customer/me/complete-profile ✅ (D22) A
5 POST file/create POST /customer/me/documents ✅ با purpose A، D، G
6 POST /me-data GET /customer/me 🟡 هیچ‌کدام از filterBrand، filterColor، filterGram، filterPercentPay، favorits، to، reagent، grams_sell، mcode را ندارد Phase 2
7 POST /front GET /catalog/products 🟡 دسته‌ها، more و ciny آماده نیستند B
8 POST /get-products (Query) GET /catalog/products 🟡 فیلتر و صفحه‌بندی سمت سرور ندارد (STUB-03) B
9 POST /get-products (products_id) GET /catalog/products 🟡 B، E
10 GET /ciny/{cat} داخل catalog (collections) 🟡 B
11 GET /product/{id} — فقط فهرست 🟡 B
12 GET /config GET /home/slider 🟡 about ندارد B
13 GET /promotion — ❌ B
14 GET /ignore — ❌ B
15 GET /price GET /pricing/latest 🟡 فقط طلا به ازای عیار (Q4) C
16 GET /tahesab/me GET /customer/me/report/balances ✅ (D24) C
17 POST /add-to-fav — ❌ (v1/v2 محلی) D
18 POST /get-favorites — ❌ D
19 POST /get-orders GET /customer/me/orders ✅ فیلتر sts در کلاینت D
20 POST /update-profile — ❌ D
21 POST /get-my-findoc GET /customer/me/ledger-entries 🟡 شکل متفاوت D
22 POST /set-findoc — ❌ D
23 GET /fin_tahesab/table GET /customer/me/report ✅ (D24) D
24 GET /fin_tahesab/my_detail/{offset} GET /customer/me/report/detail ✅ D
25 GET /fin_tahesab/detail/{code} GET /customer/me/report/:id ✅ D
26 report/order?order_id — فاکتور با window.open — ❌ D
27 report/doc?doc_id — فایل سند — ❌ D
28 POST /set-order POST /orders ✅ (MON-08) E
29 POST /my-child POST /expert/my-customers ✅ F
30 POST /customer/toggle-active — ❌ F
31 POST /customer/create — ❌ F
32 POST /customer/update — ❌ F
33 GET admin/major/list_type — ❌ از CustomerKind ساخته می‌شود F
34 POST /order/child POST /expert/child-orders ✅ F
35 PUT /order/child/{id} — ❌ F
36 POST /create-custom-order — مدل PreOrder فقط در ادمین ❌ G
37 GET /get-custom-orders — ❌ G
38 POST /update-custom-order/{id} — ❌ G
39 POST /log/create/{key} + GET /log/update/{id} — ❌ G

ساخته نمی‌شوند (در مرجع مرده‌اند): POST /hesab_detail/table (هرگز صدا زده نمی‌شود)، تکرار GET /ignore در getCustomerListType، تکرار مرده‌ی toggle-active در Dashboard، POST /cities/list (داده گرفته می‌شود ولی UI آبشاری کامنت است و فیلد شهر متن آزاد است — Register.vue:58-64)، و سه endpoint اعلان (کامپوننتشان سوار نیست).


مشخصات حس و حرکت — انیمیشن‌ها و ناوبری

این بخش همان چیزی است که یک پورت سرسری از دست می‌دهد. هر ردیف در Phase 0 با ضبط frame اثبات می‌شود.

انیمیشن‌ها

# انیمیشن پارامتر دقیق محرک شاهد
1 فرورفتگی (notch) ناوبری پایین gsap.to('.from-path', {duration: .3, attr: {d: draw()}}) تغییر تب components/ui/navigation.vue:50-86
2 جابه‌جایی آیکون فعال useTransition با TransitionPresets.easeInOutCubic، ‏150ms تغییر تب navigation.vue:110-117
3 shutter هدر @keyframes shutter در 1s با cubic-bezier(0.33, 1, 0.68, 1)؛ max-height از 0 تا 120px و opacity از 0 تا 1 هر تغییر route: afterEach پرچم را false و بعد از 100ms دوباره true می‌کند components/appHeader.vue:1-45، router/index.ts:273-286
4 فاصله‌ی محتوا از هدر margin-top = headerHeight وقتی transitionEnded همراه ۳ components/content.vue:2
5 انتقال بین صفحه‌ها ندارد. <transition> در App.vue:6,17 کامنت است. CSS slideDown (App.vue:151-166) و setPgaTransition زنده‌اند ولی به هیچ چیز وصل نیستند — اضافه نمی‌شود
6 باز شدن بخش فیلتر @keyframes drop با mode="out-in" appear باز و بسته کردن components/dropDown.vue:11,40
7 تعویض تصویر گالری slideUp با mode="out-in" تغییر تصویر یا تنوع views/singleProduct.vue:28، components/slider/slider.vue:22
8 اسپینر @keyframes rotate و rotateOpacity (سه حلقه) بارگذاری components/spinner.vue:104,115
9 ریل سفارش ساخت @keyframes gradientMove و colorChange روی رابط مرحله‌ی جاری نمایش وضعیت makeOrderStatus.vue:283,295
10 دیالوگ‌ها و notify قواعد animation: باز شدن DialogVant.vue، DialogVantOneButton.vue، NotifyVant.vue
11 فهرست اسناد TransitionGroup name="list" + کوییرک testBind (#13) بارگذاری فهرست transactions.vue:17,177-205
12 notify قدیمی @keyframes notify-in — customNotification.vue:47، Notification.vue:81 — اول بررسی شود سوار هستند یا نه
13 اسلایدر خانه Swiper با loop و autoplay خودکار slider/homeSlider.vue:7,10
14 اسلایدر محصول Swiper با ماژول Zoom، بدون loop لمس slider/slider.vue:43-45
15 overlay ها انیمیشن خود کتابخانه برای ۲۰ Drawer، ۳ Modal و ۲ action-sheet — با قفل نسخه‌ها تضمین می‌شود
16 دیالوگ نسخه‌ی جدید Lottie تغییر version App.vue:22-38

زمان‌بندی‌ها

چه چیزی مقدار شاهد
دیالوگ تشویق به ورود در خانه 5 ثانیه، در هر بازدید — گارد «فقط یک بار» کامنت شده home/index.vue:210-216
شمارش معکوس OTP 120 ثانیه، با صفر پیشرو زیر 10 Login.vue:122-131,187-189
toast ها 4000ms Dashboard.vue:269-284 و بقیه
debounce جست‌وجو 700ms components/search/SearchInput.vue
بازگرداندن پرچم انتقال هدر 100ms router/index.ts:273-286

ناوبری

  • ۲۲ route با همان path، name و meta، از جمله حروف و نام‌های عجیب: /ChildOrder، /customerChoice، /addTransaction، /makeOrder_status، /complete_profile، userPage::hasSubRoute. خانه /home است و / به آن redirect می‌شود.
  • beforeEach همان شش قدم _inv-ref-pwa.md §5.1، با تصمیم‌های D3:
    • مهمان روی پنج route محافظت‌شده → toast «ابتدا وارد شوید» + خانه.
    • کاربر واردشده روی /login یا / → خانه.
    • تله‌ی cold-boot (isLoaded) — D3 گفته تکرار شود.
    • completeProfile بسته است وقتی sts_verify_step_two ∈ {1, 2}.
  • route هایی که مرجع در guard ندارد (addTransaction، makeOrderList، makeOrderStatus، addUser، editUser، ChildOrder، customerChoice، و report/reportDetail که خودشان redirect می‌کنند) در اپ کلاسیک هم در guard نیستند؛ سرور هدف به‌هرحال 401 می‌دهد.
  • ناوبری پایین: چهار تب به ترتیب index — کاربر (۱)، سبد (۲)، جست‌وجو (۳)، خانه (۴)؛ پیش‌فرض فعال ۴. فقط روی همین چهار route دیده می‌شود، و وقتی پنل فیلتر باز است پنهان می‌شود.
  • keep-alive + suspense با کلید route.name — هر صفحه‌ی دیده‌شده mount می‌ماند (مثلاً نتایج جست‌وجو بعد از برگشت حفظ می‌شوند). این بخشی از حس ناوبری مرجع است و حفظ می‌شود.
  • scrollBehavior: بازگرداندن savedPosition، وگرنه بالای صفحه.
  • layout FullPage (بدون ناوبری پایین) برای همان ۸ route مرجع؛ بقیه Master.
  • ربودن دکمه‌ی back در صفحه‌ی محصول — تنش ۴.

ساختار فازها

Phase 0 — تصمیم‌ها و زیرساخت اثبات (بدون کد اپ)

  1. پاسخ شما به تنش‌های ۱ تا ۵ و Q1 تا Q9.
  2. اجرای مرجع: کپی henza_pwa@b171fff در .parity/ref-pwa/ (gitignored)، yarn install --frozen-lockfile، اجرا روی پورت 3030. اگر toolchain قدیمی روی Node فعلی بالا نیاید → ریسک R1.
  3. یک مجموعه‌داده با دو خروجی: JSON به شکل API مرجع (برای رهگیری درخواست‌های https://henzagold.com/oapi/** در Playwright) و seed دیتابیس برای API هدف. یک منبع، دو projection — تا هر دو اپ دقیقاً یک داده را نشان دهند.
  4. پرسوناها: مهمان؛ مشتری تأییدنشده؛ مشتری تأییدشده (sts_verify_step_two = 2)؛ بنکدار (type 4)؛ کارشناس فروش (type 1)، و کارشناس در حال کار به‌جای مشتری؛ کارگاه (type 5).
  5. مقایسه‌ی تصویری: Playwright روی یک ماشین و یک مرورگر برای هر دو اپ؛ viewport های 390×844 و 768×1024 (کانتینر مرجع max-w-screen-md است)؛ نواحی پویا مثل تاریخ و تایمر ماسک می‌شوند. آستانه‌ی قبول همین‌جا توافق می‌شود.
  6. بررسی انیمیشن: ضبط frame در زمان‌های ثابت پس از محرک (مثلاً 0، 150، 300 و 1000ms) برای هر ردیف جدول انیمیشن.
  7. spike تقویم جلالی: generatePicker عمومی + config جلالی کنار fork مرجع. اگر مقایسه‌ی تصویری صفر نشد، fork به‌صورت vendored نگه داشته می‌شود.
  8. ساخت docs/parity/03-PWA-CLASSIC-MATRIX.md — فیلد به فیلد طبق D12.

🛑 Gate — توقف و تأیید شما.

Phase 1 — پایه‌ی apps/user-app-classic

  • اسکلت Vite 5 + Vue 3.5 + TS strict + Pinia + vue-router، با نسخه‌های قفل‌شده‌ی بالا.
  • asset ها بایت‌به‌بایت با checksum: فونت‌ها، icons.json و Icon.vue، تصاویر assets/img و empty، favicon، آیکون‌های manifest، فایل Lottie، whatsapp.png.
  • themeConfig/colors.json، متغیرهای less، tailwind.config.js و postcss-rtl — همان مقادیر.
  • index.html همان: عنوان «طلای منتزر»، theme-color ‏#1C2D56، قفل zoom، دکمه‌ی شناور واتس‌اپ (شماره از env، با مقدار پیش‌فرض مرجع). bale.png در public/ هست ولی در index.html استفاده نمی‌شود — بررسی می‌شود.
  • PWA: injectManifest، sw.ts فقط precache، manifest همان، mode production.
  • زیرساخت: پورت 5183، Dockerfile و nginx به الگوی v1، سرویس compose، اضافه شدن به build:release، به‌روزرسانی DELIVERY.md.

Phase 2 — لایه‌ی core

  • client HTTP: base از env، توکن در هر درخواست؛ 401 سراسری = همان کار myStore.init() مرجع (پاک کردن appToken، appCart و کلید acting-as، رفتن به خانه).
  • adapter ها — قلب کار: DTO هدف → شکل‌هایی که view های مرجع انتظار دارند (MyData، Product، Variant، cartItem، سفارش با sts عددی، ردیف سند، ردیف گزارش). view ها با همان نام فیلدهای مرجع bind می‌شوند. قاعده‌ی صداقت: چیزی که هدف ندارد null می‌شود و ردیفش پنهان — هرگز مقدار ساختگی.
  • نگاشت enum ها:
    • CustomerKind → type مرجع (۲، ۳، ۴، ۵؛ و ۱ برای کارشناس).
    • OrderStatus هدف (۹ وضعیت) → sts مرجع (۸ تب).
    • PreOrderStatus → رشته‌های فارسی sts_str_fa.
    • LedgerSourceType → نوع سند ۱ تا ۴ و ۹.
  • بک‌اند پایه: معادل کامل POST /me-data (ردیف ۶ نقشه) — همه‌ی صفحه‌ها به آن وابسته‌اند.
  • store های Pinia با همان state مرجع: base، me (از همین حالا با جای _activeUser برای تنش ۲)، cart (useStorage('appCart') با همان کلید و شکل)، nav، query، token، transition، windowData، report.
  • composable ها: getProducts با فرمول دقیق صفحه‌بندی floor(count/limit) - 1؛ موتور تخفیف (۴ نوع، نوع ۳ خاموش، بیشترین discount_percent)؛ getWage؛ getHasDiscountWage؛ علاقه‌مندی خوش‌بینانه.
  • formatter ها با همان خروجی: تومان با فاصله‌ها، truncate (نه round) در useTowDecimal، حذف علامت در useFormat. validator ها با همان پیام‌ها، ولی بدون پرچم g (نقص #18).
  • تست واحد برای همه‌ی این‌ها، با نمونه‌های مرجع.

Phase 3 — پوسته، ناوبری، انیمیشن

  • App.vue با keep-alive/suspense، دو layout، چک نسخه + دیالوگ Lottie، به‌روزرسانی بی‌صدای service worker.
  • router با ۲۲ route و guard ها؛ hook آنالیتیکس (وصلش در Batch G).
  • ناوبری پایین با GSAP، appHeader با shutter، content با margin.
  • کامپوننت‌های پایه: DialogVant، DialogVantOneButton، NotifyVant، spinner، empty، WorkActionSheet، container، ScrollFetch، SearchInput، otpInput، SingleImageUploader، InputDatePicker.
  • هر ردیف جدول انیمیشن با harness فاز ۰ اثبات می‌شود.

Batch A — ورود، ثبت‌نام، تکمیل پروفایل · حجم بک‌اند: کم

  • صفحه‌ها: LoginRegister/index.vue، Login.vue، Register.vue، completeProfile.vue، input/otpInput.vue، input/SingleOtpInput.vue.
  • بک‌اند:
    • معادل POST /major/register — مشتری تازه با verificationStep = UNVERIFIED، با بررسی یکتایی شماره در هر دو جدول.
    • رد ورود برای sts_verify_step_one == 3 با پیام «مجوز ورود ندارید» — نگاشتش به وضعیت هدف بررسی می‌شود.
    • تکمیل پروفایل و آپلود مدارک: موجود (D22).
  • کوییرک‌هایی که حفظ می‌شوند: OTP چهاررقمی (APP-01)؛ رنگ notify همیشه قرمز #DC2626، حتی برای موفقیت؛ برچسب دکمه «دریافت رمز عبور» / «دریافت مجدد رمز عبور»؛ دیالوگ موفقیت ثبت‌نام که با کلیک بیرون بسته نمی‌شود؛ فیلد شهر متن آزاد؛ تلفن فروشگاه بدون الگو.

Batch B — کاتالوگ · حجم بک‌اند: زیاد

  • صفحه‌ها: home/index.vue، search/searchPage.vue، search/collection/index.vue و CollectionCard.vue، newest.vue، singleProduct.vue (صفحه و حالت drawer)، components/product/*، components/search/*، components/slider/*، viewAll.vue.
  • بک‌اند:
    • معادل POST /front: دسته‌ها با total، icon و image؛ محصولات جدید؛ more؛ ciny.
    • معادل POST /get-products: همه‌ی کلیدهای Query (colors، brands، limit_percent، limit_gram، has_discount، text، cats، ciny_id، page، limit) با پاسخ {rows, count, limit}، و حالت products_id برای rehydrate سبد. سمت سرور، چون صفحه‌بندی مرجع سمت سرور است.
    • معادل GET /product/{id} و GET /ciny/{cat}.
    • معادل GET /config (about + main_slider).
    • معادل GET /promotion و GET /ignore برای کاربر واردشده.
  • کوییرک‌ها: ترتیب ۹ دسته (Q5)؛ دیالوگ ورود در هر بازدید بعد از ۵ ثانیه؛ ارتفاع اسلایدر min(width, 768) / 2.2125؛ تنوع پیش‌فرض = کمترین percentage_pay با fallback «بدون تنوع»؛ تخفیف نوع ۳ خاموش؛ «افزودن به سبد» فقط با sts_verify_step_two === 2؛ نمونه‌ی تصادفی ۶ کالکشن؛ برچسب «N فیلتر» / «اعمال فیلتر»؛ بازه فقط وقتی «فعال» حساب می‌شود که هر دو سرش عوض شده باشد؛ بنکدار اسلایدر اجرت را نمی‌بیند.
  • وابسته به: D9 قدم ۵، Q3، Q5، تصمیم دکمه‌ی back.

Batch C — میز کار (/user) · حجم بک‌اند: کم تا متوسط

  • صفحه‌ها: views/user/index.vue، Dashboard.vue، about.vue.
  • بک‌اند: تابلوی قیمت (Q4)؛ grams_sell برای کارشناس.
  • کوییرک‌ها: «بدهکار گرمی» / «بستانکار گرمی» با قدر مطلق؛ «فروش گرمی» فقط برای کارشناس؛ کاشی‌ها برای مهمان → دیالوگ ورود؛ دیالوگ «ّکاربر فعال شود؟» با همان تشدید سرگردان؛ دیالوگ خروج؛ متن‌های toast قیمت؛ سرتیتر تاریخ و ساعت قیمت که همیشه خالی است (#7 — کوییرک بصری).
  • تصمیم‌ها: #5، #6، #8، #19؛ تنش ۲ برای دکمه‌ی «انتخاب مشتری» / «خروج از حساب مشتری».

Batch D — سفارش‌ها، علاقه‌مندی‌ها، پروفایل، اسناد، گزارش · حجم بک‌اند: زیاد

  • صفحه‌ها: Orders.vue، product/order.vue، product/orderItem.vue، favorits.vue، profile.vue، editUser.vue، transactions.vue، addTransaction.vue، addFindoc.vue، report/index.vue، report/detail.vue، Accounting.vue، AccountingDetail.vue.
  • بک‌اند:
    • علاقه‌مندی: جدول افزایشی، toggle و list.
    • ویرایش پروفایل: فقط فیلدهای فرم (whitelist). مرجع کل بدنه را روی ردیف مشتری می‌نوشت (ApiMobileController::updateProfile — همان خانواده‌ی SEC-14). ستون‌های افزایشی birthDate و marriageDate (PERS-03).
    • اسناد: فهرست به شکل مرجع از LedgerEntry. ثبت سند به‌صورت ورودی تأییدنشده، با نرمال‌سازی آب‌شده value × ayar / 750 (همان REPAYMENT_MELTED_GOLD). پیامک به مدیران از env، به‌جای دو شماره‌ی هاردکد مرجع (الگوی SEC-15). مرجع اینجا هم کل بدنه را ذخیره می‌کرد.
    • فاکتور سفارش و فایل سند (معادل report/order و report/doc).
    • گزارش: موجود (D24).
  • کوییرک‌ها: ۸ تب وضعیت با همان رنگ‌ها (۰ و ۲ بدون رنگ)؛ ریل چهارمرحله‌ای با current = 1 پیش‌فرض؛ جست‌وجوی دقیق شماره در کلاینت؛ مودال تمام‌صفحه؛ باز شدن فاکتور در پنجره‌ای به نام _bank؛ دو دکمه‌ی شناور هم‌پوشان در اسناد، با همان ترتیب لایه‌ها؛ رنگ و آیکون ردیف برای type == 9؛ چهار تب فرم سند و متن ثابت تب «پولی»؛ دکمه‌ی «افزودن کاربر» که هنگام کار به‌جای مشتری پنهان است (#11).
  • تصمیم‌ها: #4، #12، #14، #15.

Batch E — سبد و ثبت سفارش · حجم بک‌اند: متوسط

  • صفحه‌ها: cart.vue، product/cartItem.vue.
  • بک‌اند: MON-08؛ MON-05؛ پرچم from_parent (تنش ۲).
  • کوییرک‌ها: کلید appCart و شکلش؛ حذف بی‌صدای ردیف‌هایی که محصولشان دیگر نیست؛ وقتی تعداد ۱ است، منفی به سطل زباله تبدیل می‌شود؛ drawer یادداشت 280px با textarea پنج‌خطی؛ جمع فقط وزن با .toFixed(2)؛ دیالوگ تأیید؛ صفحه‌ی موفقیت با شماره‌ی سفارش؛ بنکدار اجرت را نمی‌بیند.
  • تصمیم‌ها: تنش ۵.

Batch F — کارشناس فروش · حجم بک‌اند: زیاد

  • صفحه‌ها: customerChoice.vue، addUser.vue، ChildOrders.vue، و بخش‌های کارشناس در Dashboard و profile.
  • بک‌اند:
    • کار به‌جای مشتری (تنش ۲).
    • ساخت، ویرایش و فعال/غیرفعال کردن مشتری توسط کارشناس، با دامنه‌ی referredByAgentId و یکتایی شماره در هر دو جدول.
    • فهرست نوع مشتری (معادل admin/major/list_type) از CustomerKind.
    • ویرایش سفارش مشتری و ثبت نهایی (معادل PUT /order/child/{id}).
  • کوییرک‌ها: پیش‌پر کردن از sessionStorage.editCustomer؛ برگشت به customerChoice یا profile بر اساس query.from؛ ۲۲ منطقه‌ی تهران؛ بنکدار → sts = -1؛ toast شماره‌ی تکراری با قرمز #b10f0f؛ جست‌وجوی نام در کلاینت؛ ویرایش وزن خام (بدون اجرت)؛ دو متن تأیید.

Batch G — سفارش ساخت + آنالیتیکس · حجم بک‌اند: متوسط

  • صفحه‌ها: makeOrder.vue، makeOrderStatus.vue، کاشی سفارش ساخت در Dashboard، router/customAnalytics.ts.
  • بک‌اند:
    • ثبت و فهرست سفارش ساخت مشتری روی مدل موجود PreOrder (colorName، sizeSpec، minaColor، stoneColor، description، تصویر) + ستون افزایشی تعداد — فیلد sum مرجع در PreOrder نیست.
    • تأیید و ارسال توسط کارگاه (تنش ۳، #9).
    • آنالیتیکس روی CustomerActivityLog + ستون افزایشی endedAt (Q6).
  • کوییرک‌ها: نگاشت ۵ مرحله از رشته‌ی فارسی sts_str_fa — سرور باید همان رشته‌ها را بدهد؛ confirmedOrders فقط در حافظه است و با reload از دست می‌رود؛ کاشی برای type 5 مستقیم و برای بقیه مودال دوگزینه‌ای؛ اسپینری که به‌خاطر سایه‌انداختن متغیر loading هرگز دیده نمی‌شود.

Phase نهایی — ممیزی و تحویل

  • همه‌ی ردیف‌های ماتریس: ✅، یا ➖ با شماره‌ی ISSUE، یا ⏸️.
  • گزارش مقایسه‌ی تصویری همه‌ی صفحه‌ها × پرسوناها × viewport ها.
  • سرشماری‌ها (§معیار تمام شد).
  • typecheck، lint، build، docker compose، build:release.
  • به‌روزرسانی DELIVERY.md و PROGRESS.md.

روش کار هر Batch

  1. خواندن خط‌به‌خط فایل‌های مرجع آن batch — نه فقط inventory.
  2. ردیف‌های ماتریس، فیلد به فیلد.
  3. شکاف‌های بک‌اند: endpoint افزایشی + تست (رفت‌وبرگشت، توکن متقابل، IDOR).
  4. پورت view ها: template و style تا جای ممکن عین مرجع؛ script بازنویسی‌شده.
  5. مقایسه‌ی تصویری و انیمیشن در برابر مرجع.
  6. typecheck، lint، build.
  7. گزارش کوتاه: چه پورت شد، چه عمداً نشد (با شماره)، چه باگ تازه‌ای در مرجع پیدا شد.

تحت D18 بین batch ها توقف نمی‌شود؛ فقط برای موارد توقف D18 و gate فاز ۰.


معیار «تمام شد» — اثبات خودکار اینکه چیزی از دست نرفت

سرشماری چطور قبول
route استخراج path، name و meta از هر دو router ۲۲ از ۲۲، یکسان
رشته‌ها استخراج هر literal فارسی از فایل‌های زنده‌ی مرجع (template و script) همه در اپ کلاسیک موجود؛ هر غایب یا در §چیزی که پورت نمی‌شود هست یا خطاست
asset checksum همه یکسان
endpoint هر ردیف نقشه ✅ یا تصمیم ثبت‌شده
تصویر مقایسه‌ی هر صفحه × پرسونا × viewport زیر آستانه‌ی توافق‌شده در فاز ۰
انیمیشن frame های زمان ثابت منطبق
ماتریس — بدون ردیف باز
کیفیت typecheck strict، lint، build، compose سبز

چیزی که پورت نمی‌شود (و چرا)

هر مورد «کد مرده» قبل از کنار گذاشتن با جست‌وجوی importer تأیید می‌شود.

مورد چرا شاهد
src/views/login.vue کل فایل کامنت است login.vue:1,201
user/src/components/report.vue صفحه‌ی دیباگ، سوار نشده _inv-ref-pwa.md §6.1
NotificationList.vue و سه endpoint اعلان در مرجع سوار نیست home/index.vue:5
FCM (Mixins/fireBase.js) و firebase-messaging-sw.js در مرجع غیرفعال؛ کلید API هاردکد App.vue:105
پرکردن خودکار OTP (Web OTP API) غیرفعال App.vue:100
POST /cities/list UI آبشاری کامنت است Register.vue:58-64
cax، noneAuthUrl، canNavigate، getHomeRouteForLoggedInUser، getCustomerListType، loadingStore، filters sample.js، Date.vue، UploadPic.vue، updateProfile بی‌مصرف در makeOrder.vue، logOut دوم در user/index.vue کد مرده _inv-ref-pwa.md §2.2، §5.1، §8.6، §9
دو fetch تکراری در singleProduct یک fetch؛ نتیجه‌ی دیده‌شده یکسان #20
wage_weight و weight ثابت در payload سفارش سرور نادیده می‌گیرد DEAD-06
حلقه‌ی setInterval(reload) یک reload #10
کلید analytics به شکل undefined کلید از نام route #16
PWA در dev mode production #17

ریسک‌ها

# ریسک اثر کاهش
R1 مرجع روی Node فعلی بالا نیاید (Vite 3، plugin-vue 2، وابستگی webpack 5.0.0) بدون مقایسه‌ی تصویری، «دقیقاً» فقط با خواندن کد ادعا می‌شود Node قدیمی‌تر فقط در همان کپی؛ اگر نشد، اعلام صریح سطح اطمینان پایین‌تر
R2 تفاوت داده بین دو API adapter وسوسه می‌شود چیزی جعل کند قاعده‌ی صداقت؛ تست adapter با fixture
R3 تقویم جلالی ظاهر متفاوت spike فاز ۰؛ fallback به fork
R4 حجم بک‌اند بیشتر کار در apps/api است، نه در UI batch بندی بر اساس وابستگی
R5 رندر فونت بین ماشین‌ها تفاوت کاذب در مقایسه‌ی تصویری هر دو اپ روی یک ماشین و یک مرورگر
R6 keep-alive state کهنه بعد از برگشت — که رفتار مرجع است حفظ، با تست سناریوی برگشت
R7 v1/v2 عقب می‌افتند (CLAUDE.md §2) ناسازگاری منطقی بین اپ‌ها تنش ۱
R8 شناسه‌های عددی دسته‌ها ترتیب اشتباه دسته‌ها در خانه Q5

وضعیت اجرا

هنوز شروع نشده. قدم بعدی: پاسخ شما به تنش‌های ۱ تا ۵ و Q1 تا Q9؛ بعد Phase 0.