Fix admin review update detection and redirect cleanup
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useParams, useRouter, useSearchParams } from "next/navigation";
|
import { useParams, useRouter, useSearchParams } from "next/navigation";
|
||||||
import { Suspense, useEffect, useState } from "react";
|
import { Suspense, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
const API_BASE = process.env.NEXT_PUBLIC_API_URL || "https://be.inatrading.co.id";
|
const API_BASE = process.env.NEXT_PUBLIC_API_URL || "https://be.inatrading.co.id";
|
||||||
|
|
||||||
@ -61,6 +61,26 @@ function extractIdChange(payload: unknown) {
|
|||||||
| undefined;
|
| undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isProductUpdateFromCompare(
|
||||||
|
change:
|
||||||
|
| {
|
||||||
|
oldValue?: string;
|
||||||
|
newValue?: string;
|
||||||
|
isUpdate?: boolean;
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
|
) {
|
||||||
|
if (!change) return false;
|
||||||
|
const hasDifferentIds =
|
||||||
|
typeof change.oldValue === "string" &&
|
||||||
|
typeof change.newValue === "string" &&
|
||||||
|
change.oldValue !== "" &&
|
||||||
|
change.newValue !== "" &&
|
||||||
|
change.oldValue !== change.newValue;
|
||||||
|
|
||||||
|
return change.isUpdate === true || hasDifferentIds;
|
||||||
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
function ProductColumn({ product, label, accent }: { product: any; label: string; accent?: boolean }) {
|
function ProductColumn({ product, label, accent }: { product: any; label: string; accent?: boolean }) {
|
||||||
if (!product) return (
|
if (!product) return (
|
||||||
@ -208,6 +228,7 @@ function AdminReviewDetailPageInner() {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const [oldProduct, setOldProduct] = useState<any>(null); // original (compare)
|
const [oldProduct, setOldProduct] = useState<any>(null); // original (compare)
|
||||||
const [isComparison, setIsComparison] = useState(false);
|
const [isComparison, setIsComparison] = useState(false);
|
||||||
|
const [isUpdateProduct, setIsUpdateProduct] = useState(false);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [loadError, setLoadError] = useState("");
|
const [loadError, setLoadError] = useState("");
|
||||||
|
|
||||||
@ -216,6 +237,7 @@ function AdminReviewDetailPageInner() {
|
|||||||
const [actionSuccess, setActionSuccess] = useState("");
|
const [actionSuccess, setActionSuccess] = useState("");
|
||||||
const [showRejectModal, setShowRejectModal] = useState(false);
|
const [showRejectModal, setShowRejectModal] = useState(false);
|
||||||
const [rejectReason, setRejectReason] = useState("");
|
const [rejectReason, setRejectReason] = useState("");
|
||||||
|
const redirectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!params.productId) return;
|
if (!params.productId) return;
|
||||||
@ -223,6 +245,7 @@ function AdminReviewDetailPageInner() {
|
|||||||
setLoadError("");
|
setLoadError("");
|
||||||
setOldProduct(null);
|
setOldProduct(null);
|
||||||
setIsComparison(false);
|
setIsComparison(false);
|
||||||
|
setIsUpdateProduct(false);
|
||||||
|
|
||||||
const reviewFetch = fetch(`/api/admin/review/${params.productId}`, {
|
const reviewFetch = fetch(`/api/admin/review/${params.productId}`, {
|
||||||
headers: { "x-auth-token": getToken() },
|
headers: { "x-auth-token": getToken() },
|
||||||
@ -254,7 +277,10 @@ function AdminReviewDetailPageInner() {
|
|||||||
|
|
||||||
setProduct(updated);
|
setProduct(updated);
|
||||||
|
|
||||||
const shouldCompare = idChange?.isUpdate === true && Boolean(idChange.oldValue) && Boolean(idChange.newValue);
|
const isUpdate = isProductUpdateFromCompare(idChange);
|
||||||
|
setIsUpdateProduct(isUpdate);
|
||||||
|
|
||||||
|
const shouldCompare = isUpdate && Boolean(idChange?.oldValue) && Boolean(idChange?.newValue);
|
||||||
setIsComparison(shouldCompare);
|
setIsComparison(shouldCompare);
|
||||||
|
|
||||||
if (shouldCompare) {
|
if (shouldCompare) {
|
||||||
@ -272,6 +298,14 @@ function AdminReviewDetailPageInner() {
|
|||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
}, [params.productId]);
|
}, [params.productId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (redirectTimeoutRef.current) {
|
||||||
|
clearTimeout(redirectTimeoutRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
async function submitReview(action: "accept" | "reject", reason?: string) {
|
async function submitReview(action: "accept" | "reject", reason?: string) {
|
||||||
setActing(true);
|
setActing(true);
|
||||||
setActionError("");
|
setActionError("");
|
||||||
@ -279,7 +313,7 @@ function AdminReviewDetailPageInner() {
|
|||||||
const res = await fetch(`/api/admin/review/${params.productId}`, {
|
const res = await fetch(`/api/admin/review/${params.productId}`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json", "x-auth-token": getToken() },
|
headers: { "Content-Type": "application/json", "x-auth-token": getToken() },
|
||||||
body: JSON.stringify({ action, isNew: product?.isNew ?? true, reason }),
|
body: JSON.stringify({ action, isUpdate: isUpdateProduct, reason }),
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
@ -287,7 +321,12 @@ function AdminReviewDetailPageInner() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setActionSuccess(action === "accept" ? "Update produk berhasil disetujui!" : "Update produk berhasil ditolak!");
|
setActionSuccess(action === "accept" ? "Update produk berhasil disetujui!" : "Update produk berhasil ditolak!");
|
||||||
setTimeout(() => router.push("/admin/review"), 1800);
|
if (redirectTimeoutRef.current) {
|
||||||
|
clearTimeout(redirectTimeoutRef.current);
|
||||||
|
}
|
||||||
|
redirectTimeoutRef.current = setTimeout(() => {
|
||||||
|
router.push("/admin/review");
|
||||||
|
}, 1800);
|
||||||
} catch {
|
} catch {
|
||||||
setActionError("Gagal terhubung ke server");
|
setActionError("Gagal terhubung ke server");
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export async function GET(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// action: "accept" | "reject"
|
// action: "accept" | "reject"
|
||||||
// isNew: boolean — determines which backend endpoint to call
|
// isUpdate: boolean — true for product update review, false for new product review
|
||||||
// body for reject: { reason: string }
|
// body for reject: { reason: string }
|
||||||
export async function POST(
|
export async function POST(
|
||||||
req: NextRequest,
|
req: NextRequest,
|
||||||
@ -25,23 +25,23 @@ export async function POST(
|
|||||||
) {
|
) {
|
||||||
const token = req.headers.get("x-auth-token") || "";
|
const token = req.headers.get("x-auth-token") || "";
|
||||||
const { productId } = await context.params;
|
const { productId } = await context.params;
|
||||||
const { action, isNew, reason } = await req.json();
|
const { action, isUpdate, reason } = await req.json();
|
||||||
|
|
||||||
let url: string;
|
let url: string;
|
||||||
let method = "POST";
|
let method = "POST";
|
||||||
let body: Record<string, string> | undefined;
|
let body: Record<string, string> | undefined;
|
||||||
|
|
||||||
if (action === "accept") {
|
if (action === "accept") {
|
||||||
// isNew=true: POST /product/accept/{id}
|
// new product review: POST /product/accept/{id}
|
||||||
// isNew=false: PUT /product/accept/{id}
|
// product update review: PUT /product/accept/{id}
|
||||||
url = `${API_URL}/api/v1.0/product/accept/${productId}`;
|
url = `${API_URL}/api/v1.0/product/accept/${productId}`;
|
||||||
method = isNew ? "POST" : "PUT";
|
method = isUpdate ? "PUT" : "POST";
|
||||||
body = { state: "PUBLISHED" };
|
body = { state: "PUBLISHED" };
|
||||||
} else {
|
} else {
|
||||||
// isNew=true: POST /product/reject/{id}
|
// new product review: POST /product/reject/{id}
|
||||||
// isNew=false: PUT /product/reject/{id}
|
// product update review: PUT /product/reject/{id}
|
||||||
url = `${API_URL}/api/v1.0/product/reject/${productId}`;
|
url = `${API_URL}/api/v1.0/product/reject/${productId}`;
|
||||||
method = isNew ? "POST" : "PUT";
|
method = isUpdate ? "PUT" : "POST";
|
||||||
body = reason ? { reason, state: "REJECTED" } : { state: "REJECTED" };
|
body = reason ? { reason, state: "REJECTED" } : { state: "REJECTED" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user