Files
InaTrading-Portal/HANDOFF.md

17 KiB

Handoff

Project: ina-trading-web Current branch: main Latest verified commit: 7e6446b

Summary

This codebase has recent updates around auth/onboarding, help/privacy pages, dashboard search, product creation/edit/review/detail, admin review/detail, stock/price editing, seller in-review listing, and backend request logging.

The latest build was verified successfully with:

npm run build

Current Local Changes After 7e6446b

These are the important local changes made after the last recorded commit. The latest local build was verified successfully with npm run build, and the production local server was restarted on http://localhost:3000.

Admin review compare flow

File:

  • src/app/admin/review/[productId]/page.tsx

Behavior:

  • Product update review now uses the compare API as the source of truth:
    • frontend proxy: GET /api/admin/review/{productId}/compare
    • backend: GET /api/v1.0/product/compare/{productId}
  • The compare payload is parsed from rows like:
    • productImages[id=...].image
    • productFiles[id=...].fileId
    • productModels[sku=...].price
    • categoryInformations[paramName=Design].paramValue
    • productFeatures[3]
    • nested objects such as complianceInformation.safetyWarning
  • The page reconstructs:
    • oldProduct from oldValue
    • newProduct from newValue
  • The compare layout is now section-paired, not product-paired:
    • Gambar Produk (Diajukan)
    • Gambar Produk (Live Saat Ini)
    • Detail Produk (Diajukan)
    • Detail Produk (Live Saat Ini)
    • and so on for features, keywords, info, files, models, compliance, warranty
  • Empty section pairs are hidden. If both proposed and live sections have no displayable content, nothing is rendered.
  • Status is not shown in the compare Detail Produk section and no longer marks the section as updated.
  • Compare image thumbnails are rendered as small square thumbnails with object-contain, so images are visible in full instead of cropped into wide banners.
  • Approve/reject for update reviews uses the resolved review/action id from compare, when available.

Reference test data:

  • /Users/wirabasalamah/Downloads/json compare.txt
  • Example compare API:
    • /api/v1.0/product/compare/ba70a8e3-2342-4cd3-a7c7-a0f1b58689ab

Image URL handling

Files:

  • src/lib/image-url.ts
  • src/components/product-variant-showcase.tsx
  • src/app/(dashboard)/products/[productId]/detail/page.tsx
  • src/app/admin/products/[productId]/page.tsx
  • src/app/admin/review/[productId]/page.tsx
  • src/app/admin/review/page.tsx
  • src/app/admin/news/new/page.tsx
  • src/app/admin/news/[newsId]/edit/page.tsx
  • src/app/admin/places/PlaceForm.tsx

Behavior:

  • Added shared image URL helper:
    • if backend already provides an image URL, use it as-is
    • otherwise build a fallback URL from imageId
    • default fallback uses /api/v1.0/file/image/tmp/{imageId}
  • Seller/admin product details and admin review now use backend image fields before building URLs.
  • Product variant showcase now supports image on product images and model images.

Product create/edit thumbnail persistence

Files:

  • src/app/(dashboard)/products/new/details/page.tsx
  • src/app/(dashboard)/products/new/pricing/page.tsx
  • src/app/(dashboard)/products/new/review/page.tsx
  • src/app/api/file/image/[...path]/route.ts

Behavior:

  • Added local API proxy for images:
    • GET /api/file/image/{path}
    • forwards to backend /api/v1.0/file/image/{path} with auth headers
  • Create product step 2 and step 3 reload thumbnails from saved file ids when navigating forward/back.
  • Create product final review shows real thumbnails for visual identity and model images.
  • Review page was made full width and now displays model image and measurement details more completely.

Product create submit debug logging

File:

  • src/app/api/products/create/route.ts

Behavior:

  • When DEBUG_BACKEND_PROXY=true, create product submit writes product-create-submit-log.json.
  • The log captures:
    • local endpoint
    • backend endpoint
    • redacted headers
    • full request payload
    • backend response

Current known finding from latest capture:

  • Payload sent top-level imageId and separate productImages.
  • Backend review detail returned top-level imageId from productImages[0], not from request top-level imageId.
  • Payload sent productFiles, but review detail returned productFiles: [] in the checked response.

Dashboard seller metrics

File:

  • src/app/api/dashboard/seller/route.ts

Behavior:

  • Fixed parsing of scalar metrics from backend payloads where data is an object like { total: 96 }.
  • Verified for Pendopo account that dashboard total products can resolve to non-zero.

Admin product list/detail

Files:

  • src/app/admin/products/page.tsx
  • src/app/admin/products/[productId]/page.tsx
  • src/app/api/admin/products/route.ts

Behavior:

  • Admin product list now renders product thumbnails in All Product and Deleted tabs.
  • Thumbnail uses the shared image URL helper.
  • Admin product detail now resolves main category by looking up categories/subcategories when backend omits subCategory.category.name.
  • Admin All Product endpoint was tested with:
    • GET /api/v1.0/admin/product?page=1&size=20
  • Backend returned:
    • HTTP 400
    • body {"responseCode":"000001","data":null,"responseDesc":"Bad Request"}
  • Current proxy behavior:
    • tries /api/v1.0/admin/product
    • if non-deleted tab and the admin endpoint fails, falls back to /api/v1.0/product
  • Deleted endpoint remains:
    • GET /api/v1.0/admin/deleted/product?page={page}&size={size}
  • Server log showed request reached backend with admin token and failed in about 3 ms, suggesting request validation/contract mismatch rather than auth or DB latency.

Seller profile save flow

Files:

  • src/app/(dashboard)/settings/page.tsx
  • src/app/api/seller/profile/route.ts

Behavior:

  • Seller profile edit saves via:
    • frontend: PUT /api/seller/profile
    • backend: PUT /api/v1.0/seller/store
  • Payload:
    • storeName
    • storeBiography
    • optional imageId when seller avatar was uploaded
    • optional storeImageId when store image was uploaded

Example payload:

{
  "storeName": "...",
  "storeBiography": "...",
  "imageId": "optional-file-id",
  "storeImageId": "optional-file-id"
}

Recent Commits

  • 7e6446b Refine seller onboarding and product review flows
  • e9a0cd0 Update product review, measurement, and backend logging flows
  • b266047 Fix TypeScript build errors in product detail and admin review

Main Changes

1. Auth, help, and onboarding

Files:

  • next.config.ts
  • src/app/(onboarding)/layout.tsx
  • src/app/(auth)/login/page.tsx
  • src/app/(auth)/register/verify/page.tsx
  • src/app/(auth)/forgot-password/page.tsx
  • src/app/(auth)/account-not-found/page.tsx
  • src/app/help/page.tsx
  • src/app/privacy/page.tsx
  • src/app/terms/page.tsx

Behavior:

  • Seller onboarding is enabled again
  • Seller login redirects incomplete seller profiles to onboarding
  • Register verify flow redirects seller to onboarding instead of dashboard
  • Forgot password support link opens default mail app to admin@inatrading.co.id
  • Forgot password ? button links to public /help
  • Account-not-found Bantuan, Kebijakan Privasi, and Syarat & Ketentuan link to public pages
  • Login Remember me now stores email and password in localStorage

2. Onboarding seller final submit flow

Files:

  • src/app/(onboarding)/onboarding/business/page.tsx
  • src/app/(onboarding)/onboarding/store-detail/page.tsx
  • src/app/api/seller/route.ts
  • src/app/api/seller/store/route.ts
  • src/app/api/warehouses/route.ts

Behavior:

  • Plan step was removed from seller onboarding UI flow
  • Warehouse Type is hidden in UI and forced to INA
  • Final onboarding submit is not a single endpoint. It calls, in order:
    1. POST /api/seller -> host POST /api/v1.0/seller
    2. PUT /api/seller/store -> host PUT /api/v1.0/seller/store
    3. GET /api/products/warehouses?page=1&size=100
    4. PUT /api/warehouses/{id} or POST /api/warehouses
  • Frontend tries to reuse backend autogenerated warehouse if found, to avoid duplicate warehouse creation

