fix: table agent,promo, form CRUD agent,

This commit is contained in:
Anang Yusman 2026-01-22 14:30:45 +08:00
parent 52a5d8f9eb
commit 274c41bf88
12 changed files with 329 additions and 244 deletions

View File

@ -126,193 +126,221 @@ export function DialogDetailGaleri({ open, onClose, data }: any) {
return ( return (
<> <>
<div> <Dialog open={open} onOpenChange={onClose}>
<Dialog open={open} onOpenChange={onClose}> <DialogContent className=" rounded-2xl p-0 overflow-hidden">
<DialogContent className=" rounded-2xl p-0 overflow-hidden"> {/* Header */}
{/* Header */} <div className="bg-[#1F6779] text-white px-6 py-4">
<div className="bg-[#1F6779] text-white px-6 py-4"> <DialogTitle className="text-white">Detail Galeri</DialogTitle>
<DialogTitle className="text-white">Detail Galeri</DialogTitle> <div className="flex items-center gap-2 mt-3">
<span
className={`text-xs font-medium px-3 py-1 rounded-full ${
data?.status_id === 1
? "bg-yellow-100 text-yellow-800"
: data?.status_id === 2
? "bg-green-100 text-green-800"
: data?.status_id === 3
? "bg-red-100 text-red-800"
: "bg-gray-100 text-gray-800"
}`}
>
{data?.status_id === 1
? "Menunggu"
: data?.status_id === 2
? "Disetujui"
: data?.status_id === 3
? "Ditolak"
: "Tidak Diketahui"}
</span>
<span className="bg-white text-[#0F6C75] text-xs font-medium px-3 py-1 rounded-full">
Galeri
</span>
{/* <span className="bg-white/20 text-white text-xs px-2 py-[2px] rounded-full">
{promo.position}
</span> */}
</div>
</div>
<div className=" py-3">
{/* Images List */}
<div className="mx-2">
<h2 className="text-2xl font-semibold text-black">
{data.title}
</h2>
<div className="my-3">
<p className="font-medium text-sm text-black">Deskripsi</p>
<p className="text-gray-800">{data.description}</p>
</div>
<div className="grid grid-cols-3 gap-4">
{images.length === 0 && (
<p className="text-gray-500 col-span-3 text-center">
Tidak ada gambar.
</p>
)}
{images.map((img) => (
<div
key={img.id}
className="relative h-32 w-full cursor-pointer group"
onClick={() => openFile(img.image_url)}
>
<Image
src={img.image_url}
alt={img.title}
fill
className="object-cover rounded-lg"
/>
<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 text-white flex items-center justify-center text-sm transition">
Lihat File
</div>
</div>
))}
</div>
</div> </div>
<div className=" py-3"> {/* Title */}
{/* Images List */}
<div className="mx-2"> {/* Deskripsi */}
<h2 className="text-2xl font-semibold text-black">
{data.title} {/* Tanggal Upload */}
</h2> <div className="mx-2">
<div className="my-3"> <p className="font-medium text-sm text-gray-700">
<p className="font-medium text-sm text-black">Deskripsi</p> Tanggal Upload
<p className="text-gray-800">{data.description}</p> </p>
</div> <p className="text-gray-600">
<div className="grid grid-cols-3 gap-4"> {new Date(data.created_at).toLocaleDateString("id-ID")}
{images.length === 0 && ( </p>
<p className="text-gray-500 col-span-3 text-center"> </div>
Tidak ada gambar.
{/* Timeline */}
<div className="mx-2">
<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>
)} <p className="text-sm text-gray-500">
{convertDateFormat(data?.created_at)} WIB
{images.map((img) => ( </p>
<div </div>
key={img.id}
className="relative h-32 w-full cursor-pointer group"
onClick={() => openFile(img.image_url)}
>
<Image
src={img.image_url}
alt={img.title}
fill
className="object-cover rounded-lg"
/>
<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 text-white flex items-center justify-center text-sm transition">
Lihat File
</div>
</div>
))}
</div> </div>
</div>
{/* Title */} <div className="flex gap-3">
<div
{/* Deskripsi */} className={`w-6 h-6 rounded-full flex items-center justify-center ${
data?.status_id === 1
{/* Tanggal Upload */} ? "bg-yellow-100"
<div className="mx-2"> : data?.status_id === 2
<p className="font-medium text-sm text-gray-700"> ? "bg-green-100"
Tanggal Upload : "bg-red-100"
</p> }`}
<p className="text-gray-600"> >
{new Date(data.created_at).toLocaleDateString("id-ID")} {data?.status_id === 1 ? (
</p> <Clock className="w-4 h-4 text-yellow-700" />
</div> ) : data?.status_id === 2 ? (
{/* Timeline */}
<div className="mx-2">
<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" /> <Check className="w-4 h-4 text-green-600" />
</div> ) : (
<div> <X className="w-4 h-4 text-red-700" />
<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>
<div <p className="font-medium text-gray-800">
className={`w-6 h-6 rounded-full flex items-center justify-center ${ {data?.status_id === 1
data?.status_id === 1 ? "Menunggu disetujui oleh Approver"
? "bg-yellow-100" : data?.status_id === 2
: data?.status_id === 2 ? "Disetujui oleh Approver"
? "bg-green-100" : "Ditolak oleh Approver"}
: "bg-red-100" </p>
}`}
<p className="text-sm text-gray-500">
{convertDateFormat(data?.updated_at)} WIB
</p>
</div>
</div>
<div className="border rounded-lg px-3 py-3">
<p>Comment : </p>
<div className="flex flex-row justify-between">
<button
onClick={handleOpenApproverHistory}
className="text-sm text-blue-600 hover:underline mt-2"
> >
{data?.status_id === 1 ? ( View Approver History
<Clock className="w-4 h-4 text-yellow-700" /> </button>
) : data?.status_id === 2 ? ( <p>Jaecoo - Approver | 10/11/2026</p>
<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 className="border rounded-lg px-3 py-3">
<p>Comment : </p>
<div className="flex flex-row justify-between">
<button
onClick={handleOpenApproverHistory}
className="text-sm text-blue-600 hover:underline mt-2"
>
View Approver History
</button>
<p>Jaecoo - Approver | 10/11/2026</p>
</div>
</div> </div>
</div> </div>
</div> </div>
{userRoleId !== "2" && data && ( </div>
<div className="flex justify-between items-center gap-3 px-6 py-4 border-t bg-[#F2F7FA]"> {userRoleId !== "2" && data && (
{data.status_id === 1 ? ( <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-[150]"
variant="destructive"
onClick={(e) => {
e.stopPropagation();
handleRejectGalery(data.id);
}}
>
Reject
</Button>
{userRoleId === "1" && (
<Button
// variant="ghost"
size="sm"
className="bg-green-600 hover:bg-green-700 text-white w-[150]"
onClick={(e) => {
e.stopPropagation();
handleApproveGalery(data.id);
}}
>
<CheckCheck className="w-4 h-4 mr-1" />
Approve
</Button>
)}
</>
) : (
<Button <Button
variant="secondary" variant="secondary"
className="mx-auto" className="bg-blue-200 hover:bg-blue-400"
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
setOpenViewDialog(false); setOpenCommentModal(true);
}} }}
> >
Tutup Beri Tanggapan
</Button> </Button>
)}
</div>
)}
</div>
{/* <DialogFooter className="px-6 pb-6"> <Button
className=" w-[150]"
variant="destructive"
onClick={(e) => {
e.stopPropagation();
handleRejectGalery(data.id);
}}
>
Reject
</Button>
{userRoleId === "1" && (
<Button
// variant="ghost"
size="sm"
className="bg-green-600 hover:bg-green-700 text-white w-[150]"
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">
<button <button
onClick={onClose} onClick={onClose}
className="bg-gray-300 text-gray-700 px-6 py-2 rounded-lg" className="bg-gray-300 text-gray-700 px-6 py-2 rounded-lg"
@ -320,9 +348,8 @@ export function DialogDetailGaleri({ open, onClose, data }: any) {
Tutup Tutup
</button> </button>
</DialogFooter> */} </DialogFooter> */}
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</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"

View File

@ -27,6 +27,7 @@ import Cookies from "js-cookie";
import { error, loading, success } from "@/config/swal"; import { error, loading, success } from "@/config/swal";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import promo from "../landing-page/promo";
type PromoDetailDialogProps = { type PromoDetailDialogProps = {
promoId: number | null; promoId: number | null;
@ -187,17 +188,39 @@ export default function PromoDetailDialog({
<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>
<DialogTitle className="text-white text-xl font-semibold"> <DialogTitle className="text-white text-xl font-semibold">
Detail Promo Detail Promoaa
</DialogTitle> </DialogTitle>
</DialogHeader> </DialogHeader>
{/* STATUS BADGE */} <div className="flex items-center gap-2 mt-3">
{promo && ( <span
<div className="mt-2 bg-white/20 text-white px-4 py-[3px] rounded-full text-xs inline-flex items-center gap-2"> className={`text-xs font-medium px-3 py-1 rounded-full ${
<span className="w-2 h-2 rounded-full bg-lime-300"></span> promo?.status_id === 1
{promo.status} ? "bg-yellow-100 text-yellow-800"
</div> : promo?.status_id === 2
)} ? "bg-green-100 text-green-800"
: promo?.status_id === 3
? "bg-red-100 text-red-800"
: "bg-gray-100 text-gray-800"
}`}
>
{promo?.status_id === 1
? "Menunggu"
: promo?.status_id === 2
? "Disetujui"
: promo?.status_id === 3
? "Ditolak"
: "Tidak Diketahui"}
</span>
<span className="bg-white text-[#0F6C75] text-xs font-medium px-3 py-1 rounded-full">
Promo
</span>
{/* <span className="bg-white/20 text-white text-xs px-2 py-[2px] rounded-full">
{promo.position}
</span> */}
</div>
</div> </div>
{/* BODY */} {/* BODY */}

View File

@ -22,9 +22,10 @@ import { UploadCloud } from "lucide-react";
type AgentFormValues = { type AgentFormValues = {
fullName: string; fullName: string;
job_title: string;
position: string; position: string;
phone: string; phone: string;
roles: string[]; agent_type: string[];
profileImage: File | null; profileImage: File | null;
}; };
@ -40,9 +41,10 @@ export default function AddAgentForm() {
const form = useForm<AgentFormValues>({ const form = useForm<AgentFormValues>({
defaultValues: { defaultValues: {
fullName: "", fullName: "",
job_title: "",
position: "", position: "",
phone: "", phone: "",
roles: [], agent_type: [],
profileImage: null, profileImage: null,
}, },
}); });
@ -60,13 +62,13 @@ export default function AddAgentForm() {
const onSubmit = async (data: AgentFormValues) => { const onSubmit = async (data: AgentFormValues) => {
try { try {
const formData = new FormData(); const formData = new FormData();
formData.append("name", data.fullName); formData.append("name", data.fullName);
formData.append("job_title", data.position); formData.append("job_title", data.job_title);
formData.append("phone", data.phone); formData.append("phone", data.phone);
data.roles.forEach((role) => { // ✅ FIX UTAMA
formData.append("agent_type[]", role); formData.append("agent_type", JSON.stringify(data.agent_type));
});
if (file) { if (file) {
formData.append("file", file); formData.append("file", file);
@ -122,7 +124,7 @@ export default function AddAgentForm() {
<FormField <FormField
control={form.control} control={form.control}
name="position" name="job_title"
rules={{ required: true }} rules={{ required: true }}
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
@ -169,7 +171,7 @@ export default function AddAgentForm() {
<FormField <FormField
key={role} key={role}
control={form.control} control={form.control}
name="roles" name="agent_type"
render={({ field }) => { render={({ field }) => {
const selected = field.value || []; const selected = field.value || [];
return ( return (

View File

@ -218,7 +218,16 @@ export default function DetailAgentForm(props: { isDetail: boolean }) {
<div className="flex gap-6"> <div className="flex gap-6">
{AGENT_TYPES.map((item) => ( {AGENT_TYPES.map((item) => (
<div key={item.key} className="flex items-center gap-2"> <div key={item.key} className="flex items-center gap-2">
<Checkbox checked={data.job_title === item.key} disabled /> <Checkbox
checked={
Array.isArray(data.agent_type) &&
data.agent_type
.map((v: string) => v.toLowerCase())
.includes(item.label.toLowerCase())
}
disabled
/>
<span>{item.label}</span> <span>{item.label}</span>
</div> </div>
))} ))}
@ -230,7 +239,7 @@ export default function DetailAgentForm(props: { isDetail: boolean }) {
<Label className="mb-2 block">Foto Profile</Label> <Label className="mb-2 block">Foto Profile</Label>
<div className="w-24 h-24 rounded-lg overflow-hidden border"> <div className="w-24 h-24 rounded-lg overflow-hidden border">
<Image <Image
src={data.profile_picture_url} src={data?.profile_picture_url}
alt="Profile" alt="Profile"
width={96} width={96}
height={96} height={96}

View File

@ -20,12 +20,13 @@ import { X } from "lucide-react";
type AgentFormValues = { type AgentFormValues = {
fullName: string; fullName: string;
job_title: string;
position: string; position: string;
phone: string; phone: string;
roles: string[]; roles: string[];
}; };
const AGENT_TYPES = ["after-Sales", "sales", "spv", "branch_manager"]; const AGENT_TYPES = ["After Sales", "Sales", "Spv", "Branch Manager"];
export default function UpdateAgentForm({ id }: { id: number }) { export default function UpdateAgentForm({ id }: { id: number }) {
const router = useRouter(); const router = useRouter();
@ -57,9 +58,9 @@ export default function UpdateAgentForm({ id }: { id: number }) {
form.reset({ form.reset({
fullName: agent.name, fullName: agent.name,
position: agent.job_title, job_title: agent.job_title,
phone: agent.phone, phone: agent.phone,
roles: agent.job_title ? [agent.job_title] : [], roles: Array.isArray(agent.agent_type) ? agent.agent_type : [],
}); });
// ✅ FOTO DARI API // ✅ FOTO DARI API
@ -92,14 +93,23 @@ export default function UpdateAgentForm({ id }: { id: number }) {
const onSubmit = async (data: AgentFormValues) => { const onSubmit = async (data: AgentFormValues) => {
try { try {
const formData = new FormData(); const formData = new FormData();
formData.append("name", data.fullName); formData.append("name", data.fullName);
formData.append("job_title", data.roles[0]); // single role formData.append("job_title", data.job_title);
formData.append("phone", data.phone); formData.append("phone", data.phone);
// ✅ MULTI agent_type
formData.append("agent_type", JSON.stringify(data.roles));
if (file) { if (file) {
formData.append("file", file); formData.append("file", file);
} }
// DEBUG
for (const pair of formData.entries()) {
console.log(pair[0], pair[1]);
}
await updateAgent(id, formData); await updateAgent(id, formData);
MySwal.fire({ MySwal.fire({
@ -137,12 +147,12 @@ export default function UpdateAgentForm({ id }: { id: number }) {
<FormField <FormField
control={form.control} control={form.control}
name="position" name="job_title"
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel>Jabatan</FormLabel> <FormLabel>Jabatan</FormLabel>
<FormControl> <FormControl>
<Input {...field} readOnly /> <Input {...field} />
</FormControl> </FormControl>
</FormItem> </FormItem>
)} )}
@ -171,21 +181,27 @@ export default function UpdateAgentForm({ id }: { id: number }) {
key={role} key={role}
control={form.control} control={form.control}
name="roles" name="roles"
render={({ field }) => ( render={({ field }) => {
<FormItem className="flex items-center gap-2"> const selected = field.value || [];
<FormControl>
<Checkbox return (
checked={field.value?.includes(role)} <FormItem className="flex items-center gap-2">
onCheckedChange={(checked) => <FormControl>
field.onChange(checked ? [role] : []) <Checkbox
} checked={selected.includes(role)}
/> onCheckedChange={(checked) => {
</FormControl> const updated = checked
<span className="capitalize"> ? [...selected, role] // tambah
{role.replace("_", " ")} : selected.filter((r) => r !== role); // hapus
</span>
</FormItem> field.onChange(updated);
)} }}
/>
</FormControl>
<span>{role}</span>
</FormItem>
);
}}
/> />
))} ))}
</div> </div>

View File

@ -365,7 +365,7 @@ export default function DetailProductForm(props: { isDetail: boolean }) {
<Card className="w-full border-none shadow-md"> <Card className="w-full border-none shadow-md">
<CardHeader> <CardHeader>
<CardTitle className="text-xl font-bold text-teal-900"> <CardTitle className="text-xl font-bold text-teal-900">
Edit Produk Detail Produk
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>

View File

@ -11,7 +11,15 @@ export type OptionProps = {
active?: boolean; active?: boolean;
}; };
const Option = ({ Icon, title, selected, setSelected, open, notifs, active }: OptionProps) => { const Option = ({
Icon,
title,
selected,
setSelected,
open,
notifs,
active,
}: OptionProps) => {
const [hovered, setHovered] = useState(false); const [hovered, setHovered] = useState(false);
const isActive = active ?? selected === title; const isActive = active ?? selected === title;
@ -23,7 +31,7 @@ const Option = ({ Icon, title, selected, setSelected, open, notifs, active }: Op
onMouseLeave={() => setHovered(false)} onMouseLeave={() => setHovered(false)}
className={`relative flex h-12 w-full px-3 items-center rounded-xl transition-all duration-200 cursor-pointer group ${ className={`relative flex h-12 w-full px-3 items-center rounded-xl transition-all duration-200 cursor-pointer group ${
isActive isActive
? "bg-gradient-to-r from-emerald-500 to-green-500 text-white shadow-lg shadow-emerald-500/25" ? "bg-gradient-to-r from-[#1F6779] to-[#1F6779] text-white shadow-lg shadow-emerald-500/25"
: "text-slate-600 hover:bg-gradient-to-r hover:from-slate-100 hover:to-slate-200/50 hover:text-slate-800" : "text-slate-600 hover:bg-gradient-to-r hover:from-slate-100 hover:to-slate-200/50 hover:text-slate-800"
}`} }`}
whileHover={{ scale: 1.02 }} whileHover={{ scale: 1.02 }}
@ -46,11 +54,13 @@ const Option = ({ Icon, title, selected, setSelected, open, notifs, active }: Op
open ? "w-12" : "w-full" open ? "w-12" : "w-full"
}`} }`}
> >
<div className={`text-lg transition-all duration-200 ${ <div
isActive className={`text-lg transition-all duration-200 ${
? "text-white" isActive
: "text-slate-500 group-hover:text-slate-700" ? "text-white"
}`}> : "text-slate-500 group-hover:text-slate-700"
}`}
>
<Icon /> <Icon />
</div> </div>
</motion.div> </motion.div>
@ -93,9 +103,7 @@ const Option = ({ Icon, title, selected, setSelected, open, notifs, active }: Op
animate={{ opacity: 1, scale: 1 }} animate={{ opacity: 1, scale: 1 }}
transition={{ delay: 0.3, type: "spring" }} transition={{ delay: 0.3, type: "spring" }}
className={`absolute right-3 top-1/2 -translate-y-1/2 size-5 rounded-full text-xs font-semibold flex items-center justify-center ${ className={`absolute right-3 top-1/2 -translate-y-1/2 size-5 rounded-full text-xs font-semibold flex items-center justify-center ${
isActive isActive ? "bg-white text-emerald-500" : "bg-red-500 text-white"
? "bg-white text-emerald-500"
: "bg-red-500 text-white"
}`} }`}
> >
{notifs} {notifs}

View File

@ -242,9 +242,9 @@ const SidebarContent = ({
> >
<p className="text-lg font-bold bg-gradient-to-r from-slate-800 to-slate-600 bg-clip-text text-white dark:text-white"> <p className="text-lg font-bold bg-gradient-to-r from-slate-800 to-slate-600 bg-clip-text text-white dark:text-white">
JAECOO{" "} JAECOO{" "}
<span className="text-lg font-normal"> {/* <span className="text-lg font-normal">
{userRoleId != null ? roleLabel[userRoleId] : ""} {userRoleId != null ? roleLabel[userRoleId] : ""}
</span> </span> */}
</p> </p>
{/* <span className="text-xs text-slate-500">Admin Panel</span> */} {/* <span className="text-xs text-slate-500">Admin Panel</span> */}
</motion.div> </motion.div>

View File

@ -381,7 +381,7 @@ export default function AgentTable() {
<div className="w-full overflow-x-auto rounded-2xl shadow-sm border border-gray-200"> <div className="w-full overflow-x-auto rounded-2xl shadow-sm border border-gray-200">
{/* Header */} {/* Header */}
<div className="bg-[#0F6C75] text-white text-lg rounded-t-sm px-6 py-3"> <div className="bg-[#0F6C75] text-white text-lg rounded-t-sm px-6 py-3">
Daftar Product Daftar Agen
</div> </div>
{/* Table */} {/* Table */}

View File

@ -104,14 +104,14 @@ export default function CostumerServiceTable() {
endDate: null, endDate: null,
}); });
const [userLevelId, setUserLevelId] = useState<string | null>(null); const [userRoleId, setUserRoleId] = useState<string | null>(null);
const router = useRouter(); const router = useRouter();
// 🔹 Ambil userlevelId dari cookies // 🔹 Ambil userlevelId dari cookies
useEffect(() => { useEffect(() => {
const ulne = Cookies.get("ulne"); // contoh: "3" const urie = Cookies.get("urie"); // contoh: "3"
setUserLevelId(ulne ?? null); setUserRoleId(urie ?? null);
}, []); }, []);
useEffect(() => { useEffect(() => {
@ -354,7 +354,7 @@ export default function CostumerServiceTable() {
Sales Sales
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
{userLevelId !== "3" && ( {userRoleId !== "1" && (
<Link href={"/admin/product/create"}> <Link href={"/admin/product/create"}>
<Button className="bg-[#1F6779] text-white w-full lg:w-fit hover:bg-[#1a9bb5] flex items-center gap-2"> <Button className="bg-[#1F6779] text-white w-full lg:w-fit hover:bg-[#1a9bb5] flex items-center gap-2">
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />

View File

@ -383,7 +383,7 @@ export default function PromotionTable() {
<div className="w-full overflow-x-auto rounded-2xl shadow-sm border border-gray-200"> <div className="w-full overflow-x-auto rounded-2xl shadow-sm border border-gray-200">
{/* Header */} {/* Header */}
<div className="bg-[#0F6C75] text-white text-lg rounded-t-sm px-6 py-3"> <div className="bg-[#0F6C75] text-white text-lg rounded-t-sm px-6 py-3">
Daftar Product Daftar Promo
</div> </div>
{/* Table */} {/* Table */}

View File

@ -104,14 +104,14 @@ export default function ServicesTable() {
endDate: null, endDate: null,
}); });
const [userLevelId, setUserLevelId] = useState<string | null>(null); const [userRoleId, setUserRoleId] = useState<string | null>(null);
const router = useRouter(); const router = useRouter();
// 🔹 Ambil userlevelId dari cookies // 🔹 Ambil userlevelId dari cookies
useEffect(() => { useEffect(() => {
const ulne = Cookies.get("ulne"); // contoh: "3" const urie = Cookies.get("urie"); // contoh: "3"
setUserLevelId(ulne ?? null); setUserRoleId(urie ?? null);
}, []); }, []);
useEffect(() => { useEffect(() => {
@ -354,7 +354,7 @@ export default function ServicesTable() {
After Sales After Sales
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
{userLevelId !== "3" && ( {userRoleId !== "1" && (
<Link href={"/admin/product/create"}> <Link href={"/admin/product/create"}>
<Button className="bg-[#1F6779] text-white w-full lg:w-fit hover:bg-[#1a9bb5] flex items-center gap-2"> <Button className="bg-[#1F6779] text-white w-full lg:w-fit hover:bg-[#1a9bb5] flex items-center gap-2">
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />