From d15bf885e2ab02e486d55eb7cdbfd9446cf5a8cf Mon Sep 17 00:00:00 2001 From: Wira Irawan Date: Sat, 30 May 2026 10:07:54 +0700 Subject: [PATCH] Fix product preorder and warranty submit flow --- HANDOFF.md | 35 ++++++++++ .../(dashboard)/products/new/details/page.tsx | 25 +++++-- .../(dashboard)/products/new/review/page.tsx | 2 +- .../products/new/specifications/page.tsx | 70 +++++++++++++++---- src/lib/product-draft.tsx | 6 ++ src/lib/product-request-validation.ts | 8 ++- src/lib/use-product-submit.ts | 20 +++++- 7 files changed, 143 insertions(+), 23 deletions(-) diff --git a/HANDOFF.md b/HANDOFF.md index 908b472..52e1e73 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -22,6 +22,41 @@ npx tsc --noEmit ## Latest Codex Changes After `76fb4f3` +### Product create preorder and warranty submit rules + +Files: +- `src/app/(dashboard)/products/new/details/page.tsx` +- `src/app/(dashboard)/products/new/specifications/page.tsx` +- `src/app/(dashboard)/products/new/review/page.tsx` +- `src/lib/product-draft.tsx` +- `src/lib/use-product-submit.ts` +- `src/lib/product-request-validation.ts` + +Behavior: +- Pre-order day placeholder is now `0`, not `14`, so an empty/unfilled value is visually obvious. +- If pre-order is checked, the Details step blocks Next unless `preOrderDay` is a valid number greater than or equal to 1. +- Warranty now has an On/Off switch in the Specifications step. +- When warranty is On: + - warranty type is required + - warranty duration must be greater than or equal to 1 + - the review page shows warranty information + - submit payload sends the filled `warrantyInformation` object +- When warranty is Off: + - warranty inputs are disabled and dimmed + - the review page hides warranty information + - submit payload still sends `warrantyInformation` as an object required by the backend, with: + +```json +{ + "type": null, + "duration": null, + "durationType": "MONTH" +} +``` + +- Frontend payload validation treats the above null-valued warranty object as warranty Off, so it does not block submit with warranty type/duration errors. +- Local test server was rebuilt and restarted against `https://api-dev.inatrading.co.id` in `.env.local`; `.env.local` is not committed. + ### AddProductRequest validation Files: diff --git a/src/app/(dashboard)/products/new/details/page.tsx b/src/app/(dashboard)/products/new/details/page.tsx index 82f3345..1f58fe8 100644 --- a/src/app/(dashboard)/products/new/details/page.tsx +++ b/src/app/(dashboard)/products/new/details/page.tsx @@ -171,6 +171,7 @@ export default function ProductDetailsPage() { const { submit, submitting } = useProductSubmit(); const { t } = useLanguage(); const d = t.dashboard.productNew.details; + const [preOrderError, setPreOrderError] = useState(""); const [keywordInput, setKeywordInput] = useState(""); const keywordLimitReached = draft.keywords.filter(Boolean).length >= MAX_KEYWORDS; const featureLimitReached = draft.features.length >= MAX_FEATURES; @@ -249,6 +250,17 @@ export default function ProductDetailsPage() { })); } + function goToPricing() { + const preOrderDay = Number(draft.preOrderDay); + if (draft.isPreOrder && (!Number.isFinite(preOrderDay) || preOrderDay < 1)) { + setPreOrderError("Hari pre-order wajib diisi minimal 1 hari."); + return; + } + + setPreOrderError(""); + router.push("/products/new/pricing"); + } + return (
@@ -318,14 +330,17 @@ export default function ProductDetailsPage() { setDraft((prev) => ({ ...prev, preOrderDay: e.target.value }))} - placeholder="14" + onChange={(e) => { + setPreOrderError(""); + setDraft((prev) => ({ ...prev, preOrderDay: e.target.value })); + }} + placeholder="0" type="number" min="1" className="w-full bg-surface-container-low border-none rounded-xl p-4 font-semibold focus:ring-2 focus:ring-primary/10" /> -

- Minimal 1 hari jika pre-order aktif. +

+ {preOrderError || "Minimal 1 hari jika pre-order aktif."}

@@ -517,7 +532,7 @@ export default function ProductDetailsPage() {