feat(apps): read products by id instead of loading the whole catalogue
Step 3 of docs/CATALOG-PAGINATION-PLAN.md. Step 2 added the targeted routes; these are the five callers that were fetching all ~16k products to find a handful of rows: product screen whole catalogue, then find(id) -> GET /products/:id cart re-sync whole catalogue for 2-3 lines -> ?ids= favourites whole catalogue, filtered here -> ?ids= home categories categories derived from it -> /products/facets order row labels joined on variantId -> included with the order Three of these were not merely slow, they were going to be wrong. Favourites filtered the loaded catalogue, so once the list pages a favourite outside the loaded slice silently disappears. Home categories were derived the same way, so a category whose products all sit further down would vanish from the home screen. Order rows looked their title up in the catalogue, which ALREADY failed for a product that had since left the storefront — exactly the old orders history exists for — and rendered a blank row. Order labels went to the server rather than to another id lookup: the item carries productVariantId, not a product id, so ?ids= could not answer it. One nested include in getOrders returns the variant, its product and the product's first image. Deliberately NOT filtered by storefront visibility, so a de-listed product still shows what was bought; asserted in the new spec. OrderItemCard is synchronous now — no fetch, no onMounted, the row renders complete on its first frame. variantLookup is deleted from catalogStore rather than left behind: it existed only to label order rows, and keeping it would have kept a reason to load the full catalogue. getProductsByIds chunks at 100 because the route caps ids there and drops the rest. A partial answer reads to callers as "these products are no longer on the storefront" — the cart would silently drop valid lines. Favourites already run to 874 rows in the imported data (FAV-01). A failed cart re-sync now leaves the cart alone: it is the person's own data in localStorage, and dropping lines because the network blinked is worse than a slightly stale price. The product screen tells a real 404 from a failed request, so only the former renders the not-found page. One bug introduced and caught while doing this: moving the home categories to /facets meant memory.init() no longer loaded the catalogue as a side effect, and the home rails read catalog.products — the home screen would have rendered empty rails. HomeView now loads it explicitly. Found by grepping every caller of configStore.init, which is also how I know HomeView is the only one. Still on the unpaged list by design: the home rails and the search/newest lists. Moving those onto paged reads is step 4, kept separate because it is the risky part — debounce, loading state, and telling "no results" from "still loading". api 334/334 across 30 suites; both apps vue-tsc clean. getOrders has a spec now (3 cases) because its include is a contract both apps depend on and the method had no test at all. Nothing click-tested — the cart re-sync and the favourites screen are the two worth a manual pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
cbb93dec5d
commit
9fc0886a57
@@ -113,13 +113,27 @@ ProductImage: @@index([productId])
|
||||
|
||||
## ۴. ترتیب اجرا (هر مرحله قابل تست و بیشکست)
|
||||
|
||||
| مرحله | کار | چرا این ترتیب |
|
||||
| مرحله | کار | وضعیت |
|
||||
|---|---|---|
|
||||
| ۱ | مهاجرت ایندکسها | بدون این، صفحهبندی هم کند است. مستقل و بیریسک. |
|
||||
| ۲ | چهار مسیر سرور + کش کلیدی + تست | سازگار عقبرو؛ اپها هنوز دستنخورده کار میکنند |
|
||||
| ۳ | `useProductDetail`، `cartStore`، `FavoritesView`، `configStore` → مسیرهای نقطهای | بزرگترین برد با کمترین ریسک؛ رفتار دیداری عوض نمیشود |
|
||||
| ۴ | `SearchView` / `NewestView` → صفحهبندی واقعی سرور | پرریسکترین (فیلتر + اسکرول)؛ آخر، وقتی بقیه پایدار است |
|
||||
| ۵ | حذف خوانش کل کاتالوگ و هشدار لاگ | فقط وقتی هیچ مصرفکنندهای نمانده |
|
||||
| ۱ | مهاجرت ایندکسها | ✅ **انجام شد** (`cbb93de`) — `Product` هیچ ایندکسی نداشت |
|
||||
| ۲ | مسیرهای سرور + تست | ✅ **انجام شد** (`cbb93de`) — صفحهبندی opt-in، فیلتر سمت سرور، ۱۷ تست |
|
||||
| ۳ | صفحه محصول، سبد، علاقهمندی، دستهها، برچسب آیتم سفارش | ✅ **انجام شد** — پنج مصرفکننده منتقل شد |
|
||||
| ۴ | `SearchView` / `NewestView` / rails خانه → صفحهبندی واقعی | ⏳ **باقی** — پرریسکترین (فیلتر + اسکرول) |
|
||||
| ۵ | حذف خوانش کل کاتالوگ و هشدار لاگ | ⏳ فقط وقتی هیچ مصرفکنندهای نمانده |
|
||||
|
||||
### یادداشت مرحله ۳ (انجامشده)
|
||||
|
||||
«برچسب آیتم سفارش» در طرح اولیه نبود و سر راه پیدا شد: `OrderItem` فقط
|
||||
`productVariantId` دارد نه `productId`، پس `?ids=` جوابش نمیداد. سرور همان را
|
||||
با یک `include` برمیگرداند — که برای محصول حذفشده هم کار میکند، برعکس روش
|
||||
قبلی که ردیف را خالی میگذاشت.
|
||||
|
||||
یک باگ هم در حین کار ساخته و گرفته شد: انتقال دستهها به `/facets` باعث شد
|
||||
`memory.init()` دیگر کاتالوگ را بار نزند و rails خانه خالی شود؛ `HomeView` حالا
|
||||
صریحاً کاتالوگ را بار میکند.
|
||||
|
||||
**مرحله ۴ هنوز باقی است** — یعنی rails خانه، جستجو و «جدیدترین» همچنان کل
|
||||
کاتالوگ را میگیرند. پس تا آن مرحله، سود واقعی ۱۶ هزار رکوردی کامل نشده.
|
||||
|
||||
## ۵. دو چیز که باید بدانی
|
||||
|
||||
|
||||
Reference in New Issue
Block a user