update table agent,banner,promotion,galery,product and approve flow
This commit is contained in:
parent
5579ad8c20
commit
c2c08a1c4e
|
|
@ -8,14 +8,39 @@ import {
|
||||||
DialogFooter,
|
DialogFooter,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { CheckCircle } from "lucide-react";
|
import { Check, CheckCheck, CheckCircle, Clock, X } from "lucide-react";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { getGaleryFileData } from "@/service/galery";
|
import { approveGalery, getGaleryFileData } from "@/service/galery";
|
||||||
|
import { convertDateFormat } from "@/utils/global";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
import { error, loading, success } from "@/config/swal";
|
||||||
|
|
||||||
export function DialogDetailGaleri({ open, onClose, data }: any) {
|
export function DialogDetailGaleri({ open, onClose, data }: any) {
|
||||||
const [images, setImages] = useState<any[]>([]);
|
const [images, setImages] = useState<any[]>([]);
|
||||||
const [openApproverHistory, setOpenApproverHistory] = useState(false);
|
const [openApproverHistory, setOpenApproverHistory] = useState(false);
|
||||||
|
const [userLevelId, setUserLevelId] = useState<string | null>(null);
|
||||||
|
const [openViewDialog, setOpenViewDialog] = useState(false);
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 🔹 Ambil userlevelId dari cookies
|
||||||
|
useEffect(() => {
|
||||||
|
const ulne = Cookies.get("ulne"); // contoh: "3"
|
||||||
|
setUserLevelId(ulne ?? null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const [openCommentModal, setOpenCommentModal] = useState(false);
|
||||||
|
const [commentValue, setCommentValue] = useState("");
|
||||||
|
|
||||||
|
const handleSubmitComment = async () => {
|
||||||
|
// await api.post("/banner/comment", {
|
||||||
|
// bannerId: viewBanner.id,
|
||||||
|
// comment: commentValue,
|
||||||
|
// });
|
||||||
|
|
||||||
|
setOpenCommentModal(false);
|
||||||
|
};
|
||||||
const fetchImages = async () => {
|
const fetchImages = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await getGaleryFileData(data.id);
|
const res = await getGaleryFileData(data.id);
|
||||||
|
|
@ -44,6 +69,21 @@ export function DialogDetailGaleri({ open, onClose, data }: any) {
|
||||||
setOpenApproverHistory(true);
|
setOpenApproverHistory(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleApproveGalery = async (id: number) => {
|
||||||
|
loading();
|
||||||
|
const res = await approveGalery(id);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
error(res.message || "Gagal menyetujui galeri");
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
close();
|
||||||
|
success("Galeri berhasil disetujui");
|
||||||
|
fetchImages(); // refresh table
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Dialog open={open} onOpenChange={onClose}>
|
<Dialog open={open} onOpenChange={onClose}>
|
||||||
|
|
@ -107,43 +147,59 @@ export function DialogDetailGaleri({ open, onClose, data }: any) {
|
||||||
|
|
||||||
{/* Timeline */}
|
{/* Timeline */}
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium text-sm text-gray-700 mb-2">
|
<h4 className="text-sm font-semibold text-gray-700 mb-3">
|
||||||
Status Timeline
|
Status Timeline
|
||||||
</p>
|
</h4>
|
||||||
|
|
||||||
<div className="flex flex-col gap-3">
|
<div className="space-y-4">
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex gap-3">
|
||||||
<CheckCircle className="text-green-600" />
|
<div className="w-6 h-6 rounded-full bg-green-100 flex items-center justify-center">
|
||||||
|
<Check className="w-4 h-4 text-green-600" />
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="font-semibold">Diupload Oleh :</p>
|
<p className="font-medium text-gray-800">
|
||||||
<p className="text-gray-500 text-sm">
|
Diupload oleh Operator
|
||||||
{new Date(data.created_at).toLocaleString("id-ID")}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
<p className="text-sm text-gray-500">
|
||||||
</div>
|
{convertDateFormat(data?.created_at)} WIB
|
||||||
<div className="flex items-start gap-3">
|
|
||||||
<CheckCircle className="text-green-600" />
|
|
||||||
<div>
|
|
||||||
<p className="font-semibold">Disetujui Oleh :</p>
|
|
||||||
<p className="text-gray-500 text-sm">
|
|
||||||
{new Date(data.created_at).toLocaleString("id-ID")}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{data.approved_at && (
|
<div className="flex gap-3">
|
||||||
<div className="flex items-start gap-3">
|
<div
|
||||||
<CheckCircle className="text-green-600" />
|
className={`w-6 h-6 rounded-full flex items-center justify-center ${
|
||||||
<div>
|
data?.status_id === 1
|
||||||
<p className="font-semibold">Disetujui oleh Approver</p>
|
? "bg-yellow-100"
|
||||||
<p className="text-gray-500 text-sm">
|
: data?.status_id === 2
|
||||||
{new Date(data.approved_at).toLocaleString("id-ID")}
|
? "bg-green-100"
|
||||||
</p>
|
: "bg-red-100"
|
||||||
</div>
|
}`}
|
||||||
</div>
|
>
|
||||||
|
{data?.status_id === 1 ? (
|
||||||
|
<Clock className="w-4 h-4 text-yellow-700" />
|
||||||
|
) : data?.status_id === 2 ? (
|
||||||
|
<Check className="w-4 h-4 text-green-600" />
|
||||||
|
) : (
|
||||||
|
<X className="w-4 h-4 text-red-700" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p className="font-medium text-gray-800">
|
||||||
|
{data?.status_id === 1
|
||||||
|
? "Menunggu disetujui oleh Approver"
|
||||||
|
: data?.status_id === 2
|
||||||
|
? "Disetujui oleh Approver"
|
||||||
|
: "Ditolak oleh Approver"}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
{convertDateFormat(data?.updated_at)} WIB
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="border rounded-lg px-3 py-3">
|
<div className="border rounded-lg px-3 py-3">
|
||||||
<p>Comment : </p>
|
<p>Comment : </p>
|
||||||
<div className="flex flex-row justify-between">
|
<div className="flex flex-row justify-between">
|
||||||
|
|
@ -157,6 +213,63 @@ export function DialogDetailGaleri({ open, onClose, data }: any) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{openViewDialog && userLevelId !== "2" && (
|
||||||
|
<div className="flex justify-between items-center gap-3 px-6 py-4 border-t bg-[#F2F7FA]">
|
||||||
|
{data.status_id === 1 ? (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
className="bg-blue-200 hover:bg-blue-400"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setOpenCommentModal(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Beri Tanggapan
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className=" w-[180]"
|
||||||
|
variant="destructive"
|
||||||
|
// onClick={(e) => {
|
||||||
|
// e.stopPropagation();
|
||||||
|
// handleReject();
|
||||||
|
// }}
|
||||||
|
>
|
||||||
|
Reject
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{userLevelId === "1" && (
|
||||||
|
<Button
|
||||||
|
// variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="bg-green-600 hover:bg-green-700 text-white w-[180]"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleApproveGalery(data.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
className="mx-auto"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setOpenViewDialog(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Tutup
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* <DialogFooter className="px-6 pb-6">
|
{/* <DialogFooter className="px-6 pb-6">
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,20 @@ import {
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { CheckCircle2, FileText } from "lucide-react";
|
import {
|
||||||
import { getPromotionById } from "@/service/promotion";
|
Check,
|
||||||
|
CheckCheck,
|
||||||
|
CheckCircle2,
|
||||||
|
Clock,
|
||||||
|
FileText,
|
||||||
|
X,
|
||||||
|
} from "lucide-react";
|
||||||
|
import { approvePromotion, getPromotionById } from "@/service/promotion";
|
||||||
|
import { convertDateFormat } from "@/utils/global";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
import { error, loading, success } from "@/config/swal";
|
||||||
|
|
||||||
type PromoDetailDialogProps = {
|
type PromoDetailDialogProps = {
|
||||||
promoId: number | null;
|
promoId: number | null;
|
||||||
|
|
@ -21,10 +33,20 @@ export default function PromoDetailDialog({
|
||||||
open,
|
open,
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
}: PromoDetailDialogProps) {
|
}: PromoDetailDialogProps) {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loadingData, setLoadingData] = useState(false);
|
||||||
const [promo, setPromo] = useState<any>(null);
|
const [promo, setPromo] = useState<any>(null);
|
||||||
const [openApproverHistory, setOpenApproverHistory] = useState(false);
|
const [openApproverHistory, setOpenApproverHistory] = useState(false);
|
||||||
|
|
||||||
|
const [userLevelId, setUserLevelId] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 🔹 Ambil userlevelId dari cookies
|
||||||
|
useEffect(() => {
|
||||||
|
const ulne = Cookies.get("ulne"); // contoh: "3"
|
||||||
|
setUserLevelId(ulne ?? null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
// FORMAT TANGGAL → DD-MM-YYYY
|
// FORMAT TANGGAL → DD-MM-YYYY
|
||||||
const formatDate = (dateStr: string) => {
|
const formatDate = (dateStr: string) => {
|
||||||
const d = new Date(dateStr);
|
const d = new Date(dateStr);
|
||||||
|
|
@ -37,17 +59,37 @@ export default function PromoDetailDialog({
|
||||||
const handleOpenApproverHistory = () => {
|
const handleOpenApproverHistory = () => {
|
||||||
setOpenApproverHistory(true);
|
setOpenApproverHistory(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleApprovePromotion = async (promoId: number) => {
|
||||||
|
loading();
|
||||||
|
const res = await approvePromotion(promoId);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
error(res.message || "Gagal menyetujui promotion");
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
close();
|
||||||
|
success("Promotion berhasil disetujui");
|
||||||
|
// fetchData(); // refresh table
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!promoId || !open) return;
|
if (!promoId || !open) return;
|
||||||
|
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoadingData(true);
|
||||||
const res = await getPromotionById(promoId);
|
const res = await getPromotionById(promoId);
|
||||||
|
|
||||||
// Mapping ke format dialog
|
// Mapping ke format dialog
|
||||||
const mapped = {
|
const mapped = {
|
||||||
|
id: res?.data?.data?.id,
|
||||||
title: res?.data?.data?.title,
|
title: res?.data?.data?.title,
|
||||||
|
status_id: res?.data?.data?.status_id,
|
||||||
|
created_at: res?.data?.data?.created_at,
|
||||||
|
updated_at: res?.data?.data?.updated_at,
|
||||||
fileSize: "Tidak diketahui",
|
fileSize: "Tidak diketahui",
|
||||||
uploadDate: formatDate(res?.data?.data?.created_at),
|
uploadDate: formatDate(res?.data?.data?.created_at),
|
||||||
status: res?.data?.data?.is_active ? "Aktif" : "Nonaktif",
|
status: res?.data?.data?.is_active ? "Aktif" : "Nonaktif",
|
||||||
|
|
@ -75,19 +117,32 @@ export default function PromoDetailDialog({
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("ERROR FETCH PROMO:", err);
|
console.error("ERROR FETCH PROMO:", err);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoadingData(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchData();
|
fetchData();
|
||||||
}, [promoId, open]);
|
}, [promoId, open]);
|
||||||
|
|
||||||
|
const [openCommentModal, setOpenCommentModal] = useState(false);
|
||||||
|
const [commentValue, setCommentValue] = useState("");
|
||||||
|
const [openViewDialog, setOpenViewDialog] = useState(false);
|
||||||
|
|
||||||
if (!open) return null;
|
if (!open) return null;
|
||||||
|
|
||||||
|
const handleSubmitComment = async () => {
|
||||||
|
// await api.post("/banner/comment", {
|
||||||
|
// bannerId: promo.id,
|
||||||
|
// comment: commentValue,
|
||||||
|
// });
|
||||||
|
|
||||||
|
setOpenCommentModal(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
<DialogContent className="p-0 max-w-xl overflow-hidden rounded-2xl">
|
<DialogContent className="p-0 max-w-lg overflow-hidden">
|
||||||
{/* HEADER */}
|
{/* HEADER */}
|
||||||
<div className="bg-gradient-to-r from-[#0f6c75] to-[#145f66] text-white px-6 py-5 relative">
|
<div className="bg-gradient-to-r from-[#0f6c75] to-[#145f66] text-white px-6 py-5 relative">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
|
|
@ -107,7 +162,7 @@ export default function PromoDetailDialog({
|
||||||
|
|
||||||
{/* BODY */}
|
{/* BODY */}
|
||||||
<div className="p-6">
|
<div className="p-6">
|
||||||
{loading ? (
|
{loadingData ? (
|
||||||
<p className="text-Start text-gray-600">Memuat data...</p>
|
<p className="text-Start text-gray-600">Memuat data...</p>
|
||||||
) : promo ? (
|
) : promo ? (
|
||||||
<>
|
<>
|
||||||
|
|
@ -133,28 +188,61 @@ export default function PromoDetailDialog({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* TIMELINE */}
|
{/* TIMELINE */}
|
||||||
<div className="mt-4">
|
<div>
|
||||||
<p className="text-gray-600 mb-3 font-medium">
|
<h4 className="text-sm font-semibold text-gray-700 mb-3">
|
||||||
Status Timeline
|
Status Timeline
|
||||||
</p>
|
</h4>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{promo.timeline.map((item: any, idx: number) => (
|
<div className="flex gap-3">
|
||||||
<div key={idx} className="flex gap-3 items-start">
|
<div className="w-6 h-6 rounded-full bg-green-100 flex items-center justify-center">
|
||||||
<CheckCircle2
|
<Check className="w-4 h-4 text-green-600" />
|
||||||
size={20}
|
</div>
|
||||||
className="text-green-600 shrink-0"
|
|
||||||
/>
|
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium">{item.label}</p>
|
<p className="font-medium text-gray-800">
|
||||||
<p className="text-gray-600 text-sm">
|
Diupload oleh Operator
|
||||||
{item.date} • {item.time} WIB
|
</p>
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
{convertDateFormat(promo?.created_at)} WIB
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
|
||||||
|
<div className="flex gap-3">
|
||||||
|
<div
|
||||||
|
className={`w-6 h-6 rounded-full flex items-center justify-center ${
|
||||||
|
promo?.status_id === 1
|
||||||
|
? "bg-yellow-100"
|
||||||
|
: promo?.status_id === 2
|
||||||
|
? "bg-green-100"
|
||||||
|
: "bg-red-100"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{promo?.status_id === 1 ? (
|
||||||
|
<Clock className="w-4 h-4 text-yellow-700" />
|
||||||
|
) : promo?.status_id === 2 ? (
|
||||||
|
<Check className="w-4 h-4 text-green-600" />
|
||||||
|
) : (
|
||||||
|
<X className="w-4 h-4 text-red-700" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="border rounded-lg px-3 py-3 mt-3">
|
|
||||||
|
<div>
|
||||||
|
<p className="font-medium text-gray-800">
|
||||||
|
{promo?.status_id === 1
|
||||||
|
? "Menunggu disetujui oleh Approver"
|
||||||
|
: promo?.status_id === 2
|
||||||
|
? "Disetujui oleh Approver"
|
||||||
|
: "Ditolak oleh Approver"}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
{convertDateFormat(promo?.updated_at)} WIB
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="border rounded-lg px-3 py-3">
|
||||||
<p>Comment : </p>
|
<p>Comment : </p>
|
||||||
<div className="flex flex-row justify-between">
|
<div className="flex flex-row justify-between">
|
||||||
<button
|
<button
|
||||||
|
|
@ -168,11 +256,67 @@ export default function PromoDetailDialog({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<p className="text-center text-gray-600">Data tidak ditemukan</p>
|
<p className="text-center text-gray-600">Data tidak ditemukan</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{userLevelId !== "2" && promo && (
|
||||||
|
<div className="flex justify-between items-center gap-3 px-6 py-4 border-t bg-[#F2F7FA]">
|
||||||
|
{promo.status_id === 1 ? (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
className="bg-blue-200 hover:bg-blue-400"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setOpenCommentModal(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Beri Tanggapan
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className=" w-[150]"
|
||||||
|
variant="destructive"
|
||||||
|
// onClick={(e) => {
|
||||||
|
// e.stopPropagation();
|
||||||
|
// handleReject();
|
||||||
|
// }}
|
||||||
|
>
|
||||||
|
Reject
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{userLevelId === "1" && (
|
||||||
|
<Button
|
||||||
|
// variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="bg-green-600 hover:bg-green-700 text-white w-[150]"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleApprovePromotion(promo.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
className="mx-auto"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setOpenViewDialog(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Tutup
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{openApproverHistory && (
|
{openApproverHistory && (
|
||||||
<div
|
<div
|
||||||
className="fixed inset-0 z-[60] flex items-center justify-center bg-black/50 p-4"
|
className="fixed inset-0 z-[60] flex items-center justify-center bg-black/50 p-4"
|
||||||
|
|
@ -271,7 +415,7 @@ export default function PromoDetailDialog({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* FOOTER */}
|
{/* FOOTER
|
||||||
<div className="bg-[#E3EFF4] text-center py-3">
|
<div className="bg-[#E3EFF4] text-center py-3">
|
||||||
<button
|
<button
|
||||||
onClick={() => onOpenChange(false)}
|
onClick={() => onOpenChange(false)}
|
||||||
|
|
@ -279,7 +423,7 @@ export default function PromoDetailDialog({
|
||||||
>
|
>
|
||||||
Tutup
|
Tutup
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div> */}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
{openApproverHistory && (
|
{openApproverHistory && (
|
||||||
|
|
@ -380,6 +524,76 @@ export default function PromoDetailDialog({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{openCommentModal && promo && (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 z-[60] flex items-center justify-center bg-black/50 p-4"
|
||||||
|
onClick={() => setOpenCommentModal(false)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="bg-white rounded-2xl shadow-2xl max-w-lg w-full overflow-hidden"
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{/* HEADER */}
|
||||||
|
<div className="bg-gradient-to-br from-[#1F6779] to-[#0F6C75] text-white px-6 py-5 relative">
|
||||||
|
<button
|
||||||
|
onClick={() => setOpenCommentModal(false)}
|
||||||
|
className="absolute top-4 right-4 text-white/80 hover:text-white text-xl"
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<h2 className="text-lg font-semibold">Beri Tanggapan</h2>
|
||||||
|
|
||||||
|
{/* Badge */}
|
||||||
|
<div className="flex items-center gap-2 mt-3">
|
||||||
|
<span className="bg-yellow-100 text-yellow-800 text-xs font-medium px-3 py-1 rounded-full">
|
||||||
|
Menunggu
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span className="bg-white text-[#0F6C75] text-xs font-medium px-3 py-1 rounded-full">
|
||||||
|
Banner
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span className="bg-white/20 text-white text-xs px-2 py-[2px] rounded-full">
|
||||||
|
{promo.position}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* BODY */}
|
||||||
|
<div className="p-6 space-y-4">
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-500 mb-2">
|
||||||
|
Comment
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
value={commentValue}
|
||||||
|
onChange={(e) => setCommentValue(e.target.value)}
|
||||||
|
placeholder="Masukkan komentar"
|
||||||
|
className="w-full min-h-[100px] border rounded-lg p-3 focus:outline-none focus:ring-2 focus:ring-[#0F6C75]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* FOOTER */}
|
||||||
|
<div className="flex justify-between gap-3 px-6 py-4 border-t bg-[#F2F7FA]">
|
||||||
|
<button
|
||||||
|
onClick={() => setOpenCommentModal(false)}
|
||||||
|
className="flex-1 py-2 rounded-xl bg-blue-100 hover:bg-blue-200 text-gray-700 font-medium"
|
||||||
|
>
|
||||||
|
Batal
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={handleSubmitComment}
|
||||||
|
className="flex-1 py-2 rounded-xl bg-[#1F6779] hover:bg-[#0F6C75] text-white font-medium"
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,15 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Upload, Plus, Settings, CheckCheck } from "lucide-react";
|
import {
|
||||||
|
Upload,
|
||||||
|
Plus,
|
||||||
|
Settings,
|
||||||
|
CheckCheck,
|
||||||
|
Check,
|
||||||
|
Clock,
|
||||||
|
X,
|
||||||
|
} from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
|
|
@ -14,17 +22,18 @@ import {
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { loading } from "@/config/swal";
|
import { error, loading, success } from "@/config/swal";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useDropzone } from "react-dropzone";
|
import { useDropzone } from "react-dropzone";
|
||||||
import z from "zod";
|
import z from "zod";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { getProductDataById } from "@/service/product";
|
import { getProductDataById } from "@/service/product";
|
||||||
import { getAgentById } from "@/service/agent";
|
import { approveAgent, getAgentById, updateAgent } from "@/service/agent";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { convertDateFormat } from "@/utils/global";
|
||||||
|
|
||||||
const ViewEditor = dynamic(
|
const ViewEditor = dynamic(
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -85,7 +94,25 @@ export default function DetailAgentForm(props: { isDetail: boolean }) {
|
||||||
const id = params?.id;
|
const id = params?.id;
|
||||||
const [data, setData] = useState<any>(null);
|
const [data, setData] = useState<any>(null);
|
||||||
const [openApproverHistory, setOpenApproverHistory] = useState(false);
|
const [openApproverHistory, setOpenApproverHistory] = useState(false);
|
||||||
|
const [userLevelId, setUserLevelId] = useState<string | null>(null);
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const [openCommentModal, setOpenCommentModal] = useState(false);
|
||||||
|
const [commentValue, setCommentValue] = useState("");
|
||||||
|
const handleSubmitComment = async () => {
|
||||||
|
// await api.post("/banner/comment", {
|
||||||
|
// bannerId: viewBanner.id,
|
||||||
|
// comment: commentValue,
|
||||||
|
// });
|
||||||
|
|
||||||
|
setOpenCommentModal(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 🔹 Ambil userlevelId dari cookies
|
||||||
|
useEffect(() => {
|
||||||
|
const ulne = Cookies.get("ulne"); // contoh: "3"
|
||||||
|
setUserLevelId(ulne ?? null);
|
||||||
|
}, []);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -101,6 +128,41 @@ export default function DetailAgentForm(props: { isDetail: boolean }) {
|
||||||
setOpenApproverHistory(true);
|
setOpenApproverHistory(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// const handleRejectProduct = async (id: number) => {
|
||||||
|
// loading();
|
||||||
|
|
||||||
|
// const payload = {
|
||||||
|
// status_id: 3, // ✅ number
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const res = await updateAgent(payload, id);
|
||||||
|
|
||||||
|
// if (res?.error) {
|
||||||
|
// error(res.message || "Gagal menolak product");
|
||||||
|
// close();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// close();
|
||||||
|
// success("Product berhasil ditolak");
|
||||||
|
// fetchData();
|
||||||
|
// };
|
||||||
|
|
||||||
|
const handleApproveAgent = async (id: number) => {
|
||||||
|
loading();
|
||||||
|
const res = await approveAgent(id);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
error(res.message || "Gagal menyetujui agent");
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
close();
|
||||||
|
success("Agent berhasil disetujui");
|
||||||
|
fetchData(); // refresh table
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card className="w-full border-none shadow-md">
|
<Card className="w-full border-none shadow-md">
|
||||||
|
|
@ -155,6 +217,60 @@ export default function DetailAgentForm(props: { isDetail: boolean }) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="text-sm font-semibold text-gray-700 mb-3">
|
||||||
|
Status Timeline
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="flex gap-3">
|
||||||
|
<div className="w-6 h-6 rounded-full bg-green-100 flex items-center justify-center">
|
||||||
|
<Check className="w-4 h-4 text-green-600" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="font-medium text-gray-800">
|
||||||
|
Diupload oleh Operator
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
{convertDateFormat(data.created_at)} WIB
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-3">
|
||||||
|
<div
|
||||||
|
className={`w-6 h-6 rounded-full flex items-center justify-center ${
|
||||||
|
data?.status_id === 1
|
||||||
|
? "bg-yellow-100"
|
||||||
|
: data?.status_id === 2
|
||||||
|
? "bg-green-100"
|
||||||
|
: "bg-red-100"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{data?.status_id === 1 ? (
|
||||||
|
<Clock className="w-4 h-4 text-yellow-700" />
|
||||||
|
) : data?.status_id === 2 ? (
|
||||||
|
<Check className="w-4 h-4 text-green-600" />
|
||||||
|
) : (
|
||||||
|
<X className="w-4 h-4 text-red-700" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p className="font-medium text-gray-800">
|
||||||
|
{data?.status_id === 1
|
||||||
|
? "Menunggu disetujui oleh Approver"
|
||||||
|
: data?.status_id === 2
|
||||||
|
? "Disetujui oleh Approver"
|
||||||
|
: "Ditolak oleh Approver"}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
{convertDateFormat(data?.updated_at)} WIB
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="border rounded-lg px-3 py-3">
|
<div className="border rounded-lg px-3 py-3">
|
||||||
<p>Comment : </p>
|
<p>Comment : </p>
|
||||||
<div className="flex flex-row justify-between">
|
<div className="flex flex-row justify-between">
|
||||||
|
|
@ -167,6 +283,47 @@ export default function DetailAgentForm(props: { isDetail: boolean }) {
|
||||||
<p>Jaecoo - Approver | 10/11/2026</p>
|
<p>Jaecoo - Approver | 10/11/2026</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{userLevelId !== "2" && data && (
|
||||||
|
<div className="flex justify-between items-center gap-3 px-6 py-4 border-t bg-[#F2F7FA] mt-10">
|
||||||
|
{data.status_id === 1 ? (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
className="bg-blue-200 hover:bg-blue-400"
|
||||||
|
onClick={() => setOpenCommentModal(true)}
|
||||||
|
>
|
||||||
|
Beri Tanggapan
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="destructive"
|
||||||
|
className="w-[180px]"
|
||||||
|
// onClick={() => handleRejectProduct(detailData.id)}
|
||||||
|
>
|
||||||
|
Reject
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{userLevelId === "1" && (
|
||||||
|
<Button
|
||||||
|
className="bg-green-600 hover:bg-green-700 text-white w-[180px]"
|
||||||
|
onClick={() => handleApproveAgent(data.id)}
|
||||||
|
>
|
||||||
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
className="mx-auto"
|
||||||
|
onClick={() => router.back()}
|
||||||
|
>
|
||||||
|
Tutup
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{/* <Button className=" bg-teal-800 hover:bg-teal-900 text-white py-3">
|
{/* <Button className=" bg-teal-800 hover:bg-teal-900 text-white py-3">
|
||||||
Submit
|
Submit
|
||||||
</Button> */}
|
</Button> */}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,15 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Upload, Plus, Settings, CheckCheck } from "lucide-react";
|
import {
|
||||||
|
Upload,
|
||||||
|
Plus,
|
||||||
|
Settings,
|
||||||
|
CheckCheck,
|
||||||
|
Clock,
|
||||||
|
Check,
|
||||||
|
X,
|
||||||
|
} from "lucide-react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
|
|
@ -14,15 +22,20 @@ import {
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { loading } from "@/config/swal";
|
import { error, loading, success } from "@/config/swal";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { useDropzone } from "react-dropzone";
|
import { useDropzone } from "react-dropzone";
|
||||||
import z from "zod";
|
import z from "zod";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { getProductDataById } from "@/service/product";
|
import {
|
||||||
|
approveProduct,
|
||||||
|
getProductDataById,
|
||||||
|
updateProduct,
|
||||||
|
} from "@/service/product";
|
||||||
|
import { convertDateFormat } from "@/utils/global";
|
||||||
|
|
||||||
const ViewEditor = dynamic(
|
const ViewEditor = dynamic(
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -99,6 +112,15 @@ export default function DetailProductForm(props: { isDetail: boolean }) {
|
||||||
const [startDateValue, setStartDateValue] = useState<any>(null);
|
const [startDateValue, setStartDateValue] = useState<any>(null);
|
||||||
const [timeValue, setTimeValue] = useState("00:00");
|
const [timeValue, setTimeValue] = useState("00:00");
|
||||||
const [openApproverHistory, setOpenApproverHistory] = useState(false);
|
const [openApproverHistory, setOpenApproverHistory] = useState(false);
|
||||||
|
const [userLevelId, setUserLevelId] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 🔹 Ambil userlevelId dari cookies
|
||||||
|
useEffect(() => {
|
||||||
|
const ulne = Cookies.get("ulne"); // contoh: "3"
|
||||||
|
setUserLevelId(ulne ?? null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const { getRootProps, getInputProps } = useDropzone({
|
const { getRootProps, getInputProps } = useDropzone({
|
||||||
onDrop: (acceptedFiles) => {
|
onDrop: (acceptedFiles) => {
|
||||||
|
|
@ -199,6 +221,17 @@ export default function DetailProductForm(props: { isDetail: boolean }) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const [isUploadDialogOpen, setIsUploadDialogOpen] = useState(false);
|
const [isUploadDialogOpen, setIsUploadDialogOpen] = useState(false);
|
||||||
|
const [openCommentModal, setOpenCommentModal] = useState(false);
|
||||||
|
const [commentValue, setCommentValue] = useState("");
|
||||||
|
const handleSubmitComment = async () => {
|
||||||
|
// await api.post("/banner/comment", {
|
||||||
|
// bannerId: viewBanner.id,
|
||||||
|
// comment: commentValue,
|
||||||
|
// });
|
||||||
|
|
||||||
|
setOpenCommentModal(false);
|
||||||
|
};
|
||||||
|
|
||||||
const [uploadTarget, setUploadTarget] = useState<{
|
const [uploadTarget, setUploadTarget] = useState<{
|
||||||
type: "spec" | "color";
|
type: "spec" | "color";
|
||||||
index: number;
|
index: number;
|
||||||
|
|
@ -268,6 +301,41 @@ export default function DetailProductForm(props: { isDetail: boolean }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleRejectProduct = async (id: number) => {
|
||||||
|
loading();
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
status_id: 3, // ✅ number
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await updateProduct(payload, id);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
error(res.message || "Gagal menolak product");
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
close();
|
||||||
|
success("Product berhasil ditolak");
|
||||||
|
initState();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleApproveProduct = async (id: number) => {
|
||||||
|
loading();
|
||||||
|
const res = await approveProduct(id);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
error(res.message || "Gagal menyetujui product");
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
close();
|
||||||
|
success("Product berhasil disetujui");
|
||||||
|
initState(); // refresh table
|
||||||
|
};
|
||||||
|
|
||||||
const handleOpenApproverHistory = () => {
|
const handleOpenApproverHistory = () => {
|
||||||
setOpenApproverHistory(true);
|
setOpenApproverHistory(true);
|
||||||
};
|
};
|
||||||
|
|
@ -517,21 +585,56 @@ export default function DetailProductForm(props: { isDetail: boolean }) {
|
||||||
</Button> */}
|
</Button> */}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p>Status Timeline</p>
|
<h4 className="text-sm font-semibold text-gray-700 mb-3">
|
||||||
|
Status Timeline
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<div className="w-6 h-6 rounded-full bg-green-100 flex items-center justify-center">
|
<div className="w-6 h-6 rounded-full bg-green-100 flex items-center justify-center">
|
||||||
<CheckCheck className="w-4 h-4 text-green-600" />
|
<Check className="w-4 h-4 text-green-600" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium text-gray-800">Diupload oleh</p>
|
<p className="font-medium text-gray-800">
|
||||||
|
Diupload oleh Operator
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
{convertDateFormat(detailData?.created_at)} WIB
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-3 mt-3">
|
|
||||||
<div className="w-6 h-6 rounded-full bg-green-100 flex items-center justify-center">
|
|
||||||
<CheckCheck className="w-4 h-4 text-green-600" />
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex gap-3">
|
||||||
|
<div
|
||||||
|
className={`w-6 h-6 rounded-full flex items-center justify-center ${
|
||||||
|
detailData?.status_id === 1
|
||||||
|
? "bg-yellow-100"
|
||||||
|
: detailData?.status_id === 2
|
||||||
|
? "bg-green-100"
|
||||||
|
: "bg-red-100"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{detailData?.status_id === 1 ? (
|
||||||
|
<Clock className="w-4 h-4 text-yellow-700" />
|
||||||
|
) : detailData?.status_id === 2 ? (
|
||||||
|
<Check className="w-4 h-4 text-green-600" />
|
||||||
|
) : (
|
||||||
|
<X className="w-4 h-4 text-red-700" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium text-gray-800">Disetujui oleh</p>
|
<p className="font-medium text-gray-800">
|
||||||
|
{detailData?.status_id === 1
|
||||||
|
? "Menunggu disetujui oleh Approver"
|
||||||
|
: detailData?.status_id === 2
|
||||||
|
? "Disetujui oleh Approver"
|
||||||
|
: "Ditolak oleh Approver"}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
{convertDateFormat(detailData?.updated_at)} WIB
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -547,6 +650,48 @@ export default function DetailProductForm(props: { isDetail: boolean }) {
|
||||||
<p>Jaecoo - Approver | 10/11/2026</p>
|
<p>Jaecoo - Approver | 10/11/2026</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{userLevelId !== "2" && detailData && (
|
||||||
|
<div className="flex justify-between items-center gap-3 px-6 py-4 border-t bg-[#F2F7FA] mt-10">
|
||||||
|
{detailData.status_id === 1 ? (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
className="bg-blue-200 hover:bg-blue-400"
|
||||||
|
onClick={() => setOpenCommentModal(true)}
|
||||||
|
>
|
||||||
|
Beri Tanggapan
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="destructive"
|
||||||
|
className="w-[180px]"
|
||||||
|
onClick={() => handleRejectProduct(detailData.id)}
|
||||||
|
>
|
||||||
|
Reject
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{userLevelId === "1" && (
|
||||||
|
<Button
|
||||||
|
className="bg-green-600 hover:bg-green-700 text-white w-[180px]"
|
||||||
|
onClick={() => handleApproveProduct(detailData.id)}
|
||||||
|
>
|
||||||
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
className="mx-auto"
|
||||||
|
onClick={() => router.back()}
|
||||||
|
>
|
||||||
|
Tutup
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* <Button className=" bg-teal-800 hover:bg-teal-900 text-white py-3">
|
{/* <Button className=" bg-teal-800 hover:bg-teal-900 text-white py-3">
|
||||||
Submit
|
Submit
|
||||||
</Button> */}
|
</Button> */}
|
||||||
|
|
@ -695,6 +840,76 @@ export default function DetailProductForm(props: { isDetail: boolean }) {
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
{openCommentModal && detailData && (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 z-[60] flex items-center justify-center bg-black/50 p-4"
|
||||||
|
onClick={() => setOpenCommentModal(false)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="bg-white rounded-2xl shadow-2xl max-w-lg w-full overflow-hidden"
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{/* HEADER */}
|
||||||
|
<div className="bg-gradient-to-br from-[#1F6779] to-[#0F6C75] text-white px-6 py-5 relative">
|
||||||
|
<button
|
||||||
|
onClick={() => setOpenCommentModal(false)}
|
||||||
|
className="absolute top-4 right-4 text-white/80 hover:text-white text-xl"
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<h2 className="text-lg font-semibold">Beri Tanggapan</h2>
|
||||||
|
|
||||||
|
{/* Badge */}
|
||||||
|
<div className="flex items-center gap-2 mt-3">
|
||||||
|
<span className="bg-yellow-100 text-yellow-800 text-xs font-medium px-3 py-1 rounded-full">
|
||||||
|
Menunggu
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span className="bg-white text-[#0F6C75] text-xs font-medium px-3 py-1 rounded-full">
|
||||||
|
Banner
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span className="bg-white/20 text-white text-xs px-2 py-[2px] rounded-full">
|
||||||
|
{detailData.position}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* BODY */}
|
||||||
|
<div className="p-6 space-y-4">
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-500 mb-2">
|
||||||
|
Comment
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
value={commentValue}
|
||||||
|
onChange={(e) => setCommentValue(e.target.value)}
|
||||||
|
placeholder="Masukkan komentar"
|
||||||
|
className="w-full min-h-[100px] border rounded-lg p-3 focus:outline-none focus:ring-2 focus:ring-[#0F6C75]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* FOOTER */}
|
||||||
|
<div className="flex justify-between gap-3 px-6 py-4 border-t bg-[#F2F7FA]">
|
||||||
|
<button
|
||||||
|
onClick={() => setOpenCommentModal(false)}
|
||||||
|
className="flex-1 py-2 rounded-xl bg-blue-100 hover:bg-blue-200 text-gray-700 font-medium"
|
||||||
|
>
|
||||||
|
Batal
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={handleSubmitComment}
|
||||||
|
className="flex-1 py-2 rounded-xl bg-[#1F6779] hover:bg-[#0F6C75] text-white font-medium"
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -416,6 +416,10 @@ export default function AgentTable() {
|
||||||
<span className="bg-green-100 text-green-700 text-xs px-3 py-1 rounded-full font-medium">
|
<span className="bg-green-100 text-green-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
Disetujui
|
Disetujui
|
||||||
</span>
|
</span>
|
||||||
|
) : item.status_id === 3 ? (
|
||||||
|
<span className="bg-red-100 text-red-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
|
Ditolak
|
||||||
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="bg-gray-100 text-gray-600 text-xs px-3 py-1 rounded-full font-medium">
|
<span className="bg-gray-100 text-gray-600 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
{item.status_id || "Tidak Diketahui"}
|
{item.status_id || "Tidak Diketahui"}
|
||||||
|
|
@ -448,6 +452,7 @@ export default function AgentTable() {
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
{/* Tombol Edit */}
|
{/* Tombol Edit */}
|
||||||
|
{userLevelId !== "1" && (
|
||||||
<Link href={`/admin/agent/update/${item.id}`}>
|
<Link href={`/admin/agent/update/${item.id}`}>
|
||||||
<Button
|
<Button
|
||||||
className="text-[#0F6C75] hover:bg-transparent hover:underline p-0"
|
className="text-[#0F6C75] hover:bg-transparent hover:underline p-0"
|
||||||
|
|
@ -457,9 +462,9 @@ export default function AgentTable() {
|
||||||
<CreateIconIon className="w-4 h-4 mr-1" /> Edit
|
<CreateIconIon className="w-4 h-4 mr-1" /> Edit
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
)}
|
||||||
{/* Tombol Approve - hanya untuk admin dan status pending */}
|
{/* Tombol Approve - hanya untuk admin dan status pending */}
|
||||||
{userLevelId === "1" && item.status_id === 1 && (
|
{/* {userLevelId === "1" && item.status_id === 1 && (
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -469,7 +474,7 @@ export default function AgentTable() {
|
||||||
<CheckCheck className="w-4 h-4 mr-1" />
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
Approve
|
Approve
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)} */}
|
||||||
{/* Tombol Hapus */}
|
{/* Tombol Hapus */}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,12 @@ import {
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import CustomPagination from "../layout/custom-pagination";
|
import CustomPagination from "../layout/custom-pagination";
|
||||||
import { EditBannerDialog } from "../form/banner-edit-dialog";
|
import { EditBannerDialog } from "../form/banner-edit-dialog";
|
||||||
import { deleteBanner, getBannerData, updateBanner, approveBanner } from "@/service/banner";
|
import {
|
||||||
|
deleteBanner,
|
||||||
|
getBannerData,
|
||||||
|
updateBanner,
|
||||||
|
approveBanner,
|
||||||
|
} from "@/service/banner";
|
||||||
import { Check, CheckCheck, Clock, Eye, X } from "lucide-react";
|
import { Check, CheckCheck, Clock, Eye, X } from "lucide-react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
|
|
@ -219,25 +224,25 @@ export default function ArticleTable() {
|
||||||
await updateBanner(formData, id);
|
await updateBanner(formData, id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleApprove = async () => {
|
// const handleApprove = async () => {
|
||||||
if (!viewBanner) return;
|
// if (!viewBanner) return;
|
||||||
|
|
||||||
loading();
|
// loading();
|
||||||
const formData = new FormData();
|
// const formData = new FormData();
|
||||||
formData.append("status", "2"); // APPROVED
|
// formData.append("status", "2"); // APPROVED
|
||||||
|
|
||||||
const res = await updateBanner(formData, viewBanner.id);
|
// const res = await updateBanner(formData, viewBanner.id);
|
||||||
|
|
||||||
if (res?.error) {
|
// if (res?.error) {
|
||||||
error(res.message);
|
// error(res.message);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
close();
|
// close();
|
||||||
success("Banner berhasil disetujui");
|
// success("Banner berhasil disetujui");
|
||||||
setOpenViewDialog(false);
|
// setOpenViewDialog(false);
|
||||||
initState(); // refresh table
|
// initState(); // refresh table
|
||||||
};
|
// };
|
||||||
|
|
||||||
const handleApproveBanner = async (id: number) => {
|
const handleApproveBanner = async (id: number) => {
|
||||||
loading();
|
loading();
|
||||||
|
|
@ -486,6 +491,10 @@ export default function ArticleTable() {
|
||||||
<span className="bg-green-100 text-green-700 text-xs px-3 py-1 rounded-full font-medium">
|
<span className="bg-green-100 text-green-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
Disetujui
|
Disetujui
|
||||||
</span>
|
</span>
|
||||||
|
) : item.status_id === 3 ? (
|
||||||
|
<span className="bg-red-100 text-red-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
|
Ditolak
|
||||||
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="bg-gray-100 text-gray-600 text-xs px-3 py-1 rounded-full font-medium">
|
<span className="bg-gray-100 text-gray-600 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
{item.status_id || "Tidak Diketahui"}
|
{item.status_id || "Tidak Diketahui"}
|
||||||
|
|
@ -505,7 +514,7 @@ export default function ArticleTable() {
|
||||||
<Eye className="w-4 h-4 mr-1" />
|
<Eye className="w-4 h-4 mr-1" />
|
||||||
Lihat
|
Lihat
|
||||||
</Button>
|
</Button>
|
||||||
{userLevelId !== "3" && (
|
{userLevelId !== "1" && (
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -516,7 +525,7 @@ export default function ArticleTable() {
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{userLevelId === "1" && item.status_id === 1 && (
|
{/* {userLevelId === "1" && item.status_id === 1 && (
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -526,7 +535,7 @@ export default function ArticleTable() {
|
||||||
<CheckCheck className="w-4 h-4 mr-1" />
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
Approve
|
Approve
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)} */}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -669,21 +678,21 @@ export default function ArticleTable() {
|
||||||
<div className="flex items-center gap-2 mt-3">
|
<div className="flex items-center gap-2 mt-3">
|
||||||
<span
|
<span
|
||||||
className={`text-xs font-medium px-3 py-1 rounded-full ${
|
className={`text-xs font-medium px-3 py-1 rounded-full ${
|
||||||
viewBanner.status === "1"
|
viewBanner.status_id === 1
|
||||||
? "bg-yellow-100 text-yellow-800"
|
? "bg-yellow-100 text-yellow-800"
|
||||||
: viewBanner.status === "2"
|
: viewBanner.status_id === 2
|
||||||
? "bg-green-100 text-green-800"
|
? "bg-green-100 text-green-800"
|
||||||
: viewBanner.status === "3"
|
: viewBanner.status_id === 3
|
||||||
? "bg-red-100 text-red-800"
|
? "bg-red-100 text-red-800"
|
||||||
: "bg-gray-100 text-gray-800"
|
: "bg-gray-100 text-gray-800"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{viewBanner.status === "1"
|
{viewBanner.status_id === 1
|
||||||
? "Menunggu"
|
? "Menunggu"
|
||||||
: viewBanner.status === "2"
|
: viewBanner.status_id === 2
|
||||||
? "Disetujui"
|
? "Disetujui"
|
||||||
: viewBanner.status === "3"
|
: viewBanner.status_id === 3
|
||||||
? "Reject"
|
? "Ditolak"
|
||||||
: "Tidak Diketahui"}
|
: "Tidak Diketahui"}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
@ -753,16 +762,16 @@ export default function ArticleTable() {
|
||||||
<div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<div
|
<div
|
||||||
className={`w-6 h-6 rounded-full flex items-center justify-center ${
|
className={`w-6 h-6 rounded-full flex items-center justify-center ${
|
||||||
viewBanner.status === "1"
|
viewBanner.status_id === 1
|
||||||
? "bg-yellow-100"
|
? "bg-yellow-100"
|
||||||
: viewBanner.status === "2"
|
: viewBanner.status_id === 2
|
||||||
? "bg-green-100"
|
? "bg-green-100"
|
||||||
: "bg-red-100"
|
: "bg-red-100"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{viewBanner.status === "1" ? (
|
{viewBanner.status_id === 1 ? (
|
||||||
<Clock className="w-4 h-4 text-yellow-700" />
|
<Clock className="w-4 h-4 text-yellow-700" />
|
||||||
) : viewBanner.status === "2" ? (
|
) : viewBanner.status_id === 2 ? (
|
||||||
<Check className="w-4 h-4 text-green-600" />
|
<Check className="w-4 h-4 text-green-600" />
|
||||||
) : (
|
) : (
|
||||||
<X className="w-4 h-4 text-red-700" />
|
<X className="w-4 h-4 text-red-700" />
|
||||||
|
|
@ -771,9 +780,9 @@ export default function ArticleTable() {
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium text-gray-800">
|
<p className="font-medium text-gray-800">
|
||||||
{viewBanner.status === "1"
|
{viewBanner.status_id === 1
|
||||||
? "Menunggu disetujui oleh Approver"
|
? "Menunggu disetujui oleh Approver"
|
||||||
: viewBanner.status === "2"
|
: viewBanner.status_id === 2
|
||||||
? "Disetujui oleh Approver"
|
? "Disetujui oleh Approver"
|
||||||
: "Ditolak oleh Approver"}
|
: "Ditolak oleh Approver"}
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -803,7 +812,7 @@ export default function ArticleTable() {
|
||||||
{/* FOOTER */}
|
{/* FOOTER */}
|
||||||
{userLevelId !== "2" && (
|
{userLevelId !== "2" && (
|
||||||
<div className="flex justify-between items-center gap-3 px-6 py-4 border-t bg-[#F2F7FA]">
|
<div className="flex justify-between items-center gap-3 px-6 py-4 border-t bg-[#F2F7FA]">
|
||||||
{viewBanner.status === "1" ? (
|
{viewBanner.status_id === 1 ? (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
|
|
@ -817,8 +826,8 @@ export default function ArticleTable() {
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="destructive"
|
|
||||||
className=" w-[180]"
|
className=" w-[180]"
|
||||||
|
variant="destructive"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
handleReject();
|
handleReject();
|
||||||
|
|
@ -827,15 +836,20 @@ export default function ArticleTable() {
|
||||||
Reject
|
Reject
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
{userLevelId === "1" && (
|
||||||
<Button
|
<Button
|
||||||
|
// variant="ghost"
|
||||||
|
size="sm"
|
||||||
className="bg-green-600 hover:bg-green-700 text-white w-[180]"
|
className="bg-green-600 hover:bg-green-700 text-white w-[180]"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
handleApprove();
|
handleApproveBanner(viewBanner.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Approved
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
|
Approve
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,14 @@
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { Eye, Pencil, Trash2, Calendar, MapPin, CheckCheck } from "lucide-react";
|
import {
|
||||||
|
Eye,
|
||||||
|
Pencil,
|
||||||
|
Trash2,
|
||||||
|
Calendar,
|
||||||
|
MapPin,
|
||||||
|
CheckCheck,
|
||||||
|
} from "lucide-react";
|
||||||
import {
|
import {
|
||||||
deleteGalery,
|
deleteGalery,
|
||||||
getGaleryById,
|
getGaleryById,
|
||||||
|
|
@ -50,7 +57,7 @@ export default function Galery() {
|
||||||
|
|
||||||
// Filter file dengan gallery_id sama dengan item.id
|
// Filter file dengan gallery_id sama dengan item.id
|
||||||
const filteredImages = images?.filter(
|
const filteredImages = images?.filter(
|
||||||
(img: any) => img.gallery_id === item.id
|
(img: any) => img.gallery_id === item.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ambil gambar pertama sebagai thumbnail
|
// Ambil gambar pertama sebagai thumbnail
|
||||||
|
|
@ -64,7 +71,7 @@ export default function Galery() {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return { ...item, image_url: null };
|
return { ...item, image_url: null };
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
setData(merged);
|
setData(merged);
|
||||||
|
|
@ -211,23 +218,23 @@ export default function Galery() {
|
||||||
>
|
>
|
||||||
<Eye className="h-4 w-4" /> Lihat
|
<Eye className="h-4 w-4" /> Lihat
|
||||||
</button>
|
</button>
|
||||||
|
{userLevelId !== "1" && (
|
||||||
<button
|
<button
|
||||||
onClick={() => openEdit(item.id)}
|
onClick={() => openEdit(item.id)}
|
||||||
className="flex items-center gap-1 text-gray-700 hover:text-[#1F6779] transition"
|
className="flex items-center gap-1 text-gray-700 hover:text-[#1F6779] transition"
|
||||||
>
|
>
|
||||||
<Pencil className="h-4 w-4" /> Edit
|
<Pencil className="h-4 w-4" /> Edit
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
{/* Tombol Approve - hanya untuk admin dan status pending */}
|
{/* Tombol Approve - hanya untuk admin dan status pending */}
|
||||||
{userLevelId === "1" && item.status_id === 1 && (
|
{/* {userLevelId === "1" && item.status_id === 1 && (
|
||||||
<button
|
<button
|
||||||
className="flex items-center gap-1 text-green-600 hover:text-green-700 transition"
|
className="flex items-center gap-1 text-green-600 hover:text-green-700 transition"
|
||||||
onClick={() => handleApproveGalery(item.id)}
|
onClick={() => handleApproveGalery(item.id)}
|
||||||
>
|
>
|
||||||
<CheckCheck className="h-4 w-4" /> Approve
|
<CheckCheck className="h-4 w-4" /> Approve
|
||||||
</button>
|
</button>
|
||||||
)}
|
)} */}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className="flex items-center gap-1 text-red-600 hover:text-red-700 transition"
|
className="flex items-center gap-1 text-red-600 hover:text-red-700 transition"
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,11 @@ import {
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import CustomPagination from "../layout/custom-pagination";
|
import CustomPagination from "../layout/custom-pagination";
|
||||||
import { EditBannerDialog } from "../form/banner-edit-dialog";
|
import { EditBannerDialog } from "../form/banner-edit-dialog";
|
||||||
import { deleteProduct, getProductPagination, approveProduct } from "@/service/product";
|
import {
|
||||||
|
deleteProduct,
|
||||||
|
getProductPagination,
|
||||||
|
approveProduct,
|
||||||
|
} from "@/service/product";
|
||||||
import { CheckCheck, Eye } from "lucide-react";
|
import { CheckCheck, Eye } from "lucide-react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
|
|
@ -448,6 +452,10 @@ export default function ProductTable() {
|
||||||
<span className="bg-green-100 text-green-700 text-xs px-3 py-1 rounded-full font-medium">
|
<span className="bg-green-100 text-green-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
Disetujui
|
Disetujui
|
||||||
</span>
|
</span>
|
||||||
|
) : item.status_id === 3 ? (
|
||||||
|
<span className="bg-red-100 text-red-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
|
Ditolak
|
||||||
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="bg-gray-100 text-gray-600 text-xs px-3 py-1 rounded-full font-medium">
|
<span className="bg-gray-100 text-gray-600 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
{item.status_id || "Tidak Diketahui"}
|
{item.status_id || "Tidak Diketahui"}
|
||||||
|
|
@ -468,7 +476,7 @@ export default function ProductTable() {
|
||||||
Lihat
|
Lihat
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
{userLevelId !== "3" && (
|
{userLevelId !== "1" && (
|
||||||
<Link href={"/admin/product/update"}>
|
<Link href={"/admin/product/update"}>
|
||||||
<Button
|
<Button
|
||||||
className="text-[#0F6C75] hover:bg-transparent hover:underline p-0"
|
className="text-[#0F6C75] hover:bg-transparent hover:underline p-0"
|
||||||
|
|
@ -479,7 +487,7 @@ export default function ProductTable() {
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
{userLevelId === "1" && item.status_id === 1 && (
|
{/* {userLevelId === "1" && item.status_id === 1 && (
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -489,7 +497,7 @@ export default function ProductTable() {
|
||||||
<CheckCheck className="w-4 h-4 mr-1" />
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
Approve
|
Approve
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)} */}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,11 @@ import { EditBannerDialog } from "../form/banner-edit-dialog";
|
||||||
import { Eye, Trash2, CheckCheck } from "lucide-react";
|
import { Eye, Trash2, CheckCheck } from "lucide-react";
|
||||||
import AgentDetailDialog from "../dialog/agent-dialog";
|
import AgentDetailDialog from "../dialog/agent-dialog";
|
||||||
import PromoDetailDialog from "../dialog/promo-dialog";
|
import PromoDetailDialog from "../dialog/promo-dialog";
|
||||||
import { deletePromotion, getPromotionPagination, approvePromotion } from "@/service/promotion";
|
import {
|
||||||
|
deletePromotion,
|
||||||
|
getPromotionPagination,
|
||||||
|
approvePromotion,
|
||||||
|
} from "@/service/promotion";
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ name: "No", uid: "no" },
|
{ name: "No", uid: "no" },
|
||||||
|
|
@ -433,7 +437,7 @@ export default function PromotionTable() {
|
||||||
{/* Tombol Edit */}
|
{/* Tombol Edit */}
|
||||||
|
|
||||||
{/* Tombol Approve - hanya untuk admin dan status pending */}
|
{/* Tombol Approve - hanya untuk admin dan status pending */}
|
||||||
{userLevelId === "1" && item.status_id === 1 && (
|
{/* {userLevelId === "1" && item.status_id === 1 && (
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -443,7 +447,7 @@ export default function PromotionTable() {
|
||||||
<CheckCheck className="w-4 h-4 mr-1" />
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
Approve
|
Approve
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)} */}
|
||||||
{/* Tombol Hapus */}
|
{/* Tombol Hapus */}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue