feat: update approval for all module
This commit is contained in:
parent
9ee2433a78
commit
98bace5dcc
|
|
@ -47,9 +47,9 @@ 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 { Eye } from "lucide-react";
|
import { Eye, CheckCheck } from "lucide-react";
|
||||||
import AgentDetailDialog from "../dialog/agent-dialog";
|
import AgentDetailDialog from "../dialog/agent-dialog";
|
||||||
import { deleteAgent, getAgentData } from "@/service/agent";
|
import { deleteAgent, getAgentData, approveAgent } from "@/service/agent";
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ name: "No", uid: "no" },
|
{ name: "No", uid: "no" },
|
||||||
|
|
@ -94,6 +94,13 @@ export default function AgentTable() {
|
||||||
startDate: null,
|
startDate: null,
|
||||||
endDate: null,
|
endDate: null,
|
||||||
});
|
});
|
||||||
|
const [userLevelId, setUserLevelId] = useState<string | null>(null);
|
||||||
|
|
||||||
|
// 🔹 Ambil userlevelId dari cookies
|
||||||
|
useEffect(() => {
|
||||||
|
const ulne = Cookies.get("ulne"); // contoh: "3"
|
||||||
|
setUserLevelId(ulne ?? null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initState();
|
initState();
|
||||||
|
|
@ -180,6 +187,21 @@ export default function AgentTable() {
|
||||||
setOpenPreview(true);
|
setOpenPreview(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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");
|
||||||
|
initState(); // refresh table
|
||||||
|
};
|
||||||
|
|
||||||
const copyUrlArticle = async (id: number, slug: string) => {
|
const copyUrlArticle = async (id: number, slug: string) => {
|
||||||
const url =
|
const url =
|
||||||
`${window.location.protocol}//${window.location.host}` +
|
`${window.location.protocol}//${window.location.host}` +
|
||||||
|
|
@ -386,9 +408,19 @@ export default function AgentTable() {
|
||||||
|
|
||||||
{/* STATUS */}
|
{/* STATUS */}
|
||||||
<TableCell className="text-center">
|
<TableCell className="text-center">
|
||||||
<span className="bg-yellow-100 text-yellow-800 text-xs font-medium px-3 py-1 rounded-full">
|
{item.status_id === 1 ? (
|
||||||
|
<span className="bg-yellow-100 text-yellow-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
Menunggu
|
Menunggu
|
||||||
</span>
|
</span>
|
||||||
|
) : item.status_id === 2 ? (
|
||||||
|
<span className="bg-green-100 text-green-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
|
Disetujui
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="bg-gray-100 text-gray-600 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
|
{item.status_id || "Tidak Diketahui"}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
{/* AKSI */}
|
{/* AKSI */}
|
||||||
|
|
@ -426,6 +458,18 @@ export default function AgentTable() {
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
{/* Tombol Approve - hanya untuk admin dan status pending */}
|
||||||
|
{userLevelId === "1" && item.status_id === 1 && (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handleApproveAgent(item.id)}
|
||||||
|
className="text-green-600 hover:bg-transparent hover:underline p-0"
|
||||||
|
>
|
||||||
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
{/* Tombol Hapus */}
|
{/* Tombol Hapus */}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ 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 } 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";
|
||||||
|
|
||||||
|
|
@ -239,6 +239,21 @@ export default function ArticleTable() {
|
||||||
initState(); // refresh table
|
initState(); // refresh table
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleApproveBanner = async (id: number) => {
|
||||||
|
loading();
|
||||||
|
const res = await approveBanner(id);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
error(res.message || "Gagal menyetujui banner");
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
close();
|
||||||
|
success("Banner berhasil disetujui");
|
||||||
|
initState(); // refresh table
|
||||||
|
};
|
||||||
|
|
||||||
const handleReject = async () => {
|
const handleReject = async () => {
|
||||||
if (!viewBanner) return;
|
if (!viewBanner) return;
|
||||||
|
|
||||||
|
|
@ -463,21 +478,17 @@ export default function ArticleTable() {
|
||||||
|
|
||||||
{/* STATUS */}
|
{/* STATUS */}
|
||||||
<TableCell className="text-center">
|
<TableCell className="text-center">
|
||||||
{item.status === "1" ? (
|
{item.status_id === 1 ? (
|
||||||
<span className="bg-yellow-100 text-yellow-700 text-xs px-3 py-1 rounded-full font-medium">
|
<span className="bg-yellow-100 text-yellow-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
Menunggu
|
Menunggu
|
||||||
</span>
|
</span>
|
||||||
) : item.status === "2" ? (
|
) : item.status_id === 2 ? (
|
||||||
<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 === "3" ? (
|
|
||||||
<span className="bg-red-100 text-red-700 text-xs px-3 py-1 rounded-full font-medium">
|
|
||||||
Canceled
|
|
||||||
</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">
|
||||||
Tidak Diketahui
|
{item.status_id || "Tidak Diketahui"}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
@ -505,6 +516,17 @@ export default function ArticleTable() {
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
{userLevelId === "1" && item.status_id === 1 && (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="text-green-600 hover:bg-transparent hover:underline p-0"
|
||||||
|
onClick={() => handleApproveBanner(item.id)}
|
||||||
|
>
|
||||||
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,25 @@
|
||||||
|
|
||||||
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 } from "lucide-react";
|
import { Eye, Pencil, Trash2, Calendar, MapPin, CheckCheck } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
deleteGalery,
|
deleteGalery,
|
||||||
getGaleryById,
|
getGaleryById,
|
||||||
getGaleryData,
|
getGaleryData,
|
||||||
getGaleryFileData,
|
getGaleryFileData,
|
||||||
|
approveGalery,
|
||||||
} from "@/service/galery";
|
} from "@/service/galery";
|
||||||
import { DialogDetailGaleri } from "../dialog/galery-detail-dialog";
|
import { DialogDetailGaleri } from "../dialog/galery-detail-dialog";
|
||||||
import { DialogUpdateGaleri } from "../dialog/galery-update-dialog";
|
import { DialogUpdateGaleri } from "../dialog/galery-update-dialog";
|
||||||
import { error, success } from "@/config/swal";
|
import { error, success, loading, close } from "@/config/swal";
|
||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
export default function Galery() {
|
export default function Galery() {
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
const [data, setData] = useState<any[]>([]);
|
const [data, setData] = useState<any[]>([]);
|
||||||
|
const [userLevelId, setUserLevelId] = useState<string | null>(null);
|
||||||
|
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [showData, setShowData] = useState("10");
|
const [showData, setShowData] = useState("10");
|
||||||
|
|
@ -70,6 +73,12 @@ export default function Galery() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 🔹 Ambil userlevelId dari cookies
|
||||||
|
useEffect(() => {
|
||||||
|
const ulne = Cookies.get("ulne"); // contoh: "3"
|
||||||
|
setUserLevelId(ulne ?? null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
}, [page, showData, search]);
|
}, [page, showData, search]);
|
||||||
|
|
@ -120,6 +129,21 @@ export default function Galery() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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");
|
||||||
|
fetchData(); // refresh table
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5">
|
||||||
|
|
@ -147,12 +171,18 @@ export default function Galery() {
|
||||||
<span
|
<span
|
||||||
className={`absolute top-3 left-3 text-xs px-3 py-1 rounded-full font-medium
|
className={`absolute top-3 left-3 text-xs px-3 py-1 rounded-full font-medium
|
||||||
${
|
${
|
||||||
item.is_active
|
item.status_id === 2
|
||||||
? "bg-green-100 text-green-700"
|
? "bg-green-100 text-green-700"
|
||||||
: "bg-red-100 text-red-600"
|
: item.status_id === 1
|
||||||
|
? "bg-yellow-100 text-yellow-700"
|
||||||
|
: "bg-gray-100 text-gray-600"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{item.is_active ? "Aktif" : "Tidak Aktif"}
|
{item.status_id === 2
|
||||||
|
? "Disetujui"
|
||||||
|
: item.status_id === 1
|
||||||
|
? "Menunggu"
|
||||||
|
: "Tidak Diketahui"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -189,6 +219,16 @@ export default function Galery() {
|
||||||
<Pencil className="h-4 w-4" /> Edit
|
<Pencil className="h-4 w-4" /> Edit
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{/* Tombol Approve - hanya untuk admin dan status pending */}
|
||||||
|
{userLevelId === "1" && item.status_id === 1 && (
|
||||||
|
<button
|
||||||
|
className="flex items-center gap-1 text-green-600 hover:text-green-700 transition"
|
||||||
|
onClick={() => handleApproveGalery(item.id)}
|
||||||
|
>
|
||||||
|
<CheckCheck className="h-4 w-4" /> Approve
|
||||||
|
</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"
|
||||||
onClick={() => handleDelete(item.id)}
|
onClick={() => handleDelete(item.id)}
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ 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 } 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";
|
||||||
|
|
||||||
|
|
@ -194,6 +194,21 @@ export default function ProductTable() {
|
||||||
setOpenPreview(true);
|
setOpenPreview(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 copyUrlArticle = async (id: number, slug: string) => {
|
const copyUrlArticle = async (id: number, slug: string) => {
|
||||||
const url =
|
const url =
|
||||||
`${window.location.protocol}//${window.location.host}` +
|
`${window.location.protocol}//${window.location.host}` +
|
||||||
|
|
@ -425,13 +440,17 @@ export default function ProductTable() {
|
||||||
|
|
||||||
{/* STATUS */}
|
{/* STATUS */}
|
||||||
<TableCell className="text-center">
|
<TableCell className="text-center">
|
||||||
{item.status === "Disetujui" ? (
|
{item.status_id === 1 ? (
|
||||||
<span className="bg-green-100 text-green-700 text-xs font-medium px-3 py-1 rounded-full">
|
<span className="bg-yellow-100 text-yellow-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
|
Menunggu
|
||||||
|
</span>
|
||||||
|
) : item.status_id === 2 ? (
|
||||||
|
<span className="bg-green-100 text-green-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
Disetujui
|
Disetujui
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="bg-yellow-100 text-yellow-800 text-xs font-medium px-3 py-1 rounded-full">
|
<span className="bg-gray-100 text-gray-600 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
Menunggu
|
{item.status_id || "Tidak Diketahui"}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
@ -460,6 +479,17 @@ export default function ProductTable() {
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
|
{userLevelId === "1" && item.status_id === 1 && (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handleApproveProduct(item.id)}
|
||||||
|
className="text-green-600 hover:bg-transparent hover:underline p-0"
|
||||||
|
>
|
||||||
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,10 @@ 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 { Eye, Trash2 } 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 } from "@/service/promotion";
|
import { deletePromotion, getPromotionPagination, approvePromotion } from "@/service/promotion";
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ name: "No", uid: "no" },
|
{ name: "No", uid: "no" },
|
||||||
|
|
@ -96,6 +96,13 @@ export default function PromotionTable() {
|
||||||
startDate: null,
|
startDate: null,
|
||||||
endDate: null,
|
endDate: null,
|
||||||
});
|
});
|
||||||
|
const [userLevelId, setUserLevelId] = useState<string | null>(null);
|
||||||
|
|
||||||
|
// 🔹 Ambil userlevelId dari cookies
|
||||||
|
useEffect(() => {
|
||||||
|
const ulne = Cookies.get("ulne"); // contoh: "3"
|
||||||
|
setUserLevelId(ulne ?? null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
initState();
|
initState();
|
||||||
|
|
@ -182,6 +189,21 @@ export default function PromotionTable() {
|
||||||
setOpenPreview(true);
|
setOpenPreview(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleApprovePromotion = async (id: number) => {
|
||||||
|
loading();
|
||||||
|
const res = await approvePromotion(id);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
error(res.message || "Gagal menyetujui promotion");
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
close();
|
||||||
|
success("Promotion berhasil disetujui");
|
||||||
|
initState(); // refresh table
|
||||||
|
};
|
||||||
|
|
||||||
const copyUrlArticle = async (id: number, slug: string) => {
|
const copyUrlArticle = async (id: number, slug: string) => {
|
||||||
const url =
|
const url =
|
||||||
`${window.location.protocol}//${window.location.host}` +
|
`${window.location.protocol}//${window.location.host}` +
|
||||||
|
|
@ -378,9 +400,19 @@ export default function PromotionTable() {
|
||||||
|
|
||||||
{/* STATUS */}
|
{/* STATUS */}
|
||||||
<TableCell className="text-center">
|
<TableCell className="text-center">
|
||||||
<span className="bg-yellow-100 text-yellow-800 text-xs font-medium px-3 py-1 rounded-full">
|
{item.status_id === 1 ? (
|
||||||
|
<span className="bg-yellow-100 text-yellow-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
Menunggu
|
Menunggu
|
||||||
</span>
|
</span>
|
||||||
|
) : item.status_id === 2 ? (
|
||||||
|
<span className="bg-green-100 text-green-700 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
|
Disetujui
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span className="bg-gray-100 text-gray-600 text-xs px-3 py-1 rounded-full font-medium">
|
||||||
|
{item.status_id || "Tidak Diketahui"}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
{/* AKSI */}
|
{/* AKSI */}
|
||||||
|
|
@ -400,6 +432,18 @@ export default function PromotionTable() {
|
||||||
</Button>
|
</Button>
|
||||||
{/* Tombol Edit */}
|
{/* Tombol Edit */}
|
||||||
|
|
||||||
|
{/* Tombol Approve - hanya untuk admin dan status pending */}
|
||||||
|
{userLevelId === "1" && item.status_id === 1 && (
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => handleApprovePromotion(item.id)}
|
||||||
|
className="text-green-600 hover:bg-transparent hover:underline p-0"
|
||||||
|
>
|
||||||
|
<CheckCheck className="w-4 h-4 mr-1" />
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
{/* Tombol Hapus */}
|
{/* Tombol Hapus */}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
# Environment Setup untuk API Services
|
||||||
|
|
||||||
|
## Cara Setup Environment Variables
|
||||||
|
|
||||||
|
Buat file `.env.local` di root project dengan konfigurasi berikut:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# API Endpoints
|
||||||
|
NEXT_PUBLIC_API_BASE_URL=https://jaecookelapagading.com/api
|
||||||
|
NEXT_PUBLIC_LOCAL_API_URL=http://localhost:8800
|
||||||
|
NEXT_PUBLIC_CLIENT_KEY=bb65b1ad-e954-4a1a-b4d0-74df5bb0b640
|
||||||
|
```
|
||||||
|
|
||||||
|
## Penjelasan
|
||||||
|
|
||||||
|
- `NEXT_PUBLIC_API_BASE_URL`: URL base untuk API (production atau development)
|
||||||
|
- `NEXT_PUBLIC_LOCAL_API_URL`: URL untuk API lokal (localhost:8800)
|
||||||
|
- `NEXT_PUBLIC_CLIENT_KEY`: Client key untuk authentikasi API
|
||||||
|
|
||||||
|
## Cara Menggunakan
|
||||||
|
|
||||||
|
### 1. Untuk memanggil localhost:8800
|
||||||
|
|
||||||
|
Ubah `NEXT_PUBLIC_API_BASE_URL` di `.env.local`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
NEXT_PUBLIC_API_BASE_URL=http://localhost:8800
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Untuk memanggil API production
|
||||||
|
|
||||||
|
```env
|
||||||
|
NEXT_PUBLIC_API_BASE_URL=https://jaecookelapagading.com/api
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Menggunakan service
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Tanpa authentication
|
||||||
|
import { getDataFromLocal, postDataToLocal } from '@/service/local-api-service';
|
||||||
|
|
||||||
|
const data = await getDataFromLocal('/endpoint');
|
||||||
|
|
||||||
|
// Dengan authentication (menggunakan Bearer token dari cookies)
|
||||||
|
import { getDataWithAuth, postDataWithAuth } from '@/service/local-api-service';
|
||||||
|
|
||||||
|
const data = await getDataWithAuth('/endpoint');
|
||||||
|
```
|
||||||
|
|
||||||
|
## File yang Sudah Diupdate
|
||||||
|
|
||||||
|
- `service/http-config/axios-base-instance.ts` - Membaca dari env variable
|
||||||
|
- `service/http-config/axios-interceptor-instance.ts` - Membaca dari env variable
|
||||||
|
- `service/local-api-service.ts` - Service helper untuk memanggil API
|
||||||
|
|
||||||
|
## Catatan
|
||||||
|
|
||||||
|
- Pastikan file `.env.local` tidak di-commit ke repository
|
||||||
|
- File `.env.local` sudah ada di `.gitignore`
|
||||||
|
- Restart development server setelah mengubah environment variables
|
||||||
|
|
||||||
|
|
@ -39,3 +39,10 @@ export async function deleteAgent(id: string) {
|
||||||
};
|
};
|
||||||
return await httpDeleteInterceptor(`sales-agents/${id}`, headers);
|
return await httpDeleteInterceptor(`sales-agents/${id}`, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function approveAgent(id: string | number) {
|
||||||
|
const headers = {
|
||||||
|
"content-type": "application/json",
|
||||||
|
};
|
||||||
|
return await httpPutInterceptor(`/sales-agents/${id}/approve`, {}, headers);
|
||||||
|
}
|
||||||
|
|
@ -49,3 +49,10 @@ export async function deleteBanner(id: string) {
|
||||||
};
|
};
|
||||||
return await httpDeleteInterceptor(`banners/${id}`, headers);
|
return await httpDeleteInterceptor(`banners/${id}`, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function approveBanner(id: string | number) {
|
||||||
|
const headers = {
|
||||||
|
"content-type": "application/json",
|
||||||
|
};
|
||||||
|
return await httpPutInterceptor(`/banners/${id}/approve`, {}, headers);
|
||||||
|
}
|
||||||
|
|
@ -70,3 +70,10 @@ export async function deleteGaleryFile(id: any) {
|
||||||
};
|
};
|
||||||
return await httpDeleteInterceptor(`gallery-files/${id}`, headers);
|
return await httpDeleteInterceptor(`gallery-files/${id}`, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function approveGalery(id: string | number) {
|
||||||
|
const headers = {
|
||||||
|
"content-type": "application/json",
|
||||||
|
};
|
||||||
|
return await httpPutInterceptor(`/galleries/${id}/approve`, {}, headers);
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
const baseURL = "https://jaecookelapagading.com/api";
|
// Mengambil base URL dari environment variable, default ke API production
|
||||||
|
const baseURL = process.env.NEXT_PUBLIC_API_BASE_URL || "https://jaecookelapagading.com/api";
|
||||||
|
const clientKey = process.env.NEXT_PUBLIC_CLIENT_KEY || "bb65b1ad-e954-4a1a-b4d0-74df5bb0b640";
|
||||||
|
|
||||||
const axiosBaseInstance = axios.create({
|
const axiosBaseInstance = axios.create({
|
||||||
baseURL,
|
baseURL,
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Client-Key": "bb65b1ad-e954-4a1a-b4d0-74df5bb0b640",
|
"X-Client-Key": clientKey,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ import axios from "axios";
|
||||||
import { postSignIn } from "../master-user";
|
import { postSignIn } from "../master-user";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
|
|
||||||
const baseURL = "https://jaecookelapagading.com/api";
|
// Mengambil base URL dari environment variable, default ke API production
|
||||||
|
const baseURL = process.env.NEXT_PUBLIC_API_BASE_URL || "https://jaecookelapagading.com/api";
|
||||||
|
const clientKey = process.env.NEXT_PUBLIC_CLIENT_KEY || "bb65b1ad-e954-4a1a-b4d0-74df5bb0b640";
|
||||||
|
|
||||||
const refreshToken = Cookies.get("refresh_token");
|
const refreshToken = Cookies.get("refresh_token");
|
||||||
|
|
||||||
|
|
@ -10,7 +12,7 @@ const axiosInterceptorInstance = axios.create({
|
||||||
baseURL,
|
baseURL,
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Client-Key": "bb65b1ad-e954-4a1a-b4d0-74df5bb0b640",
|
"X-Client-Key": clientKey,
|
||||||
},
|
},
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* Service untuk memanggil API lokal (localhost:8800)
|
||||||
|
* Menggunakan endpoint dari .env
|
||||||
|
*
|
||||||
|
* Contoh penggunaan:
|
||||||
|
* - Set NEXT_PUBLIC_API_BASE_URL=http://localhost:8800 di file .env.local
|
||||||
|
* - Atau gunakan NEXT_PUBLIC_LOCAL_API_URL jika ingin endpoint terpisah
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
httpGet,
|
||||||
|
httpPost,
|
||||||
|
} from "./http-config/http-base-services";
|
||||||
|
|
||||||
|
import {
|
||||||
|
httpGetInterceptor,
|
||||||
|
httpPostInterceptor,
|
||||||
|
httpPutInterceptor,
|
||||||
|
httpDeleteInterceptor,
|
||||||
|
} from "./http-config/http-interceptor-services";
|
||||||
|
|
||||||
|
// Service untuk endpoint yang tidak memerlukan authentication
|
||||||
|
// Menggunakan axios-base-instance.ts
|
||||||
|
|
||||||
|
export async function getDataFromLocal(endpoint: string, headers?: any) {
|
||||||
|
return await httpGet(endpoint, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function postDataToLocal(endpoint: string, data: any, headers?: any) {
|
||||||
|
return await httpPost(endpoint, data, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service untuk endpoint yang memerlukan authentication
|
||||||
|
// Menggunakan axios-interceptor-instance.ts dengan Bearer token
|
||||||
|
|
||||||
|
export async function getDataWithAuth(endpoint: string, headers?: any) {
|
||||||
|
return await httpGetInterceptor(endpoint, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function postDataWithAuth(endpoint: string, data: any, headers?: any) {
|
||||||
|
return await httpPostInterceptor(endpoint, data, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateDataWithAuth(endpoint: string, data: any, headers?: any) {
|
||||||
|
return await httpPutInterceptor(endpoint, data, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteDataWithAuth(endpoint: string, headers?: any) {
|
||||||
|
return await httpDeleteInterceptor(endpoint, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contoh implementasi spesifik untuk endpoint /api/users
|
||||||
|
// Gunakan service dengan auth jika endpoint memerlukan token
|
||||||
|
|
||||||
|
export async function getUsers() {
|
||||||
|
return await httpGetInterceptor("/users");
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getUserById(id: string | number) {
|
||||||
|
return await httpGetInterceptor(`/users/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createUser(data: any) {
|
||||||
|
return await httpPostInterceptor("/users", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateUser(id: string | number, data: any) {
|
||||||
|
return await httpPutInterceptor(`/users/${id}`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteUser(id: string | number) {
|
||||||
|
return await httpDeleteInterceptor(`/users/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -42,3 +42,10 @@ export async function deleteProduct(id: string) {
|
||||||
};
|
};
|
||||||
return await httpDeleteInterceptor(`products/${id}`, headers);
|
return await httpDeleteInterceptor(`products/${id}`, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function approveProduct(id: string | number) {
|
||||||
|
const headers = {
|
||||||
|
"content-type": "application/json",
|
||||||
|
};
|
||||||
|
return await httpPutInterceptor(`/products/${id}/approve`, {}, headers);
|
||||||
|
}
|
||||||
|
|
@ -37,3 +37,10 @@ export async function deletePromotion(id: string) {
|
||||||
};
|
};
|
||||||
return await httpDeleteInterceptor(`promotions/${id}`, headers);
|
return await httpDeleteInterceptor(`promotions/${id}`, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function approvePromotion(id: string | number) {
|
||||||
|
const headers = {
|
||||||
|
"content-type": "application/json",
|
||||||
|
};
|
||||||
|
return await httpPutInterceptor(`/promotions/${id}/approve`, {}, headers);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue