This commit is contained in:
hanif salafi 2025-08-07 10:28:42 +07:00
commit 166c3c8143
8 changed files with 263 additions and 124 deletions

View File

@ -2,7 +2,7 @@ import * as React from "react";
import { ColumnDef } from "@tanstack/react-table"; import { ColumnDef } from "@tanstack/react-table";
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react"; import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn, getCookiesDecrypt } from "@/lib/utils";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@ -78,7 +78,7 @@ const columns: ColumnDef<any>[] = [
enableHiding: false, enableHiding: false,
cell: ({ row }) => { cell: ({ row }) => {
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const levelNumber = getCookiesDecrypt("ulne");
async function doDelete(id: any) { async function doDelete(id: any) {
// loading(); // loading();
const data = { const data = {
@ -132,7 +132,7 @@ const columns: ColumnDef<any>[] = [
<MoreVertical className="h-4 w-4 text-default-800" /> <MoreVertical className="h-4 w-4 text-default-800" />
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end"> {/* <DropdownMenuContent className="p-0" align="end">
<Link href={`/admin/settings/iklan/detail/${row.original.id}`}> <Link href={`/admin/settings/iklan/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none"> <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" /> <Eye className="w-4 h-4 me-1.5" />
@ -152,6 +152,33 @@ const columns: ColumnDef<any>[] = [
<Trash2 className="w-4 h-4 me-1.5" /> <Trash2 className="w-4 h-4 me-1.5" />
Delete Delete
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuContent> */}
<DropdownMenuContent className="p-0" align="end">
<Link href={`/admin/settings/iklan/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
{levelNumber === "1" && (
<>
<Link href={`/admin/settings/iklan/update/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => handleDeleteAdvertisements(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</>
)}
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
); );

View File

@ -39,7 +39,7 @@ import {
UploadIcon, UploadIcon,
UserIcon, UserIcon,
} from "lucide-react"; } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn, getCookiesDecrypt } from "@/lib/utils";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@ -94,6 +94,9 @@ const AdvertisementsList = () => {
const [statusFilter, setStatusFilter] = React.useState<number[]>([]); const [statusFilter, setStatusFilter] = React.useState<number[]>([]);
const [page, setPage] = React.useState(1); const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1);
const roleId = getCookiesDecrypt("urie");
const levelNumber = getCookiesDecrypt("ulne");
const userLevelId = getCookiesDecrypt("ulie");
const table = useReactTable({ const table = useReactTable({
data: dataTable, data: dataTable,
columns, columns,
@ -203,10 +206,11 @@ const AdvertisementsList = () => {
return ( return (
<> <>
<div> <div>
{levelNumber === "1" && (
<div className="flex-none"> <div className="flex-none">
<Link href={"/admin/settings/iklan/create"}>
<Button <Button
disabled={dataTable.length == 4} disabled={dataTable.length == 4}
onClick={() => router.push("/admin/settings/iklan/create")}
color="primary" color="primary"
className="text-white" className="text-white"
size="md" size="md"
@ -214,12 +218,15 @@ const AdvertisementsList = () => {
<UploadIcon size={18} className="mr-2" /> <UploadIcon size={18} className="mr-2" />
Tambah Iklan Tambah Iklan
</Button> </Button>
</Link>
{dataTable.length == 4 && ( {dataTable.length == 4 && (
<p className="text-sm text-red-400 pt-1"> <p className="text-sm text-red-400 pt-1">
Jumlah Iklan Sudah Maksimal (4) Jumlah Iklan Sudah Maksimal (4)
</p> </p>
)} )}
</div> </div>
)}
{/* <TambahIklanModal /> */} {/* <TambahIklanModal /> */}
</div> </div>
<div className="flex justify-between "> <div className="flex justify-between ">

View File

@ -20,6 +20,7 @@ import { Link } from "@/components/navigation";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import withReactContent from "sweetalert2-react-content"; import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2"; import Swal from "sweetalert2";
import { useState } from "react";
const useTableColumns = () => { const useTableColumns = () => {
const t = useTranslations("Table"); const t = useTranslations("Table");
@ -37,7 +38,6 @@ const useTableColumns = () => {
onCheckedChange={(val) => table.toggleAllPageRowsSelected(!!val)} onCheckedChange={(val) => table.toggleAllPageRowsSelected(!!val)}
aria-label="Pilih semua pada halaman ini" aria-label="Pilih semua pada halaman ini"
/> />
), ),
cell: ({ row }) => ( cell: ({ row }) => (
<Checkbox <Checkbox
@ -140,15 +140,23 @@ const useTableColumns = () => {
enableHiding: false, enableHiding: false,
cell: ({ row }) => { cell: ({ row }) => {
const isDisabled = row.original.isPublish; const isDisabled = row.original.isPublish;
const [open, setOpen] = useState(false);
const handleClick = (e: React.MouseEvent) => {
if (e.ctrlKey) {
console.log("Ctrl + Click detected");
}
// Paksa buka menu meskipun ctrl ditekan
setOpen(true);
};
return ( return (
<DropdownMenu> <DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger asChild disabled={isDisabled}> <DropdownMenuTrigger asChild disabled={isDisabled}>
<Button <Button
size="icon" size="icon"
className={`bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent ${ onClick={handleClick}
isDisabled ? "cursor-not-allowed opacity-50" : "" className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
}`}
disabled={isDisabled}
> >
<span className="sr-only">Open menu</span> <span className="sr-only">Open menu</span>
<MoreVertical className="h-4 w-4 text-default-800" /> <MoreVertical className="h-4 w-4 text-default-800" />
@ -159,7 +167,7 @@ const useTableColumns = () => {
href={`/contributor/content/spit/convert/${row.original.contentId}`} href={`/contributor/content/spit/convert/${row.original.contentId}`}
> >
<DropdownMenuItem <DropdownMenuItem
className={`p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none ${ className={`cursor-pointer p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none ${
isDisabled ? "cursor-not-allowed opacity-50" : "" isDisabled ? "cursor-not-allowed opacity-50" : ""
}`} }`}
disabled={isDisabled} disabled={isDisabled}

View File

@ -2,7 +2,7 @@ import * as React from "react";
import { ColumnDef } from "@tanstack/react-table"; import { ColumnDef } from "@tanstack/react-table";
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react"; import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn, getCookiesDecrypt } from "@/lib/utils";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@ -206,6 +206,15 @@ const useTableColumns = () => {
cell: ({ row }) => { cell: ({ row }) => {
const router = useRouter(); const router = useRouter();
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const roleId = getCookiesDecrypt("urie");
const levelNumber = getCookiesDecrypt("ulne");
const userLevelId = getCookiesDecrypt("ulie");
const contentLevelNumber =
row.original.createdBy?.userLevel?.levelNumber;
const isSameLevelOrLower =
levelNumber &&
contentLevelNumber &&
+levelNumber <= +contentLevelNumber;
async function deleteProcess(id: any) { async function deleteProcess(id: any) {
loading(); loading();
@ -268,7 +277,24 @@ const useTableColumns = () => {
</DropdownMenuItem> </DropdownMenuItem>
</Link> </Link>
{!isDone && ( {/* {!isDone && (
<>
<Link href={`/contributor/task/update/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem
onClick={() => TaskDelete(row.original.id)}
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</>
)} */}
{!isDone && isSameLevelOrLower && (
<> <>
<Link href={`/contributor/task/update/${row.original.id}`}> <Link href={`/contributor/task/update/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none"> <DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">

View File

@ -41,6 +41,7 @@ import FileUploader from "../shared/file-uploader";
import { Icon } from "@/components/ui/icon"; import { Icon } from "@/components/ui/icon";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "@/i18n/routing";
const calendarSchema = z.object({ const calendarSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }), title: z.string().min(1, { message: "Judul diperlukan" }),
@ -64,6 +65,7 @@ interface Detail {
export function TambahIklanDetail() { export function TambahIklanDetail() {
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const router = useRouter();
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const t = useTranslations("Schedule"); const t = useTranslations("Schedule");
const { id } = useParams() as { id: string }; const { id } = useParams() as { id: string };
@ -376,6 +378,7 @@ export function TambahIklanDetail() {
].map(({ label, value }) => ( ].map(({ label, value }) => (
<label key={value} className="flex items-center gap-2"> <label key={value} className="flex items-center gap-2">
<Checkbox <Checkbox
disabled
id={value} id={value}
checked={selectedPlacement === value} checked={selectedPlacement === value}
onCheckedChange={() => handlePlacementSelect(value)} onCheckedChange={() => handlePlacementSelect(value)}
@ -506,6 +509,7 @@ export function TambahIklanDetail() {
name="title" name="title"
render={({ field }) => ( render={({ field }) => (
<Input <Input
readOnly
size={"md"} size={"md"}
type="text" type="text"
value={detail?.title} value={detail?.title}
@ -540,6 +544,7 @@ export function TambahIklanDetail() {
name="description" name="description"
render={({ field }) => ( render={({ field }) => (
<Textarea <Textarea
readOnly
rows={3} rows={3}
value={detail?.description} value={detail?.description}
onChange={field.onChange} onChange={field.onChange}
@ -554,12 +559,22 @@ export function TambahIklanDetail() {
)} )}
</div> </div>
<div className="text-right"> {/* <div className="text-right">
<Link href={"admin/settings/iklan"}> <Link href={"admin/settings/iklan"}>
<Button type="button" variant={"outline"} color="primary"> <Button type="button" variant={"outline"} color="primary">
Kembali Kembali
</Button> </Button>
</Link> </Link>
</div> */}
<div className="text-right">
<Button
type="button"
variant="outline"
color="primary"
onClick={() => router.back()}
>
Kembali
</Button>
</div> </div>
</div> </div>
</form> </form>

View File

@ -38,6 +38,7 @@ import FileUploader from "../shared/file-uploader";
import { Icon } from "@/components/ui/icon"; import { Icon } from "@/components/ui/icon";
import { close } from "@/config/swal"; import { close } from "@/config/swal";
import { listDataAdvertisements } from "@/service/broadcast/broadcast"; import { listDataAdvertisements } from "@/service/broadcast/broadcast";
import { useRouter } from "@/i18n/routing";
const calendarSchema = z.object({ const calendarSchema = z.object({
title: z.string().min(1, { message: "Judul diperlukan" }), title: z.string().min(1, { message: "Judul diperlukan" }),
@ -54,6 +55,7 @@ interface FileUploaded {
} }
export function TambahIklanModal() { export function TambahIklanModal() {
const router = useRouter();
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const MySwal = withReactContent(Swal); const MySwal = withReactContent(Swal);
const t = useTranslations("Schedule"); const t = useTranslations("Schedule");
@ -222,7 +224,7 @@ export function TambahIklanModal() {
text: "Iklan berhasil ditambahkan.", text: "Iklan berhasil ditambahkan.",
confirmButtonText: "OK", confirmButtonText: "OK",
}).then(() => { }).then(() => {
window.location.reload(); router.push("/admin/settings/iklan");
}); });
Cookies.set("scheduleId", response?.data?.data.id, { Cookies.set("scheduleId", response?.data?.data.id, {

View File

@ -250,34 +250,38 @@ const Navbar = () => {
</PopoverTrigger> </PopoverTrigger>
<PopoverContent className="flex flex-col gap-2 w-fit px-6 py-4 rounded-md shadow-md bg-white dark:bg-black"> <PopoverContent className="flex flex-col gap-2 w-fit px-6 py-4 rounded-md shadow-md bg-white dark:bg-black">
<button <Link
onClick={() => router.push(prefixPath + "/image/filter")} href={prefixPath + "/image/filter"}
// onClick={() => router.push(prefixPath + "/image/filter")}
className="flex items-center text-slate-600 dark:text-white hover:text-[#bb3523]" className="flex items-center text-slate-600 dark:text-white hover:text-[#bb3523]"
> >
<FiImage className="mr-2" /> <FiImage className="mr-2" />
{t("image", { defaultValue: "Image" })} {t("image", { defaultValue: "Image" })}
</button> </Link>
<button <Link
onClick={() => router.push(prefixPath + "/video/filter")} href={prefixPath + "/video/filter"}
// onClick={() => router.push(prefixPath + "/video/filter")}
className="flex items-center text-slate-600 dark:text-white hover:text-[#bb3523]" className="flex items-center text-slate-600 dark:text-white hover:text-[#bb3523]"
> >
<FiYoutube className="mr-2" /> <FiYoutube className="mr-2" />
{t("video", { defaultValue: "Video" })} {t("video", { defaultValue: "Video" })}
</button> </Link>
<button <Link
onClick={() => router.push(prefixPath + "/document/filter")} href={prefixPath + "/document/filter"}
// onClick={() => router.push(prefixPath + "/document/filter")}
className="flex items-center text-slate-600 dark:text-white hover:text-[#bb3523]" className="flex items-center text-slate-600 dark:text-white hover:text-[#bb3523]"
> >
<FiFile className="mr-2" /> <FiFile className="mr-2" />
{t("text", { defaultValue: "Text" })} {t("text", { defaultValue: "Text" })}
</button> </Link>
<button <Link
onClick={() => router.push(prefixPath + "/audio/filter")} href={prefixPath + "/audio/filter"}
// onClick={() => router.push(prefixPath + "/audio/filter")}
className="flex items-center text-slate-600 dark:text-white hover:text-[#bb3523]" className="flex items-center text-slate-600 dark:text-white hover:text-[#bb3523]"
> >
<FiMusic className="mr-2" /> <FiMusic className="mr-2" />
{t("audio", { defaultValue: "Audio" })} {t("audio", { defaultValue: "Audio" })}
</button> </Link>
</PopoverContent> </PopoverContent>
</Popover> </Popover>
@ -399,7 +403,7 @@ const Navbar = () => {
<ThemeSwitcher /> <ThemeSwitcher />
</div> </div>
<div className="hidden custom-lg-button:relative text-gray-600 dark:text-white "> <div className=" custom-lg-button:relative text-gray-600 dark:text-white ">
{/* <input {/* <input
value={onSearch} value={onSearch}
onChange={(e) => setOnSearch(e.target.value)} onChange={(e) => setOnSearch(e.target.value)}

View File

@ -128,7 +128,10 @@ const NewContent = (props: { group: string; type: string }) => {
<h2 className="flex items-center text-lg md:text-xl font-bold text-[#bb3523] border-b-2 border-[#bb3523] uppercase"> <h2 className="flex items-center text-lg md:text-xl font-bold text-[#bb3523] border-b-2 border-[#bb3523] uppercase">
{pathname?.split("/")[1] == "in" ? ( {pathname?.split("/")[1] == "in" ? (
<> <>
<span className="text-[#bb3523] ">{t("content", { defaultValue: "Content" })}</span>&nbsp; <span className="text-[#bb3523] ">
{t("content", { defaultValue: "Content" })}
</span>
&nbsp;
{props.type == "popular" {props.type == "popular"
? "Terpopuler" ? "Terpopuler"
: props.type == "latest" : props.type == "latest"
@ -153,10 +156,22 @@ const NewContent = (props: { group: string; type: string }) => {
<Tabs value={selectedTab} onValueChange={setSelectedTab}> <Tabs value={selectedTab} onValueChange={setSelectedTab}>
<TabsList className="flex gap-2 bg-transparent p-0"> <TabsList className="flex gap-2 bg-transparent p-0">
{[ {[
{ label: t("image", { defaultValue: "Image" }), value: "image" }, {
{ label: t("video", { defaultValue: "Video" }), value: "video" }, label: t("image", { defaultValue: "Image" }),
{ label: t("text", { defaultValue: "Text" }), value: "document" }, value: "image",
{ label: t("audio", { defaultValue: "Audio" }), value: "audio" }, },
{
label: t("video", { defaultValue: "Video" }),
value: "video",
},
{
label: t("text", { defaultValue: "Text" }),
value: "document",
},
{
label: t("audio", { defaultValue: "Audio" }),
value: "audio",
},
].map((tab) => ( ].map((tab) => (
<TabsTrigger <TabsTrigger
key={tab.value} key={tab.value}
@ -194,12 +209,12 @@ const NewContent = (props: { group: string; type: string }) => {
className="md:basis-1/2 lg:basis-1/3" className="md:basis-1/2 lg:basis-1/3"
> >
<div <div
onClick={() => // onClick={() =>
router.push( // router.push(
prefixPath + `/image/detail/${image?.slug}` // prefixPath + `/image/detail/${image?.slug}`
) // )
} // }
className="cursor-pointer relative group overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300" className="relative group overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300"
> >
{/* Image with motion effect */} {/* Image with motion effect */}
<motion.div <motion.div
@ -207,6 +222,12 @@ const NewContent = (props: { group: string; type: string }) => {
whileHover={{ scale: 0.95 }} whileHover={{ scale: 0.95 }}
transition={{ duration: 0.3 }} transition={{ duration: 0.3 }}
> >
<Link
href={
prefixPath + `/image/detail/${image?.slug}`
}
>
{" "}
<Image <Image
priority={true} priority={true}
placeholder={`data:image/svg+xml;base64,${toBase64( placeholder={`data:image/svg+xml;base64,${toBase64(
@ -218,6 +239,7 @@ const NewContent = (props: { group: string; type: string }) => {
src={image?.smallThumbnailLink} src={image?.smallThumbnailLink}
className="w-full h-full object-cover" className="w-full h-full object-cover"
/> />
</Link>
</motion.div> </motion.div>
{/* Badge category */} {/* Badge category */}
@ -248,15 +270,15 @@ const NewContent = (props: { group: string; type: string }) => {
{image?.categoryName?.toUpperCase() ?? {image?.categoryName?.toUpperCase() ??
"Giat Pimpinan"} "Giat Pimpinan"}
</p> </p>
<p <Link
className=" href={
text-sm lg:text-base font-semibold text-black dark:text-white prefixPath + `/image/detail/${image?.slug}`
line-clamp-4 /* LIMIT to 2 lines if plugin available */ }
/* or use min-h-[3rem] as fallback */
"
> >
<p className="text-sm lg:text-base font-semibold text-black dark:text-white line-clamp-4">
{image?.title} {image?.title}
</p> </p>
</Link>
</div> </div>
{/* Optional metadata area (uncomment if needed) */} {/* Optional metadata area (uncomment if needed) */}
{/* {/*
@ -271,7 +293,7 @@ const NewContent = (props: { group: string; type: string }) => {
))} ))}
</CarouselContent> </CarouselContent>
<div className="flex justify-center mt-4"> <div className="flex justify-center mt-2">
{Array.from({ length: count }).map((_, index) => ( {Array.from({ length: count }).map((_, index) => (
<button <button
key={index} key={index}
@ -308,13 +330,14 @@ const NewContent = (props: { group: string; type: string }) => {
key={audio?.id} key={audio?.id}
className="md:basis-1/2 lg:basis-1/3" className="md:basis-1/2 lg:basis-1/3"
> >
<div <Link
onClick={() => href={prefixPath + `/audio/detail/${audio?.slug}`}
router.push( // onClick={() =>
prefixPath + `/audio/detail/${audio?.slug}` // router.push(
) // prefixPath + `/audio/detail/${audio?.slug}`
} // )
className="cursor-pointer bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300 overflow-hidden" // }
className="bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300 overflow-hidden"
> >
{/* Icon Background */} {/* Icon Background */}
<div className="flex items-center justify-center bg-[#bb3523] w-full h-[170px] text-white"> <div className="flex items-center justify-center bg-[#bb3523] w-full h-[170px] text-white">
@ -347,7 +370,7 @@ const NewContent = (props: { group: string; type: string }) => {
<Icon icon="formkit:eye" width="15" height="15" /> {audio?.clickCount} <Icon icon="formkit:eye" width="15" height="15" /> {audio?.clickCount}
</p> */} </p> */}
</div> </div>
</div> </Link>
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>
@ -390,18 +413,23 @@ const NewContent = (props: { group: string; type: string }) => {
className="md:basis-1/2 lg:basis-1/3" className="md:basis-1/2 lg:basis-1/3"
> >
<div <div
onClick={() => // onClick={() =>
router.push( // router.push(
prefixPath + `/video/detail/${video?.slug}` // prefixPath + `/video/detail/${video?.slug}`
) // )
} // }
className="cursor-pointer relative group overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300" className="relative group overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500 rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300"
> >
{/* Image with motion effect */} {/* Image with motion effect */}
<motion.div <motion.div
className="w-full h-48 lg:h-60" className="w-full h-48 lg:h-60"
whileHover={{ scale: 0.95 }} whileHover={{ scale: 0.95 }}
transition={{ duration: 0.3 }} transition={{ duration: 0.3 }}
>
<Link
href={
prefixPath + `/video/detail/${video?.slug}`
}
> >
<Image <Image
priority={true} priority={true}
@ -414,6 +442,7 @@ const NewContent = (props: { group: string; type: string }) => {
src={video?.smallThumbnailLink} src={video?.smallThumbnailLink}
className="w-full h-full object-cover" className="w-full h-full object-cover"
/> />
</Link>
</motion.div> </motion.div>
{/* Badge category */} {/* Badge category */}
@ -444,10 +473,15 @@ const NewContent = (props: { group: string; type: string }) => {
{video?.categoryName?.toUpperCase() ?? {video?.categoryName?.toUpperCase() ??
"Giat Pimpinan"} "Giat Pimpinan"}
</p> </p>
<p <Link
className="text-sm lg:text-base font-semibold text-black dark:text-white line-clamp-5"> href={
prefixPath + `/video/detail/${video?.slug}`
}
>
<p className="text-sm lg:text-base font-semibold text-black dark:text-white line-clamp-5">
{video?.title} {video?.title}
</p> </p>
</Link>
</div> </div>
{/* Optional metadata area (uncomment if needed) */} {/* Optional metadata area (uncomment if needed) */}
{/* {/*
@ -500,15 +534,18 @@ const NewContent = (props: { group: string; type: string }) => {
className="md:basis-1/2 lg:basis-1/3" className="md:basis-1/2 lg:basis-1/3"
> >
<div <div
onClick={() => // onClick={() =>
router.push( // router.push(
prefixPath + `/document/detail/${text?.slug}` // prefixPath + `/document/detail/${text?.slug}`
) // )
} // }
className="cursor-pointer rounded-lg shadow-md overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500" className="rounded-lg shadow-md overflow-hidden bg-white dark:bg-black dark:border dark:border-gray-500"
> >
{/* Ikon di tengah dengan latar kuning */} {/* Ikon di tengah dengan latar kuning */}
<div className="bg-[#e0c350] flex items-center justify-center h-[170px] text-white"> <Link
href={prefixPath + `/document/detail/${text?.slug}`}
className="bg-[#e0c350] flex items-center justify-center h-[170px] text-white"
>
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width="150" width="150"
@ -520,7 +557,7 @@ const NewContent = (props: { group: string; type: string }) => {
d="M5 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V5.414a1.5 1.5 0 0 0-.44-1.06L9.647 1.439A1.5 1.5 0 0 0 8.586 1zM4 3a1 1 0 0 1 1-1h3v2.5A1.5 1.5 0 0 0 9.5 6H12v7a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1zm7.793 2H9.5a.5.5 0 0 1-.5-.5V2.207zM7 7.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5M7.5 9a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1zM7 11.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5M5.5 8a.5.5 0 1 0 0-1a.5.5 0 0 0 0 1M6 9.5a.5.5 0 1 1-1 0a.5.5 0 0 1 1 0M5.5 12a.5.5 0 1 0 0-1a.5.5 0 0 0 0 1" d="M5 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V5.414a1.5 1.5 0 0 0-.44-1.06L9.647 1.439A1.5 1.5 0 0 0 8.586 1zM4 3a1 1 0 0 1 1-1h3v2.5A1.5 1.5 0 0 0 9.5 6H12v7a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1zm7.793 2H9.5a.5.5 0 0 1-.5-.5V2.207zM7 7.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5M7.5 9a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1zM7 11.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5M5.5 8a.5.5 0 1 0 0-1a.5.5 0 0 0 0 1M6 9.5a.5.5 0 1 1-1 0a.5.5 0 0 1 1 0M5.5 12a.5.5 0 1 0 0-1a.5.5 0 0 0 0 1"
/> />
</svg> </svg>
</div> </Link>
{/* Konten bawah */} {/* Konten bawah */}
<div className="p-4 flex flex-col gap-2"> <div className="p-4 flex flex-col gap-2">
@ -530,10 +567,15 @@ const NewContent = (props: { group: string; type: string }) => {
</div> </div>
{/* Judul */} {/* Judul */}
<div className="font-semibold text-gray-900 dark:text-white text-xl leading-snug line-clamp-4"> <Link
href={
prefixPath + `/document/detail/${text?.slug}`
}
>
<p className="font-semibold text-gray-900 dark:text-white text-xl leading-snug line-clamp-4">
{text?.title} {text?.title}
</div> </p>
</Link>
{/* Meta info */} {/* Meta info */}
{/* <div className="text-gray-500 flex items-center text-xs gap-2"> {/* <div className="text-gray-500 flex items-center text-xs gap-2">
<span> <span>
@ -592,9 +634,17 @@ const NewContent = (props: { group: string; type: string }) => {
)} )}
</div> </div>
<div className="flex items-center flex-row justify-center mt-3"> <div className="flex items-center flex-row justify-center mt-3">
<div onClick={() => router.push(prefixPath + `/${selectedTab}/filter?sortBy=${props.type}`)} className="cursor-pointer border text-[#bb3523] rounded-lg text-sm lg:text-md px-4 py-1 border-[#bb3523] hover:text-white hover:bg-[#bb3523]"> <Link
href={prefixPath + `/${selectedTab}/filter?sortBy=${props.type}`}
// onClick={() =>
// router.push(
// prefixPath + `/${selectedTab}/filter?sortBy=${props.type}`
// )
// }
className="cursor-pointer border text-[#bb3523] rounded-lg text-sm lg:text-md px-4 py-1 border-[#bb3523] hover:text-white hover:bg-[#bb3523]"
>
{t("seeAll", { defaultValue: "See All" })} {t("seeAll", { defaultValue: "See All" })}
</div> </Link>
</div> </div>
</Reveal> </Reveal>
</div> </div>