Adjust product state actions and icon font loading
This commit is contained in:
@ -30,6 +30,8 @@ interface ProductRow {
|
||||
totalStock: number;
|
||||
}
|
||||
|
||||
type ProductState = "UNPUBLISHED" | "DELETED_BY_SELLER" | "DELETED_BY_ADMIN" | string;
|
||||
|
||||
function getToken() {
|
||||
if (typeof window === "undefined") {
|
||||
return "";
|
||||
@ -184,6 +186,8 @@ function ProductsPageInner() {
|
||||
const [unpublishTarget, setUnpublishTarget] = useState<ProductRow | null>(null);
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
const [unpublishing, setUnpublishing] = useState(false);
|
||||
const [publishingId, setPublishingId] = useState<string | null>(null);
|
||||
const [restoringId, setRestoringId] = useState<string | null>(null);
|
||||
|
||||
// Reset to page 1 when tab changes
|
||||
useEffect(() => {
|
||||
@ -263,6 +267,7 @@ function ProductsPageInner() {
|
||||
}
|
||||
|
||||
async function handleRestore(productId: string) {
|
||||
setRestoringId(productId);
|
||||
try {
|
||||
const res = await fetch(`/api/products/${productId}?action=restore`, {
|
||||
method: "PUT",
|
||||
@ -277,9 +282,37 @@ function ProductsPageInner() {
|
||||
window.location.reload();
|
||||
} catch (err) {
|
||||
alert(err instanceof Error ? err.message : p.restoreError);
|
||||
} finally {
|
||||
setRestoringId(null);
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePublish(productId: string) {
|
||||
setPublishingId(productId);
|
||||
try {
|
||||
const res = await fetch(`/api/products/${productId}?action=publish`, {
|
||||
method: "PUT",
|
||||
headers: { "x-auth-token": getToken() },
|
||||
});
|
||||
const result = await res.json().catch(() => ({}));
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(result?.responseDesc || p.publishError);
|
||||
}
|
||||
|
||||
window.location.reload();
|
||||
} catch (err) {
|
||||
alert(err instanceof Error ? err.message : p.publishError);
|
||||
}
|
||||
finally {
|
||||
setPublishingId(null);
|
||||
}
|
||||
}
|
||||
|
||||
function getProductState(product: ProductRow): ProductState {
|
||||
return (product.state || product.status || product.reviewStatus || "").toUpperCase();
|
||||
}
|
||||
|
||||
const internationalCount = rows.filter(
|
||||
(row) => row.market === "International"
|
||||
).length;
|
||||
@ -411,6 +444,12 @@ function ProductsPageInner() {
|
||||
</tr>
|
||||
) : (
|
||||
rows.map((product) => {
|
||||
const productState = getProductState(product);
|
||||
const isInactiveInAllTab =
|
||||
activeTab === "All Product" &&
|
||||
(productState === "UNPUBLISHED" ||
|
||||
productState === "DELETED_BY_SELLER" ||
|
||||
productState === "DELETED_BY_ADMIN");
|
||||
const stockTone =
|
||||
product.totalStock === 0
|
||||
? "red"
|
||||
@ -441,7 +480,7 @@ function ProductsPageInner() {
|
||||
fill
|
||||
sizes="44px"
|
||||
className={`object-cover ${
|
||||
stockTone === "red" ? "grayscale" : ""
|
||||
stockTone === "red" || isInactiveInAllTab ? "grayscale" : ""
|
||||
}`}
|
||||
/>
|
||||
) : (
|
||||
@ -453,7 +492,7 @@ function ProductsPageInner() {
|
||||
<div>
|
||||
<p
|
||||
className={`text-xs font-bold transition-colors group-hover:text-primary ${
|
||||
stockTone === "red"
|
||||
stockTone === "red" || isInactiveInAllTab
|
||||
? "text-outline line-through"
|
||||
: "text-on-surface"
|
||||
}`}
|
||||
@ -469,7 +508,7 @@ function ProductsPageInner() {
|
||||
<td className="px-6 py-4 text-center">
|
||||
<span
|
||||
className={`text-xs font-bold ${
|
||||
stockTone === "red"
|
||||
stockTone === "red" || isInactiveInAllTab
|
||||
? "text-outline"
|
||||
: "text-on-surface"
|
||||
}`}
|
||||
@ -503,39 +542,64 @@ function ProductsPageInner() {
|
||||
<span
|
||||
className={`inline-flex items-center rounded-full px-2 py-0.5 text-[9px] font-black uppercase tracking-tight ${marketClasses(
|
||||
product.market
|
||||
)}`}
|
||||
)} ${isInactiveInAllTab ? "opacity-60 line-through" : ""}`}
|
||||
>
|
||||
{product.market}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-6 py-4 text-center">
|
||||
<div className="flex items-center justify-center gap-3">
|
||||
{!isInReviewTab ? (
|
||||
!isDeletedTab ? (
|
||||
<Link
|
||||
href={`/products/${product.id}/edit${activeTab === "Draft" ? "?draft=1" : ""}`}
|
||||
className="rounded-lg bg-primary px-3 py-1 text-[10px] font-bold text-white transition-colors hover:bg-primary/90"
|
||||
>
|
||||
{p.edit}
|
||||
</Link>
|
||||
) : null
|
||||
) : null}
|
||||
<Link
|
||||
href={`/products/${product.id}/detail${activeTab === "Draft" ? "?draft=1" : isInReviewTab ? "?review=1" : ""}`}
|
||||
className="text-[10px] font-bold text-primary transition-colors hover:underline"
|
||||
>
|
||||
{p.detail}
|
||||
</Link>
|
||||
{isDeletedTab ? (
|
||||
productState === "DELETED_BY_ADMIN" ? (
|
||||
<span className="rounded-full bg-error-container px-3 py-1 text-[10px] font-bold text-on-error-container">
|
||||
{p.deletedByAdmin}
|
||||
</span>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleRestore(product.id)}
|
||||
disabled={restoringId === product.id}
|
||||
className="rounded-lg bg-tertiary px-3 py-1 text-[10px] font-bold text-white transition-colors hover:bg-tertiary/90 disabled:opacity-60"
|
||||
>
|
||||
{restoringId === product.id ? p.publishing : p.restore}
|
||||
</button>
|
||||
)
|
||||
) : productState === "UNPUBLISHED" ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handlePublish(product.id)}
|
||||
disabled={publishingId === product.id}
|
||||
className="rounded-lg bg-tertiary px-3 py-1 text-[10px] font-bold text-white transition-colors hover:bg-tertiary/90 disabled:opacity-60"
|
||||
>
|
||||
{publishingId === product.id ? p.publishing : p.publish}
|
||||
</button>
|
||||
) : productState === "DELETED_BY_SELLER" ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleRestore(product.id)}
|
||||
className="rounded-lg bg-tertiary px-3 py-1 text-[10px] font-bold text-white transition-colors hover:bg-tertiary/90"
|
||||
disabled={restoringId === product.id}
|
||||
className="rounded-lg bg-tertiary px-3 py-1 text-[10px] font-bold text-white transition-colors hover:bg-tertiary/90 disabled:opacity-60"
|
||||
>
|
||||
{p.restore}
|
||||
{restoringId === product.id ? p.publishing : p.restore}
|
||||
</button>
|
||||
) : (
|
||||
<>
|
||||
{!isInReviewTab ? (
|
||||
!isDeletedTab ? (
|
||||
<Link
|
||||
href={`/products/${product.id}/edit${activeTab === "Draft" ? "?draft=1" : ""}`}
|
||||
className="rounded-lg bg-primary px-3 py-1 text-[10px] font-bold text-white transition-colors hover:bg-primary/90"
|
||||
>
|
||||
{p.edit}
|
||||
</Link>
|
||||
) : null
|
||||
) : null}
|
||||
<Link
|
||||
href={`/products/${product.id}/detail${activeTab === "Draft" ? "?draft=1" : isInReviewTab ? "?review=1" : ""}`}
|
||||
className="text-[10px] font-bold text-primary transition-colors hover:underline"
|
||||
>
|
||||
{p.detail}
|
||||
</Link>
|
||||
{canUnpublish ? (
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user