3. Backend proxy logging

Files:

  • src/lib/backend-fetch-logger.ts
  • src/instrumentation.ts
  • .env.local uses DEBUG_BACKEND_PROXY=true locally

Behavior:

  • Logs server-side fetch requests to backend
  • Logs request method, URL, headers, body preview
  • Logs response status, duration, headers, body preview
  • Redacts authorization header

Use this when tracing frontend-to-backend failures in local dev.

4. Product measurement mode on add product

Files:

  • src/app/(dashboard)/products/new/pricing/page.tsx
  • src/lib/use-product-submit.ts
  • src/app/(dashboard)/products/new/review/page.tsx

Behavior:

  • Each model has a Product Measurement switch
  • When enabled:
    • nested measurements are shown
    • model-level price, currency, weight, dimensions, promotion, packaging, and warehouse stock are disabled
    • at least 1 measurement row is required
  • Submit payload uses model.hasMeasurements
  • When measurement mode is active, model-level numeric fields are zeroed and model warehouses are omitted

5. Product measurement mode on edit product

File:

  • src/app/(dashboard)/products/[productId]/edit/page.tsx

Behavior:

  • Matches add-product measurement behavior
  • Uses explicit hasMeasurements state instead of guessing from array length
  • Disables model-level fields when measurement mode is on

6. Seller product review page improvements

File:

  • src/app/(dashboard)/products/new/review/page.tsx

Behavior:

  • Review now renders actual product thumbnails using backend file URLs
  • Previously it only showed image indicators, which was confusing
  • Review also reflects measurement-based pricing correctly

7. Product list page improvements

File:

  • src/app/(dashboard)/products/page.tsx
  • src/lib/product-variants.ts

Behavior:

  • Edit stock/price modal supports:
    • choosing model
    • choosing measurement if present
    • choosing warehouse
  • Warehouse labels use warehouse names from master warehouse API, not raw UUIDs
  • Product row status badges now show explicit state like active, draft, review, unpublished, deleted, rejected
  • Seller In Review listing now uses host endpoint /api/v1.0/seller/product/review
  • If list API returns minPrice = 0 and maxPrice = 0, frontend hydrates that row by fetching product detail and calculating effective price from model/measurement data

Important:

  • This fallback exists because some list rows from backend do not include valid min/max price for measurement-based products
  • Example verified case: product Pembersih Mobil returned 0/0 in list but IDR 50.000 in detail measurement

8. Product detail page improvements

File:

  • src/app/(dashboard)/products/[productId]/detail/page.tsx
  • src/components/product-variant-showcase.tsx
  • src/lib/product-variants.ts

Behavior:

  • Main category now resolves even when backend omits subCategory.category.name
  • Warehouse display now uses warehouse master names instead of UUID slices
  • TypeScript nullability issue for category resolution was fixed here
  • Seller detail, admin detail, and admin review now share the same variant presentation logic
  • Effective price rules:
    • no measurement: use model price
    • with measurement: use measurement price
    • multiple measurements: show min-max from measurements
    • multiple models: show min-max from effective model prices
  • Variant showcase now supports:
    • product-level summary price/weight/dimension
    • model selector
    • measurement selector
    • selected variant detail
    • model image thumbnail switching

9. Admin review page improvements

File:

  • src/app/admin/review/[productId]/page.tsx

Behavior:

  • Review supports model + measurement structures
  • New product review and compare review now handle measurement-driven price/weight/dimension/promo/stock
  • Compare view highlights updated sections using backend compare response and isUpdate
  • Product images are rendered using main image + gallery images
  • TypeScript issue around row.field nullability was fixed here
  • Single-product review view now follows admin product detail layout more closely
  • Compare view stays separate only for product update review
  • Approve/reject action flow:
    • UI POST /api/admin/review/{productId}
    • new create accept -> host POST /api/v1.0/product/accept/{productId} with { "state": "PUBLISHED" }
    • update accept -> host PUT /api/v1.0/product/accept/{productId} with { "state": "PUBLISHED" }
    • create reject -> host POST /api/v1.0/product/reject/{productId}
    • update reject -> host PUT /api/v1.0/product/reject/{productId}
  • Review approve does not resubmit full product payload. It only submits action and state.

Files:

  • src/app/(dashboard)/layout.tsx
  • src/app/(dashboard)/dashboard/page.tsx

Behavior:

  • Bell and message icons are intentionally grayed/disabled because no backend function exists yet
  • Dashboard search now resolves query results across dashboard content instead of behaving like a dead input

11. Sidebar submenu reliability

Files:

  • src/components/product-submenu-nav.tsx
  • src/components/admin-product-submenu-nav.tsx

Behavior:

  • Click behavior was hardened because submenu items were sometimes not navigating
  • Navigation is explicit via router.push(...)

Translation Files Touched

  • src/lib/translations/id.ts
  • src/lib/translations/en.ts

These include labels added for statuses and stock/price modal UI.

Important Findings

Product image inconsistency on Pembersih Mobil

Verified seller account:

  • Pendopo@Pendopo.com
  • password: password

Product:

  • Pembersih Mobil
  • ID: 92a8fae0-d067-4c90-be24-da31012aeaf9

Verified backend behavior:

  • list endpoint row returned minPrice: 0, maxPrice: 0
  • detail endpoint returned one measurement priced at IDR 50.000
  • detail endpoint currently returns:
    • imageId: null
    • productImages: []
    • model.imageId: null

Implication:

  • product images are currently absent in backend detail payload for this product
  • if user reports image visible in older browser tab, suspect stale tab state before assuming frontend regression

Admin review image issue

For at least one reviewed product, backend review payload returned:

  • image: null
  • imageId: null
  • productImages: []

In that case frontend cannot render images. If an image is missing in review, verify backend review payload before debugging frontend.

Edit product empty main image behavior

In edit product submit flow, empty imageId is currently sent as undefined, which means the field is omitted from JSON payload, not sent as null and not sent as empty string.

If backend requires explicit image removal via null, this behavior will need to be changed.

Seller in-review API note

Postman latest collection contains:

  • seller review listing: /api/v1.0/seller/product/review
  • generic review detail: /api/v1.0/product/review/{productId}

Current app matches this for listing and still uses generic review detail endpoint for product review detail.

Local Dev Notes

Run local dev:

npm run dev

Build verification:

npm run build

Dev Server Update Guide

Based on current deployment notes, dev server update flow is:

sudo -iu inadev
cd ~/apps/ina-trading-web
git fetch origin
git checkout main
git pull origin main
npm ci
npm run build
pm2 restart ina-trading-dev
pm2 save
sudo -iu inadev pm2 status

Current expected deployed commit after latest push:

7e6446b

Verify on server:

git rev-parse HEAD

Optional logs:

sudo -iu inadev pm2 logs ina-trading-dev --lines 100

Suggested Next Checks

  • Verify whether backend expects null when main image is intentionally removed during edit
  • Verify seller and admin review payload consistency for image fields
  • Verify warehouse master API always contains all warehouse IDs referenced in product payloads
  • Verify whether seller in-review detail also has a seller-specific detail endpoint in backend/Postman, to align with seller-specific listing endpoint
  • Investigate when product images were lost for Pembersih Mobil and whether edit/update flow can preserve old image ids more defensively
  • If submenu click issue still appears, inspect layout overlays with browser tooling
  • Consider adding field-level compare highlighting, not only section-level highlighting, in admin review compare page

Files Most Likely To Be Relevant Next

  • src/app/(dashboard)/products/new/pricing/page.tsx
  • src/app/(dashboard)/products/[productId]/edit/page.tsx
  • src/app/(dashboard)/products/new/review/page.tsx
  • src/app/(dashboard)/products/[productId]/detail/page.tsx
  • src/app/(dashboard)/products/page.tsx
  • src/app/admin/review/[productId]/page.tsx
  • src/components/product-variant-showcase.tsx
  • src/lib/product-variants.ts
  • src/lib/use-product-submit.ts
  • src/lib/backend-fetch-logger.ts