adjust landing page mabes

This commit is contained in:
Sabda Yagra 2025-06-02 08:00:01 +07:00
parent 6a3bb288c9
commit 4657f79556
34 changed files with 1349 additions and 1758 deletions

View File

@ -13,6 +13,7 @@ import LatestContentKaltara from "@/components/landing-page/landing-polda-kaltar
import ContactUsKaltara from "@/components/landing-page/landing-polda-kaltara/contact-us-kaltara"; import ContactUsKaltara from "@/components/landing-page/landing-polda-kaltara/contact-us-kaltara";
import NewsTickerKaltara from "../../tbnews/[polda_name]/components/news-tickers-kaltara"; import NewsTickerKaltara from "../../tbnews/[polda_name]/components/news-tickers-kaltara";
import ContentCategoryKaltara from "@/components/landing-page/landing-polda-kaltara/content-category-kaltara"; import ContentCategoryKaltara from "@/components/landing-page/landing-polda-kaltara/content-category-kaltara";
import HeroNew from "@/components/landing-page/hero-new";
const page = () => { const page = () => {
const params = useParams(); const params = useParams();
@ -31,7 +32,8 @@ const page = () => {
</div> </div>
) : ( ) : (
<div> <div>
<HeaderBanner /> {/* <HeaderBanner /> */}
<HeroNew group="polda" />
<WelcomePolda /> <WelcomePolda />
<NewContent group="polda" type="latest" /> <NewContent group="polda" type="latest" />
<NewContent group="polda" type="popular" /> <NewContent group="polda" type="popular" />

View File

@ -19,7 +19,7 @@ const Home = ({ params: { locale } }: { params: { locale: string } }) => {
return ( return (
<MountedProvider isProtected={false}> <MountedProvider isProtected={false}>
<ReactLenis root> <ReactLenis root>
<div className=""> <div>
<Navbar /> <Navbar />
<HeroNew group="mabes" /> <HeroNew group="mabes" />
<div className="flex-1 "> <div className="flex-1 ">

View File

@ -1,15 +1,7 @@
"use client"; "use client";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { import { Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
Dialog,
DialogClose,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import Image from "next/image"; import Image from "next/image";
import Coverage from "./coverage"; import Coverage from "./coverage";
import Division from "./division"; import Division from "./division";
@ -30,33 +22,20 @@ const AreaCoverageWorkUnits = () => {
}; };
}, [openPolda, openSatker]); }, [openPolda, openSatker]);
return ( return (
<div className="mx-auto px-4 lg:px-8 py-6"> <div className="mx-auto px-4 lg:px-0 py-6">
<h2 className="text-start text-lg md:text-xl font-bold text-[#bb3523] border-b-2 border-[#bb3523] mb-4 uppercase"> <h2 className="text-start text-lg md:text-xl font-bold text-[#bb3523] border-b-2 border-[#bb3523] mb-4 uppercase">
Liputan <span className="text-[#bb3523]">Wilayah</span> &{" "} Liputan <span className="text-[#bb3523]">Wilayah</span> & <span className="text-[#bb3523]">Satker</span>
<span className="text-[#bb3523]">Satker</span>
</h2> </h2>
<div className="flex flex-col justify-center lg:flex-row gap-8 "> <div className="flex flex-col justify-center lg:flex-row gap-8 ">
{/* POLDA */} {/* POLDA */}
<Dialog open={openPolda} onOpenChange={setOpenPolda}> <Dialog open={openPolda} onOpenChange={setOpenPolda}>
<DialogTrigger asChild> <DialogTrigger asChild>
<button <button onClick={() => setOpenPolda(true)} className="flex flex-col gap-2 justify-center items-center shadow-lg group rounded-xl py-5 w-full border-2 border-transparent hover:border-[#bb3523] transition-all duration-300">
onClick={() => setOpenPolda(true)} <Image width={1920} height={1080} alt="indo" src="/assets/indo.png" className="h-32 w-32 group-hover:scale-110 group-hover:border-[#bb3523] " />
className="flex flex-col gap-2 justify-center items-center shadow-lg group rounded-xl py-5 px-24 border-2 border-transparent hover:border-[#bb3523] transition-all duration-300"
>
<Image
width={1920}
height={1080}
alt="indo"
src="/assets/indo.png"
className="h-32 w-32 group-hover:scale-110 group-hover:border-[#bb3523] "
/>
<p className="text-base font-bold">Polda Jajaran</p> <p className="text-base font-bold">Polda Jajaran</p>
</button> </button>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent size="md" className="max-h-[90vh] overflow-hidden flex flex-col ">
size="md"
className="max-h-[90vh] overflow-hidden flex flex-col "
>
<DialogHeader className="flex flex-col justify-center"> <DialogHeader className="flex flex-col justify-center">
<DialogTitle> <DialogTitle>
<p className="text-center">Polda Jajaran</p> <p className="text-center">Polda Jajaran</p>
@ -78,15 +57,11 @@ const AreaCoverageWorkUnits = () => {
{/* SATKER */} {/* SATKER */}
<Dialog open={openSatker} onOpenChange={setOpenSatker}> <Dialog open={openSatker} onOpenChange={setOpenSatker}>
<DialogTrigger className="flex flex-col gap-2 justify-center items-center shadow-lg group rounded-xl py-5 px-24 border-2 border-transparent hover:border-[#bb3523] transition-all duration-300"> <DialogTrigger asChild>
<Image <button className="flex flex-col gap-2 justify-center items-center shadow-lg group rounded-xl py-5 w-full border-2 border-transparent hover:border-[#bb3523] transition-all duration-300">
width={1920} <Image width={1920} height={1080} alt="polri" src="/assets/logo-polri.png" className="h-32 w-32 group-hover:scale-110 group-hover:border-[#bb3523] transition-transform duration-300" />
height={1080}
alt="polri"
src="/assets/logo-polri.png"
className="h-32 w-32 group-hover:scale-110 group-hover:border-[#bb3523] transition-transform duration-300"
/>
<p className="text-base font-bold">Satuan Kerja Polri</p> <p className="text-base font-bold">Satuan Kerja Polri</p>
</button>
</DialogTrigger> </DialogTrigger>
<DialogContent size="md"> <DialogContent size="md">
<DialogHeader className="flex flex-col justify-center"> <DialogHeader className="flex flex-col justify-center">

View File

@ -1,20 +1,11 @@
import { import { getCategoryData, getPublicCategoryData } from "@/service/landing/landing";
getCategoryData,
getPublicCategoryData,
} from "@/service/landing/landing";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { Reveal } from "./Reveal"; import { Reveal } from "./Reveal";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { useParams } from "next/navigation"; import { useParams } from "next/navigation";
import Image from "next/image"; import Image from "next/image";
import { import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "../ui/carousel";
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "../ui/carousel";
import { useRouter } from "@/i18n/routing"; import { useRouter } from "@/i18n/routing";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
@ -28,26 +19,14 @@ const ContentCategory = (props: { group?: string; type: string }) => {
const satkerName = params?.satker_name; const satkerName = params?.satker_name;
const router = useRouter(); const router = useRouter();
let prefixPath = poldaName let prefixPath = poldaName ? `/polda/${poldaName}` : satkerName ? `/satker/${satkerName}` : "/";
? `/polda/${poldaName}`
: satkerName
? `/satker/${satkerName}`
: "/";
useEffect(() => { useEffect(() => {
initFetch(); initFetch();
}, []); }, []);
const initFetch = async () => { const initFetch = async () => {
const response = await getPublicCategoryData( const response = await getPublicCategoryData(
props.group == "mabes" props.group == "mabes" ? "" : props.group == "polda" && poldaName && String(poldaName)?.length > 1 ? poldaName : props.group == "satker" && satkerName && String(satkerName)?.length > 1 ? "satker-" + satkerName : "",
? ""
: props.group == "polda" && poldaName && String(poldaName)?.length > 1
? poldaName
: props.group == "satker" &&
satkerName &&
String(satkerName)?.length > 1
? "satker-" + satkerName
: "",
"", "",
locale == "en" ? true : false locale == "en" ? true : false
); );
@ -73,10 +52,7 @@ const ContentCategory = (props: { group?: string; type: string }) => {
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" /> <animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
</svg>`; </svg>`;
const toBase64 = (str: string) => const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
typeof window === "undefined"
? Buffer.from(str).toString("base64")
: window.btoa(str);
return ( return (
<div className="px-4 py-10"> <div className="px-4 py-10">
@ -85,66 +61,46 @@ const ContentCategory = (props: { group?: string; type: string }) => {
<h2 className="text-start text-lg md:text-xl font-bold text-[#bb3523] border-b-2 border-[#bb3523] mb-4 uppercase"> <h2 className="text-start text-lg md:text-xl font-bold text-[#bb3523] border-b-2 border-[#bb3523] mb-4 uppercase">
{pathname?.split("/")[1] == "in" ? ( {pathname?.split("/")[1] == "in" ? (
<> <>
<span className="text-[#bb3523] dark:text-white"> <span className="text-[#bb3523] dark:text-white">{t("category")}&nbsp;</span>
{t("category")}&nbsp;
</span>
{t("content")} {t("content")}
</> </>
) : ( ) : (
<> <>
<span className="text-[#bb3523] dark:text-white"> <span className="text-[#bb3523] dark:text-white">{t("content")}&nbsp;</span>
{t("content")}&nbsp;
</span>
{t("category")} {t("category")}
</> </>
)} )}
</h2> </h2>
<div className="grid grid-cols-2 md:grid-cols-2 lg:grid-cols-4 gap-4"> <div className="grid grid-cols-2 md:grid-cols-2 lg:grid-cols-4 gap-4">
{(seeAllValue ? categories : categories?.slice(0, 4))?.map( {(seeAllValue ? categories : categories?.slice(0, 8))?.map((category: any) => (
(category: any) => (
<div key={category?.id}> <div key={category?.id}>
<div <div onClick={() => router.push(`${prefixPath}all/filter?category=${category?.id}`)} className="cursor-pointer relative group rounded-md overflow-hidden shadow-md hover:shadow-lg block">
onClick={() =>
router.push(
`${prefixPath}all/filter?category=${category?.id}`
)
}
className="cursor-pointer relative group rounded-md overflow-hidden shadow-md hover:shadow-lg block"
>
{/* Gambar */} {/* Gambar */}
<Image <Image
placeholder={`data:image/svg+xml;base64,${toBase64( placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`}
shimmer(700, 475)
)}`}
alt="category" alt="category"
width={2560} width={2560}
height={1440} height={1440}
src={category?.thumbnailLink} src={category?.thumbnailLink}
className="w-full lg:h-[250px] h-40 object-cover group-hover:scale-110 transition-transform duration-300" className="w-full lg:h-[300px] h-40 object-cover group-hover:scale-110 transition-transform duration-300"
/> />
{/* Overlay gelap */} {/* Overlay gelap */}
<div className="absolute inset-0 bg-black bg-opacity-25 group-hover:bg-opacity-35 transition-all duration-300 rounded-md"></div> <div className="absolute inset-0 bg-black bg-opacity-50 group-hover:bg-opacity-35 transition-all duration-300 rounded-md"></div>
{/* Judul */} {/* Judul */}
<div className="absolute bottom-5 left-0 right-16 bg-transparent backdrop-blur-md text-white p-4 border-l-2 border-[#bb3523] z-10 group-hover:scale-x-150 origin-left"> <div className="absolute bottom-5 left-1/2 transform -translate-x-1/2 text-white">
<h3 className="text-sm font-semibold truncate"> <h3 className="text-sm font-semibold text-center">{category?.name}</h3>
{category?.name}
</h3>
</div> </div>
</div> </div>
</div> </div>
) ))}
)}
</div> </div>
{/* Tombol See More / See Less */} {/* Tombol See More / See Less */}
{categories?.length > 8 && ( {categories?.length > 8 && (
<div className="flex items-center flex-row justify-center mt-6"> <div className="flex items-center flex-row justify-center mt-6">
<Button <Button onClick={() => setSeeAllValue(!seeAllValue)} className="bg-white hover:bg-[#bb3523] text-[#bb3523] hover:text-white border-2 border-[#bb3523]">
onClick={() => setSeeAllValue(!seeAllValue)}
className="bg-white hover:bg-[#bb3523] text-[#bb3523] hover:text-white border-2 border-[#bb3523]"
>
{seeAllValue ? t("seeLess") : t("seeMore")} {seeAllValue ? t("seeLess") : t("seeMore")}
</Button> </Button>
</div> </div>

View File

@ -8,100 +8,64 @@ import { usePathname } from "next/navigation";
import Image from "next/image"; import Image from "next/image";
const regions = [ const regions = [
{ name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
{ name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
{ {
name: "Polda Metro Jaya", name: "Polda Bangka Belitung",
slug: "metro-jaya", slug: "bangka-belitung",
logo: "/logo/polda/polda-metro.png", logo: "/logo/polda/polda-bangkabelitung.png",
},
{
name: "Polda Jawa Barat",
slug: "jawa-barat",
logo: "/logo/polda/polda-jawabarat.png",
}, },
{ {
name: "Polda Banten", name: "Polda Banten",
slug: "banten", slug: "banten",
logo: "/logo/polda/polda-banten.png", logo: "/logo/polda/polda-banten.png",
}, },
{
name: "Polda Bengkulu",
slug: "bengkulu",
logo: "/logo/polda/polda-bengkulu.png",
},
{
name: "Polda DIY",
slug: "di-yogyakarta",
logo: "/logo/polda/polda-jogja.png",
},
{
name: "Polda Gorontalo",
slug: "gorontalo",
logo: "/logo/polda/polda-gorontalo.png",
},
{ name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
{
name: "Polda Jawa Barat",
slug: "jawa-barat",
logo: "/logo/polda/polda-jawabarat.png",
},
{ {
name: "Polda Jawa Tengah", name: "Polda Jawa Tengah",
slug: "jawa-tengah", slug: "jawa-tengah",
logo: "/logo/polda/polda-jawatengah.png", logo: "/logo/polda/polda-jawatengah.png",
}, },
{
name: "Polda D.I Yogyakarta",
slug: "di-yogyakarta",
logo: "/logo/polda/polda-jogja.png",
},
{ {
name: "Polda Jawa Timur", name: "Polda Jawa Timur",
slug: "jawa-timur", slug: "jawa-timur",
logo: "/logo/polda/polda-jawatimur.png", logo: "/logo/polda/polda-jawatimur.png",
}, },
{ name: "Polda Aceh", slug: "aceh", logo: "/logo/polda/polda-aceh.png" },
{
name: "Polda Sumatera Utara",
slug: "sumatera-utara",
logo: "/logo/polda/polda-sumut.png",
},
{
name: "Polda Sumatera Barat",
slug: "sumatera-barat",
logo: "/logo/polda/polda-sumatera-barat.png",
},
{ name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
{
name: "Polda Kep. Riau",
slug: "kepulauan-riau",
logo: "/logo/polda/polda-kepri.png",
},
{ name: "Polda Jambi", slug: "jambi", logo: "/logo/polda/polda-jambi.png" },
{
name: "Polda Sumatera Selatan",
slug: "sumatera-selatan",
logo: "/logo/polda/polda-sumsel.png",
},
{
name: "Polda Kep. Bangka Belitung",
slug: "bangka-belitung",
logo: "/logo/polda/polda-bangkabelitung.png",
},
{
name: "Polda Bengkulu",
slug: "bengkulu",
logo: "/logo/polda/polda-bengkulu.png",
},
{
name: "Polda Lampung",
slug: "lampung",
logo: "/logo/polda/polda-lampung.png",
},
{
name: "Polda Nusa Tenggara Barat",
slug: "ntb",
logo: "/logo/polda/polda-ntb.png",
},
{
name: "Polda Nusa Tenggara Timur",
slug: "ntt",
logo: "/logo/polda/polda-ntt.png",
},
{ name: "Polda Bali", slug: "bali", logo: "/logo/polda/polda-bali.png" },
{ {
name: "Polda Kalimantan Barat", name: "Polda Kalimantan Barat",
slug: "kalimantan-barat", slug: "kalimantan-barat",
logo: "/logo/polda/polda-kalbar.png", logo: "/logo/polda/polda-kalbar.png",
}, },
{
name: "Polda Kalimantan Tengah",
slug: "kalimantan-tengah",
logo: "/logo/polda/polda-kalteng.png",
},
{ {
name: "Polda Kalimantan Selatan", name: "Polda Kalimantan Selatan",
slug: "kalimantan-selatan", slug: "kalimantan-selatan",
logo: "/logo/polda/polda-kalsel.png", logo: "/logo/polda/polda-kalsel.png",
}, },
{
name: "Polda Kalimantan Tengah",
slug: "kalimantan-tengah",
logo: "/logo/polda/polda-kalteng.png",
},
{ {
name: "Polda Kalimantan Timur", name: "Polda Kalimantan Timur",
slug: "kalimantan-timur", slug: "kalimantan-timur",
@ -113,20 +77,47 @@ const regions = [
logo: "/logo/polda/polda-kaltara.png", logo: "/logo/polda/polda-kaltara.png",
}, },
{ {
name: "Polda Sulawesi Tengah", name: "Polda Kepulauan Riau",
slug: "sulawesi-tengah", slug: "kepulauan-riau",
logo: "/logo/polda/polda-sulawesi-tengah.png", logo: "/logo/polda/polda-kepri.png",
}, },
{ {
name: "Polda Sulawesi Utara", name: "Polda Lampung",
slug: "sulawesi-utara", slug: "lampung",
logo: "/logo/polda/polda-sulawesi-utara.png", logo: "/logo/polda/polda-lampung.png",
}, },
{ {
name: "Polda Gorontalo", name: "Polda Maluku",
slug: "gorontalo", slug: "maluku",
logo: "/logo/polda/polda-gorontalo.png", logo: "/logo/polda/polda-maluku.png",
}, },
{
name: "Polda Maluku Utara",
slug: "maluku-utara",
logo: "/logo/polda/polda-maluku-utara.png",
},
{
name: "Polda Metro Jaya",
slug: "metro-jaya",
logo: "/logo/polda/polda-metro.png",
},
{
name: "Polda NTB",
slug: "ntb",
logo: "/logo/polda/polda-ntb.png",
},
{
name: "Polda NTT",
slug: "ntt",
logo: "/logo/polda/polda-ntt.png",
},
{ name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
{
name: "Polda Papua Barat",
slug: "papua-barat",
logo: "/logo/polda/polda-papua-barat.png",
},
{ name: "Polda Riau", slug: "riau", logo: "/logo/polda/polda-riau.png" },
{ {
name: "Polda Sulawesi Barat", name: "Polda Sulawesi Barat",
slug: "sulawesi-barat", slug: "sulawesi-barat",
@ -137,54 +128,59 @@ const regions = [
slug: "sulawesi-selatan", slug: "sulawesi-selatan",
logo: "/logo/polda/polda-sulsel.png", logo: "/logo/polda/polda-sulsel.png",
}, },
{
name: "Polda Sulawesi Tengah",
slug: "sulawesi-tengah",
logo: "/logo/polda/polda-sulawesi-tengah.png",
},
{ {
name: "Polda Sulawesi Tenggara", name: "Polda Sulawesi Tenggara",
slug: "sulawesi-tenggara", slug: "sulawesi-tenggara",
logo: "/logo/polda/polda-sulawesi-tenggara.png", logo: "/logo/polda/polda-sulawesi-tenggara.png",
}, },
{ {
name: "Polda Maluku Utara", name: "Polda Sulawesi Utara",
slug: "maluku-utara", slug: "sulawesi-utara",
logo: "/logo/polda/polda-maluku-utara.png", logo: "/logo/polda/polda-sulawesi-utara.png",
}, },
{ {
name: "Polda Maluku", name: "Polda Sumatera Barat",
slug: "maluku", slug: "sumatera-barat",
logo: "/logo/polda/polda-maluku.png", logo: "/logo/polda/polda-sumatera-barat.png",
}, },
{ {
name: "Polda Papua Barat", name: "Polda Sumatera Selatan",
slug: "papua-barat", slug: "sumatera-selatan",
logo: "/logo/polda/polda-papua-barat.png", logo: "/logo/polda/polda-sumsel.png",
},
{ name: "Polda Papua", slug: "papua", logo: "/logo/polda/polda-papua.png" },
{
name: "Satuan Kerja POLRI",
slug: "satker-polri",
logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
}, },
{ {
name: "Internasional", name: "Polda Sumatera Utara",
slug: "internasional", slug: "sumatera-utara",
logo: "/assets/polda/internasional.png", logo: "/logo/polda/polda-sumut.png",
}, },
// {
// name: "Satuan Kerja POLRI",
// slug: "satker-polri",
// logo: "/logo/satker/SATUAN-KERJA-POLRI.png",
// },
// {
// name: "Internasional",
// slug: "internasional",
// logo: "/assets/polda/internasional.png",
// },
]; ];
const Coverage: React.FC = () => { const Coverage: React.FC = () => {
const [seeAllValue, setSeeAllValue] = useState(false); const [seeAllValue, setSeeAllValue] = useState(false);
const [searchTerm, setSearchTerm] = useState(""); const [searchTerm, setSearchTerm] = useState("");
const [filteredList, setFilteredList] = useState<typeof regions | undefined>( const [filteredList, setFilteredList] = useState<typeof regions | undefined>(regions);
regions
);
const pathname = usePathname(); const pathname = usePathname();
const t = useTranslations("LandingPage"); const t = useTranslations("LandingPage");
const handleSearch = () => { const handleSearch = () => {
const value = searchTerm.toLowerCase(); const value = searchTerm.toLowerCase();
const filtered = regions.filter((polda) => const filtered = regions.filter((polda) => polda.name.toLowerCase().includes(value));
polda.name.toLowerCase().includes(value)
);
setFilteredList(filtered); setFilteredList(filtered);
}; };
@ -202,32 +198,16 @@ const Coverage: React.FC = () => {
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" /> <animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
</svg>`; </svg>`;
const toBase64 = (str: string) => const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
typeof window === "undefined"
? Buffer.from(str).toString("base64")
: window.btoa(str);
return ( return (
<div className="w-full"> <div className="w-full">
<div className="max-h-[60vh] overflow-y-auto px-4"> <div className="max-h-[60vh] overflow-y-auto px-4">
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6 gap-6 px-4 max-h-[60vh]"> <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6 gap-6 px-4 max-h-[60vh]">
{filteredList?.map((region: any) => ( {filteredList?.map((region: any) => (
<Link <Link key={region.slug} href={`/polda/${region.slug}`} className="flex flex-col items-center text-center p-3 border rounded-lg shadow-md hover:shadow-lg transition-all">
key={region.slug}
href={`/polda/${region.slug}`}
className="flex flex-col items-center text-center p-3 border rounded-lg shadow-md hover:shadow-lg transition-all"
>
<div className="mb-1 flex items-center justify-center"> <div className="mb-1 flex items-center justify-center">
<Image <Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={1920} height={1080} src={region.logo} alt={region.name} className="w-14 h-14 object-contain" />
placeholder={`data:image/svg+xml;base64,${toBase64(
shimmer(700, 475)
)}`}
width={1920}
height={1080}
src={region.logo}
alt={region.name}
className="w-14 h-14 object-contain"
/>
</div> </div>
<p className="text-xs font-semibold">{region.name}</p> <p className="text-xs font-semibold">{region.name}</p>
</Link> </Link>

View File

@ -8,45 +8,55 @@ import { usePathname } from "next/navigation";
import Image from "next/image"; import Image from "next/image";
const regions = [ const regions = [
{ name: "SIBER", slug: "siber", logo: "/logo/satker/SIBER.png" }, { name: "ITWASUM POLRI", slug: "itwasum", logo: "/logo/satker/ITWASUM.png" },
{ name: "DIVKUM", slug: "divkum", logo: "/logo/satker/DIVKUM.png" }, { name: "BAINTELKAM POLRI", slug: "baintelkam", logo: "/logo/satker/BAINTELKAM.png" },
{ name: "PUSKEU", slug: "puskeu", logo: "/logo/satker/PUSKEU.png" }, { name: "BAHARKAM POLRI", slug: "baharkam", logo: "/logo/satker/BAHARKAM.png" },
{ name: "YANMA", slug: "yanma", logo: "/logo/satker/YANMA.png" }, { name: "BARESKRIM POLRI", slug: "bareskrim", logo: "/logo/satker/BARESKRIM.png" },
{ name: "SSDM", slug: "ssdm", logo: "/logo/satker/SSDM.png" }, { name: "LEMDIKLAT POLRI", slug: "lemdiklat", logo: "/logo/satker/LEMDIKLAT.png" },
{ name: "ITWASUM", slug: "itwasum", logo: "/logo/satker/ITWASUM.png" }, { name: "KORBRIMOB POLRI", slug: "brimob", logo: "/logo/satker/BRIMOB.png" },
{ name: "STIK-PTIK", slug: "stik-ptik", logo: "/logo/satker/STIK-PTIK.png" }, { name: "STAMAOPS POLRI", slug: "sops", logo: "/logo/satker/SOPS.png" },
{ name: "SATUAN KERJA POLRI", slug: "satuan-kerja-polri", logo: "/logo/satker/SATUAN-KERJA-POLRI.png" }, { name: "STAMARENA POLRI", slug: "srena", logo: "/logo/satker/SRENA.png" },
{ name: "BRIMOB", slug: "brimob", logo: "/logo/satker/BRIMOB.png" }, { name: "SSDM POLRI", slug: "ssdm", logo: "/logo/satker/SSDM.png" },
{ name: "DIV HUMAS", slug: "div-humas", logo: "/logo/satker/DIV-HUMAS.png" }, { name: "SLOG POLRI", slug: "slog", logo: "/logo/satker/SLOG.png" },
{ name: "PUSLITBANG", slug: "puslitbang", logo: "/logo/satker/PUSLITBANG.png" }, { name: "SAHLI KAPOLRI", slug: "sahli-kapolri", logo: "/logo/satker/STAFAHLI.png" },
{ name: "BINMAS", slug: "binmas", logo: "/logo/satker/BINMAS.png" }, { name: "DIVPROPRAM POLRI", slug: "divpropram", logo: "/logo/satker/DIVPROPAM.png" },
{ name: "DIV TIK", slug: "div-tik", logo: "/logo/satker/DIV-TIK.png" }, { name: "DIVKUM", slug: "divkum", logo: "/assets/satker/divkum.png" },
{ name: "SPRIPIM", slug: "spripim", logo: "/logo/satker/SPRIPIM.png" }, { name: "DIVHUBINTER POLRI", slug: "divhubinter", logo: "/logo/satker/DIVHUBINTER.png" },
{ name: "DIVPROPRAM", slug: "divpropram", logo: "/logo/satker/DIVPROPAM.png" }, { name: "DIVTIK POLRI", slug: "div-tik", logo: "/logo/satker/DIV-TIK.png" },
{ name: "KORPS SABHARA BAHARKAM", slug: "korps-sabhara-baharkam", logo: "/logo/satker/KORPS-SABHARA-BAHARKAM.png" }, { name: "KORLANTAS POLRI", slug: "korlantas", logo: "/logo/satker/KORLANTAS.png" },
{ name: "PUSDOKKES", slug: "pusdokkes", logo: "/logo/satker/PUSDOKKES.png" }, { name: "DENSUS 88 POLRI", slug: "densus-88", logo: "/logo/satker/DENSUS88.png" },
{ name: "BAHARKAM", slug: "baharkam", logo: "/logo/satker/BAHARKAM.png" }, { name: "PUSDOKKES POLRI", slug: "pusdokkes", logo: "/logo/satker/PUSDOKKES.png" },
{ name: "POLAIRUD", slug: "polairud", logo: "/logo/satker/POLAIRUD.png" }, { name: "PUSLITBANG POLRI", slug: "puslitbang", logo: "/logo/satker/PUSLITBANG.png" },
{ name: "PUSKEU POLRI", slug: "puskeu", logo: "/logo/satker/PUSKEU.png" },
{ name: "PUSJARAH POLRI", slug: "pusjarah", logo: "/logo/satker/PUSJARAH.png" },
{ name: "SETUM POLRI", slug: "setum", logo: "/logo/satker/SETUM.png" },
{ name: "YANMA POLRI", slug: "yanma", logo: "/logo/satker/YANMA.png" },
{ name: "SPRIPIM POLRI", slug: "spripim", logo: "/logo/satker/SPRIPIM.png" },
{ name: "KORPOLAIRUD BAHARKAM POLRI", slug: "polairud", logo: "/logo/satker/POLAIRUD.png" },
{ name: "KORSABHARA BAHARKAM POLRI", slug: "korps-sabhara-baharkam", logo: "/logo/satker/KORPS-SABHARA-BAHARKAM.png" },
{ name: "KORBINMAS BAHARKAM POLRI", slug: "binmas", logo: "/logo/satker/BINMAS.png" },
{ name: "DITTIPIDUM BARESKRIM POLRI", slug: "dittipidum", logo: "/logo/satker/DITTIPIDUM.png" },
{ name: "DITTIPIDEKSUS BARESKRIM POLRI", slug: "dittipideksus", logo: "/logo/satker/DITTIPIDEKSUS.png" },
{ name: "DITTIPIDKOR BARESKRIM POLRI", slug: "dittipidkor", logo: "/logo/satker/DITTIPIDKOR.png" },
{ name: "DITTIPIDNARKOBA BARESKRIM POLRI", slug: "dittipidnarkoba", logo: "/logo/satker/DITTIPIDNARKOBA.png" },
{ name: "DITTIPIDTER BARESKRIM POLRI", slug: "dittipidter", logo: "/logo/satker/DITTIPIDTER.png" },
{ name: "DITTIPIDSIBER BARESKRIM POLRI", slug: "dittipidsiber", logo: "/logo/satker/DITTIPIDSIBER.png" },
{ name: "DIT PPA-PPO BARESKRIM POLRI", slug: "dit-ppa-ppo", logo: "/logo/satker/DITPPAPPO.png" },
{ name: "PUSLABFOR BARESKRIM POLRI", slug: "puslabfor", logo: "/assets/satker/puslabfor.png" },
{ name: "PUSIKNAS BARESKRIM POLRI", slug: "pusiknas", logo: "/logo/satker/PUSKINAS.png" },
{ name: "STIK LEMDIKLAT POLRI", slug: "stik-ptik", logo: "/logo/satker/STIK-PTIK.png" },
{ name: "AKPOL LEMDIKLAT POLRI", slug: "akpol", logo: "/logo/satker/AKPOL.png" },
{ name: "SESPIM LEMDIKLAT POLRI", slug: "sespim-polri", logo: "/logo/satker/SESPIM-POLRI.png" },
{ name: "SETUKPA LEMDIKLAT POLRI", slug: "setupa-polri", logo: "/assets/satker/setupa-polri.png" },
{ name: "SEPOLWAN LEMDIKLAT POLRI", slug: "sepolwan-polri", logo: "/assets/satker/sepolwan.png" },
{ name: "SEBASA LEMDIKLAT POLRI", slug: "sebasa-polri", logo: "/assets/satker/sebasa.png" },
{ name: "RUMKIT BHAYANGKARA TK I", slug: "rumkit-bhayangkara", logo: "/assets/satker/rumkit.png" },
{ name: "POLAIR", slug: "polair", logo: "/logo/satker/POLAIR.png" }, { name: "POLAIR", slug: "polair", logo: "/logo/satker/POLAIR.png" },
{ name: "POLUDARA", slug: "poludara", logo: "/logo/satker/POLUDARA.png" }, { name: "POLUDARA", slug: "poludara", logo: "/logo/satker/POLUDARA.png" },
{ name: "LEMDIKLAT", slug: "lemdiklat", logo: "/logo/satker/LEMDIKLAT.png" },
{ name: "AKPOL", slug: "akpol", logo: "/logo/satker/AKPOL.png" },
{ name: "KORLANTAS", slug: "korlantas", logo: "/logo/satker/KORLANTAS.png" },
{ name: "PUSINAFIS", slug: "pusinafis", logo: "/logo/satker/PUSINAFIS.png" }, { name: "PUSINAFIS", slug: "pusinafis", logo: "/logo/satker/PUSINAFIS.png" },
{ name: "PUSJARAH", slug: "pusjarah", logo: "/logo/satker/PUSJARAH.png" }, // { name: "SIBER", slug: "siber", logo: "/logo/satker/SIBER.png" },
{ name: "PUSIKNAS", slug: "pusiknas", logo: "/logo/satker/PUSKINAS.png" }, // { name: "SATUAN KERJA POLRI", slug: "satuan-kerja-polri", logo: "/logo/satker/SATUAN-KERJA-POLRI.png" },
{ name: "SLOG", slug: "slog", logo: "/logo/satker/SLOG.png" }, // { name: "DIV HUMAS", slug: "div-humas", logo: "/logo/satker/DIV-HUMAS.png" },
{ name: "BAINTELKAM", slug: "baintelkam", logo: "/logo/satker/BAINTELKAM.png" },
{ name: "BARESKRIM", slug: "bareskrim", logo: "/logo/satker/BARESKRIM.png" },
{ name: "DIVHUBINTER", slug: "divhubinter", logo: "/logo/satker/DIVHUBINTER.png" },
{ name: "SETUM", slug: "setum", logo: "/logo/satker/SETUM.png" },
{ name: "PUSLABFOR", slug: "puslabfor", logo: "/assets/satker/puslabfor.png" },
{ name: "DENSUS 88", slug: "densus-88", logo: "/logo/satker/DENSUS88.png" },
{ name: "SAHLI KAPOLRI", slug: "sahli-kapolri", logo: "/logo/satker/STAFAHLI.png" },
{ name: "SOPS", slug: "sops", logo: "/logo/satker/SOPS.png" },
{ name: "SRENA", slug: "srena", logo: "/logo/satker/SRENA.png" },
{ name: "SESPIM POLRI", slug: "sespim-polri", logo: "/logo/satker/SESPIM-POLRI.png" },
{ name: "SETUPA POLRI", slug: "setupa-polri", logo: "/assets/satker/setupa-polri.png" },
]; ];
const Division = () => { const Division = () => {

View File

@ -2,13 +2,7 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { import { Carousel, CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel";
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel";
import { useParams, usePathname } from "next/navigation"; import { useParams, usePathname } from "next/navigation";
import { Icon } from "@iconify/react/dist/iconify.js"; import { Icon } from "@iconify/react/dist/iconify.js";
import { formatDateToIndonesian, secondToTimes } from "@/utils/globals"; import { formatDateToIndonesian, secondToTimes } from "@/utils/globals";
@ -18,6 +12,7 @@ import { Reveal } from "./Reveal";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { Skeleton } from "../ui/skeleton"; import { Skeleton } from "../ui/skeleton";
import Image from "next/image"; import Image from "next/image";
import { motion } from "framer-motion";
const NewContent = (props: { group: string; type: string }) => { const NewContent = (props: { group: string; type: string }) => {
const [newContent, setNewContent] = useState<any>(); const [newContent, setNewContent] = useState<any>();
@ -30,12 +25,28 @@ const NewContent = (props: { group: string; type: string }) => {
const poldaName = params?.polda_name; const poldaName = params?.polda_name;
const satkerName = params?.satker_name; const satkerName = params?.satker_name;
const t = useTranslations("LandingPage"); const t = useTranslations("LandingPage");
const [api, setApi] = React.useState<CarouselApi | null>(null);
const [current, setCurrent] = React.useState(0);
const [count, setCount] = React.useState(0);
let prefixPath = poldaName React.useEffect(() => {
? `/polda/${poldaName}` if (!api) return;
: satkerName
? `/satker/${satkerName}` setCount(api.scrollSnapList().length);
: "/"; setCurrent(api.selectedScrollSnap());
const onSelect = () => {
setCurrent(api.selectedScrollSnap());
};
api.on("select", onSelect);
return () => {
api.off("select", onSelect);
};
}, [api]);
let prefixPath = poldaName ? `/polda/${poldaName}` : satkerName ? `/satker/${satkerName}` : "/";
useEffect(() => { useEffect(() => {
const timer = setTimeout(() => { const timer = setTimeout(() => {
@ -55,26 +66,8 @@ const NewContent = (props: { group: string; type: string }) => {
page: 0, page: 0,
size: 5, size: 5,
sortBy: props.type == "popular" ? "clickCount" : "createdAt", sortBy: props.type == "popular" ? "clickCount" : "createdAt",
contentTypeId: contentTypeId: selectedTab == "image" ? "1" : selectedTab == "video" ? "2" : selectedTab == "text" ? "3" : selectedTab == "audio" ? "4" : "",
selectedTab == "image" group: props.group == "mabes" ? "" : props.group == "polda" && poldaName && String(poldaName)?.length > 1 ? poldaName : props.group == "satker" && satkerName && String(satkerName)?.length > 1 ? "satker-" + satkerName : "",
? "1"
: selectedTab == "video"
? "2"
: selectedTab == "text"
? "3"
: selectedTab == "audio"
? "4"
: "",
group:
props.group == "mabes"
? ""
: props.group == "polda" && poldaName && String(poldaName)?.length > 1
? poldaName
: props.group == "satker" &&
satkerName &&
String(satkerName)?.length > 1
? "satker-" + satkerName
: "",
isInt: locale == "en" ? true : false, isInt: locale == "en" ? true : false,
}; };
const response = await getListContent(request); const response = await getListContent(request);
@ -96,44 +89,31 @@ const NewContent = (props: { group: string; type: string }) => {
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" /> <animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
</svg>`; </svg>`;
const toBase64 = (str: string) => const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
typeof window === "undefined"
? Buffer.from(str).toString("base64")
: window.btoa(str);
return ( return (
<div className="px-4 py-4"> <div className="px-4 py-4">
<Reveal> <Reveal>
<div className="flex flex-col p-4"> <div className="flex flex-col p-4">
<h2 className="flex items-center text-lg md:text-xl font-bold text-[#bb3523] border-b-2 border-[#bb3523] mb-4 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")}</span>&nbsp; <span className="text-[#bb3523] ">{t("content")}</span>&nbsp;
{props.type == "popular" {props.type == "popular" ? "Terpopuler" : props.type == "latest" ? t("new") : "Serupa"}
? "Terpopuler"
: props.type == "latest"
? t("new")
: "Serupa"}
</> </>
) : ( ) : (
<> <>
<span className="text-[#bb3523] "> <span className="text-[#bb3523] ">{props.type == "popular" ? "Popular" : props.type == "latest" ? t("new") : "Serupa"}</span>
{props.type == "popular"
? "Popular"
: props.type == "latest"
? t("new")
: "Serupa"}
</span>
&nbsp; &nbsp;
{t("content")} {t("content")}
</> </>
)} )}
</h2> </h2>
<div className="mx-auto w-full justify-start flex px-10 flex-col lg:flex-row gap-5 mb-4"> <div className="mx-auto w-full justify-start flex flex-col lg:flex-row gap-5 my-8">
<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: "video", value: "video" }, { label: "Audio Visual", value: "video" },
{ label: "Audio", value: "audio" }, { label: "Audio", value: "audio" },
{ label: "Foto", value: "image" }, { label: "Foto", value: "image" },
{ label: "Teks", value: "text" }, { label: "Teks", value: "text" },
@ -142,7 +122,7 @@ const NewContent = (props: { group: string; type: string }) => {
key={tab.value} key={tab.value}
value={tab.value} value={tab.value}
className={` className={`
rounded-md px-4 py-2 text-sm transition-all rounded-md px-6 py-2 text-sm transition-all
bg-[#f5f5f5] text-[#666] hover:bg-[#e0e0e0] bg-[#f5f5f5] text-[#666] hover:bg-[#e0e0e0]
data-[state=active]:bg-[#bb0000] data-[state=active]:bg-[#bb0000]
data-[state=active]:text-white data-[state=active]:text-white
@ -163,304 +143,243 @@ const NewContent = (props: { group: string; type: string }) => {
<Skeleton className="h-[200px] w-[400px] rounded-xl hidden md:block" /> <Skeleton className="h-[200px] w-[400px] rounded-xl hidden md:block" />
</div> </div>
) : ( ) : (
<div className="px-0 lg:px-10"> <div className="">
{selectedTab == "image" ? ( {selectedTab == "image" ? (
newContent?.length > 0 ? ( newContent?.length > 0 ? (
<Carousel className="w-full mx-auto"> <Carousel setApi={setApi} className="w-full mx-auto">
<CarouselContent> <CarouselContent>
{newContent?.map((image: any) => ( {newContent?.map((image: any) => (
<CarouselItem <CarouselItem key={image?.id} className="md:basis-1/2 lg:basis-1/3">
key={image?.id} <div onClick={() => router.push(prefixPath + `/image/detail/${image?.slug}`)} className="cursor-pointer relative group overflow-hidden bg-white rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300">
className="md:basis-1/2 lg:basis-1/3" {/* Image with motion effect */}
> <motion.div className="w-full h-48 lg:h-60" whileHover={{ scale: 0.95 }} transition={{ duration: 0.3 }}>
<div <Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={2560} height={1440} alt="image" src={image?.thumbnailLink} className="w-full h-full object-cover" />
onClick={() => </motion.div>
router.push(
prefixPath + `/image/detail/${image?.slug}` {/* Badge category */}
) {/* <div className="absolute top-2 left-2 bg-white px-2 py-1 rounded-sm text-[10px] font-bold text-[#bb3523]">{image?.category?.toUpperCase() ?? "GIAT PIMPINAN"}</div> */}
}
className="cursor-pointer relative group overflow-hidden shadow-md hover:shadow-lg" {/* Red icon overlay */}
> <div className="absolute top-2 right-2 bg-[#bb3523] rounded-full p-1">
<Image <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
placeholder={`data:image/svg+xml;base64,${toBase64( <g fill="none">
shimmer(700, 475) <path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
)}`} <path
width={2560} fill="white"
height={1440} d="M20 6a2 2 0 0 1 2 2v11.333a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2zm-8.268 7.944L7.136 18.54l-.066.06l-.07.054v.68h13v-.68l-.07-.053l-.066-.06l-2.24-2.24l-.353.354l.055.055a1 1 0 0 1-1.32 1.497l-.094-.083zM17 3a2 2 0 0 1 1.995 1.85L19 5H5a1 1 0 0 0-.993.883L4 6v12a2 2 0 0 1-1.995-1.85L2 16V6a3 3 0 0 1 2.824-2.995L5 3zm3 5H7v7.848L10.848 12a1.25 1.25 0 0 1 1.768 0l3.241 3.24l.884-.883a1.25 1.25 0 0 1 1.768 0L20 15.848zm-3.5 1.5a1.5 1.5 0 1 1 0 3a1.5 1.5 0 0 1 0-3"
alt="image"
src={image?.thumbnailLink}
className="w-full rounded-lg h-48 lg:h-60 object-cover group-hover:scale-100 transition-transform duration-300"
/> />
<div className="absolute bottom-0 left-0 right-0 bg-gray-500/55 border-l-4 border-[#bb3523] rounded-lg backdrop-blur-sm text-white p-2"> </g>
<p className="text-sm lg:text-base mb-2 font-semibold h-6 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible"> </svg>{" "}
{image?.title} </div>
</p>
<p className="flex flex-row items-center text-[10px] gap-1"> {/* Caption section */}
{formatDateToIndonesian( <div className="p-4">
new Date(image?.createdAt) <p className="text-[12px] font-bold text-[#bb3523] uppercase mb-1">{image?.categoryName?.toUpperCase() ?? "Giat Pimpinan"}</p>
)}{" "}
{image?.timezone ? image?.timezone : "WIB"} |{" "} <p className="text-lg font-semibold text-black truncate">{image?.title}</p>
<Icon
icon="formkit:eye" {/* <p className="flex flex-row items-center text-[10px] gap-1 mt-2 text-gray-600">
width="15" {formatDateToIndonesian(new Date(image?.createdAt))} {image?.timezone ?? "WIB"} |
height="15" <Icon icon="formkit:eye" width="15" height="15" /> {image.clickCount}
/>{" "} </p> */}
{image.clickCount}{" "}
</p>
</div> </div>
</div> </div>
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>
<div className="flex justify-center mt-4">
{Array.from({ length: count }).map((_, index) => (
<button key={index} className={`w-3 h-3 mx-1 rounded-full ${index === current ? "bg-gray-800" : "bg-gray-300"}`} onClick={() => api?.scrollTo(index)} aria-label={`Slide ${index + 1}`} />
))}
</div>
<CarouselPrevious className="hover:bg-black" /> <CarouselPrevious className="hover:bg-black" />
<CarouselNext className="hover:bg-black -mr-6" /> <CarouselNext className="hover:bg-black -mr-6" />
</Carousel> </Carousel>
) : ( ) : (
<p className="flex items-center justify-center"> <p className="flex items-center justify-center">
<Image <Image width={1920} height={1080} src="/assets/empty-data.png" alt="empty" className="h-52 w-52 my-4" />
width={1920}
height={1080}
src="/assets/empty-data.png"
alt="empty"
className="h-52 w-52 my-4"
/>
</p> </p>
) )
) : selectedTab == "audio" ? ( ) : selectedTab == "audio" ? (
newContent?.length > 0 ? ( newContent?.length > 0 ? (
<Carousel className="w-full max-w-7xl mx-auto"> <Carousel setApi={setApi} className="w-full max-w-7xl mx-auto">
<CarouselContent> <CarouselContent>
{newContent?.map((audio: any) => ( {newContent?.map((audio: any) => (
<CarouselItem <CarouselItem key={audio?.id} className="md:basis-1/2 lg:basis-1/3">
key={audio?.id} <div onClick={() => router.push(prefixPath + `/audio/detail/${audio?.slug}`)} className="cursor-pointer bg-white rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300 overflow-hidden">
className="md:basis-1/2 lg:basis-1/3 " {/* Icon Background */}
> <div className="flex items-center justify-center bg-[#bb3523] w-full h-[170px] text-white">
<div className="flex flex-row gap-6"> <svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" viewBox="0 0 20 20">
<div
onClick={() =>
router.push(
prefixPath + `/audio/detail/${audio?.slug}`
)
}
className="cursor-pointer flex flex-row sm:flex-row items-center bg-white dark:bg-gray-800 shadow-md border rounded-lg p-4 my-3 gap-4 w-full "
>
<div className="flex items-center justify-center bg-red-500 text-white rounded-lg lg:w-24 h-8 lg:h-16 w-10 p-3">
<svg
width="32"
height="34"
viewBox="0 0 32 34"
fill="null"
xmlns="http://www.w3.org/2000/svg"
>
<path <path
d="M23.404 0.452014C23.7033 0.35857 24.0204 0.336816 24.3297 0.388509C24.639 0.440203 24.9318 0.563895 25.1845 0.749599C25.4371 0.935304 25.6426 1.17782 25.7843 1.45756C25.9259 1.73731 25.9998 2.04644 26 2.36001V14.414C25.3462 14.2296 24.6766 14.1064 24 14.046V8.36001L10 12.736V27C10 28.1264 9.6197 29.2197 8.92071 30.1029C8.22172 30.9861 7.24499 31.6075 6.14877 31.8663C5.05255 32.125 3.90107 32.0061 2.88089 31.5287C1.86071 31.0514 1.03159 30.2435 0.52787 29.2361C0.024152 28.2286 -0.124656 27.0806 0.105556 25.9781C0.335768 24.8755 0.931513 23.883 1.79627 23.1613C2.66102 22.4396 3.74413 22.031 4.87009 22.0017C5.99606 21.9724 7.09893 22.3242 8.00001 23V6.73601C7.99982 6.30956 8.13596 5.8942 8.38854 5.55059C8.64112 5.20698 8.99692 4.9531 9.40401 4.82601L23.404 0.452014ZM10 10.64L24 6.26601V2.36001L10 6.73601V10.64ZM5.00001 24C4.20436 24 3.44129 24.3161 2.87869 24.8787C2.31608 25.4413 2.00001 26.2044 2.00001 27C2.00001 27.7957 2.31608 28.5587 2.87869 29.1213C3.44129 29.6839 4.20436 30 5.00001 30C5.79566 30 6.55872 29.6839 7.12133 29.1213C7.68394 28.5587 8.00001 27.7957 8.00001 27C8.00001 26.2044 7.68394 25.4413 7.12133 24.8787C6.55872 24.3161 5.79566 24 5.00001 24ZM32 25C32 27.387 31.0518 29.6761 29.364 31.364C27.6761 33.0518 25.387 34 23 34C20.6131 34 18.3239 33.0518 16.636 31.364C14.9482 29.6761 14 27.387 14 25C14 22.6131 14.9482 20.3239 16.636 18.6361C18.3239 16.9482 20.6131 16 23 16C25.387 16 27.6761 16.9482 29.364 18.6361C31.0518 20.3239 32 22.6131 32 25ZM27.47 24.128L21.482 20.828C21.3298 20.7443 21.1583 20.7016 20.9846 20.7043C20.8108 20.707 20.6408 20.7549 20.4912 20.8433C20.3416 20.9317 20.2176 21.0576 20.1315 21.2086C20.0453 21.3595 20 21.5302 20 21.704V28.304C20 28.4778 20.0453 28.6486 20.1315 28.7995C20.2176 28.9504 20.3416 29.0763 20.4912 29.1647C20.6408 29.2531 20.8108 29.301 20.9846 29.3037C21.1583 29.3064 21.3298 29.2638 21.482 29.18L27.47 25.88C27.6268 25.7937 27.7575 25.6669 27.8486 25.5128C27.9397 25.3587 27.9877 25.183 27.9877 25.004C27.9877 24.825 27.9397 24.6493 27.8486 24.4952C27.7575 24.3412 27.6268 24.2143 27.47 24.128Z" fill="currentColor"
fill="white" d="M14.702 2.226A1 1 0 0 1 16 3.18v6.027a5.5 5.5 0 0 0-1-.184V6.18L8 8.368V15.5a2.5 2.5 0 1 1-1-2V5.368a1 1 0 0 1 .702-.955zM8 7.32l7-2.187V3.18L8 5.368zM5.5 14a1.5 1.5 0 1 0 0 3a1.5 1.5 0 0 0 0-3m13.5.5a4.5 4.5 0 1 1-9 0a4.5 4.5 0 0 1 9 0m-2.265-.436l-2.994-1.65a.5.5 0 0 0-.741.438v3.3a.5.5 0 0 0 .741.438l2.994-1.65a.5.5 0 0 0 0-.876"
/> />
</svg> </svg>{" "}
</div> </div>
<div className="flex flex-col flex-1"> {/* Caption */}
<div className="text-gray-500 dark:text-gray-400 flex flex-row text-sm text-center items-center"> <div className="p-4">
{formatDateToIndonesian( <p className="text-[12px] font-bold text-[#bb3523] uppercase mb-1">{audio?.categoryName?.toUpperCase() ?? "GIAT PIMPINAN"}</p>
new Date(audio?.createdAt)
)}{" "} <p className="text-xl font-semibold text-black truncate">{audio?.title}</p>
{audio?.timezone ? audio?.timezone : "WIB"}{" "}
|&nbsp;{" "} {/* <p className="text-[10px] text-gray-600 mt-2 flex items-center gap-1">
<Icon {formatDateToIndonesian(new Date(audio?.createdAt))} {audio?.timezone ?? "WIB"} |
icon="formkit:eye" <Icon icon="formkit:eye" width="15" height="15" /> {audio?.clickCount}
width="15" </p> */}
height="15"
/>
&nbsp; {audio?.clickCount}{" "}
</div>
<div className="font-semibold text-gray-900 dark:text-white mt-1 text-sm h-5 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible">
{audio?.title}
</div>
<p className="text-sm">
{" "}
{audio?.duration
? secondToTimes(Number(audio?.duration))
: "00:00:00"}
</p>
</div>
</div> </div>
</div> </div>
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>
<div className="flex justify-center mt-4">
{Array.from({ length: count }).map((_, index) => (
<button key={index} className={`w-3 h-3 mx-1 rounded-full ${index === current ? "bg-gray-800" : "bg-gray-300"}`} onClick={() => api?.scrollTo(index)} aria-label={`Slide ${index + 1}`} />
))}
</div>
<CarouselPrevious /> <CarouselPrevious />
<CarouselNext /> <CarouselNext />
</Carousel> </Carousel>
) : ( ) : (
<p className="flex items-center justify-center"> <p className="flex items-center justify-center">
<Image <Image width={1920} height={1080} src="/assets/empty-data.png" alt="empty" className="h-52 w-52 my-4" />
width={1920}
height={1080}
src="/assets/empty-data.png"
alt="empty"
className="h-52 w-52 my-4"
/>
</p> </p>
) )
) : selectedTab == "video" ? ( ) : selectedTab == "video" ? (
newContent?.length > 0 ? ( newContent?.length > 0 ? (
<Carousel className="w-full max-w-7xl mx-auto"> <Carousel setApi={setApi} className="w-full mx-auto">
<CarouselContent> <CarouselContent>
{newContent?.map((video: any) => ( {newContent?.map((video: any) => (
<CarouselItem <CarouselItem key={video?.id} className="md:basis-1/2 lg:basis-1/3">
key={video?.id} <div onClick={() => router.push(prefixPath + `/video/detail/${video?.slug}`)} className="cursor-pointer relative group overflow-hidden bg-white rounded-xl shadow-md hover:shadow-lg transition-shadow duration-300">
className="md:basis-1/2 lg:basis-1/3" {/* Image with motion effect */}
> <motion.div className="w-full h-48 lg:h-60" whileHover={{ scale: 0.95 }} transition={{ duration: 0.3 }}>
<div <Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} alt="video" width={2560} height={1440} src={video?.thumbnailLink} className="w-full h-full object-cover" />
onClick={() => </motion.div>
router.push(
prefixPath + `/video/detail/${video?.slug}` {/* Badge category */}
) {/* <div className="absolute top-2 left-2 bg-white px-2 py-1 rounded-sm text-[10px] font-bold text-[#bb3523]">{video?.category?.toUpperCase() ?? "VIDEO"}</div> */}
}
className="cursor-pointer relative group rounded-md overflow-hidden shadow-md hover:shadow-lg" {/* Red icon overlay */}
> <div className="absolute top-2 right-2 bg-[#bb3523] rounded-full p-1">
<Image <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
placeholder={`data:image/svg+xml;base64,${toBase64( <g fill="none">
shimmer(700, 475) <path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
)}`} <path
alt="video" fill="white"
width={2560} d="M20 6a2 2 0 0 1 2 2v11.333a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2zm-8.268 7.944L7.136 18.54l-.066.06l-.07.054v.68h13v-.68l-.07-.053l-.066-.06l-2.24-2.24l-.353.354l.055.055a1 1 0 0 1-1.32 1.497l-.094-.083zM17 3a2 2 0 0 1 1.995 1.85L19 5H5a1 1 0 0 0-.993.883L4 6v12a2 2 0 0 1-1.995-1.85L2 16V6a3 3 0 0 1 2.824-2.995L5 3zm3 5H7v7.848L10.848 12a1.25 1.25 0 0 1 1.768 0l3.241 3.24l.884-.883a1.25 1.25 0 0 1 1.768 0L20 15.848zm-3.5 1.5a1.5 1.5 0 1 1 0 3a1.5 1.5 0 0 1 0-3"
height={1440}
src={video?.thumbnailLink}
className="w-full h-40 lg:h-60 object-cover rounded-lg group-hover:scale-100 transition-transform duration-300"
/> />
<div className="absolute bottom-0 rounded-lg left-0 right-0 border-l-4 border-[#bb3523] bg-gray-600 text-white p-2"> </g>
<p className="text-sm lg:text-base mb-2 font-semibold h-6 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible"> </svg>{" "}
{video?.title} </div>
</p>
<p className="flex flex-row items-center text-[10px] gap-1"> {/* Caption section */}
{formatDateToIndonesian( <div className="p-4">
new Date(video?.createdAt) <p className="text-[12px] font-bold text-[#bb3523] uppercase mb-1">{video?.categoryName?.toUpperCase() ?? "Video"}</p>
)}{" "}
{video?.timezone ? video?.timezone : "WIB"}|{" "} <p className="text-lg font-semibold text-black truncate">{video?.title}</p>
<Icon
icon="formkit:eye" {/* <p className="flex flex-row items-center text-[10px] gap-1 mt-2 text-gray-600">
width="15" {formatDateToIndonesian(new Date(video?.createdAt))} {video?.timezone ?? "WIB"} |
height="15" <Icon icon="formkit:eye" width="15" height="15" /> {video?.clickCount}
/>{" "} </p> */}
{video?.clickCount}{" "}
</p>
</div> </div>
</div> </div>
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>
<CarouselPrevious />
<CarouselNext /> {/* Pagination Dots */}
<div className="flex justify-center mt-4">
{Array.from({ length: count }).map((_, index) => (
<button key={index} className={`w-3 h-3 mx-1 rounded-full ${index === current ? "bg-gray-800" : "bg-gray-300"}`} onClick={() => api?.scrollTo(index)} aria-label={`Slide ${index + 1}`} />
))}
</div>
<CarouselPrevious className="hover:bg-black" />
<CarouselNext className="hover:bg-black -mr-6" />
</Carousel> </Carousel>
) : ( ) : (
<p className="flex items-center justify-center"> <p className="flex items-center justify-center">
<Image <Image width={1920} height={1080} src="/assets/empty-data.png" alt="empty" className="h-52 w-52 my-4" />
width={1920}
height={1080}
src="/assets/empty-data.png"
alt="empty"
className="h-52 w-52 my-4"
/>
</p> </p>
) )
) : newContent.length > 0 ? ( ) : newContent.length > 0 ? (
<Carousel className="w-full max-w-7xl mx-auto"> <Carousel setApi={setApi} className="w-full max-w-7xl mx-auto">
<CarouselContent> <CarouselContent>
{newContent?.map((text: any) => ( {newContent?.map((text: any) => (
<CarouselItem <CarouselItem key={text?.id} className="md:basis-1/2 lg:basis-1/3">
key={text?.id} <div onClick={() => router.push(prefixPath + `/document/detail/${text?.slug}`)} className="cursor-pointer rounded-lg shadow-md overflow-hidden bg-white">
className="md:basis-1/2 lg:basis-1/3" {/* Ikon di tengah dengan latar kuning */}
> <div className="bg-[#e0c350] flex items-center justify-center h-[170px] text-white">
<div className="md:basis-1/2 lg:basis-1/3"> <svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" viewBox="0 0 16 16">
<div
onClick={() =>
router.push(
prefixPath + `/document/detail/${text?.slug}`
)
}
className="flex flex-row bg-yellow-500 sm:flex-row items-center dark:bg-gray-800 cursor-pointer shadow-md rounded-lg p-4 gap-4"
>
<div className="flex items-center justify-center rounded-lg w-16 h-2 lg:h-16">
<svg
width="28"
height="34"
viewBox="0 0 28 34"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path <path
d="M5.6665 17.4167C5.6665 17.0851 5.7982 16.7672 6.03262 16.5328C6.26704 16.2984 6.58498 16.1667 6.9165 16.1667C7.24802 16.1667 7.56597 16.2984 7.80039 16.5328C8.03481 16.7672 8.1665 17.0851 8.1665 17.4167C8.1665 17.7482 8.03481 18.0661 7.80039 18.3005C7.56597 18.535 7.24802 18.6667 6.9165 18.6667C6.58498 18.6667 6.26704 18.535 6.03262 18.3005C5.7982 18.0661 5.6665 17.7482 5.6665 17.4167ZM6.9165 21.1667C6.58498 21.1667 6.26704 21.2984 6.03262 21.5328C5.7982 21.7672 5.6665 22.0851 5.6665 22.4167C5.6665 22.7482 5.7982 23.0661 6.03262 23.3005C6.26704 23.535 6.58498 23.6667 6.9165 23.6667C7.24802 23.6667 7.56597 23.535 7.80039 23.3005C8.03481 23.0661 8.1665 22.7482 8.1665 22.4167C8.1665 22.0851 8.03481 21.7672 7.80039 21.5328C7.56597 21.2984 7.24802 21.1667 6.9165 21.1667ZM5.6665 27.4167C5.6665 27.0851 5.7982 26.7672 6.03262 26.5328C6.26704 26.2984 6.58498 26.1667 6.9165 26.1667C7.24802 26.1667 7.56597 26.2984 7.80039 26.5328C8.03481 26.7672 8.1665 27.0851 8.1665 27.4167C8.1665 27.7482 8.03481 28.0661 7.80039 28.3005C7.56597 28.535 7.24802 28.6667 6.9165 28.6667C6.58498 28.6667 6.26704 28.535 6.03262 28.3005C5.7982 28.0661 5.6665 27.7482 5.6665 27.4167ZM11.9165 16.1667C11.585 16.1667 11.267 16.2984 11.0326 16.5328C10.7982 16.7672 10.6665 17.0851 10.6665 17.4167C10.6665 17.7482 10.7982 18.0661 11.0326 18.3005C11.267 18.535 11.585 18.6667 11.9165 18.6667H21.0832C21.4147 18.6667 21.7326 18.535 21.9671 18.3005C22.2015 18.0661 22.3332 17.7482 22.3332 17.4167C22.3332 17.0851 22.2015 16.7672 21.9671 16.5328C21.7326 16.2984 21.4147 16.1667 21.0832 16.1667H11.9165ZM10.6665 22.4167C10.6665 22.0851 10.7982 21.7672 11.0326 21.5328C11.267 21.2984 11.585 21.1667 11.9165 21.1667H21.0832C21.4147 21.1667 21.7326 21.2984 21.9671 21.5328C22.2015 21.7672 22.3332 22.0851 22.3332 22.4167C22.3332 22.7482 22.2015 23.0661 21.9671 23.3005C21.7326 23.535 21.4147 23.6667 21.0832 23.6667H11.9165C11.585 23.6667 11.267 23.535 11.0326 23.3005C10.7982 23.0661 10.6665 22.7482 10.6665 22.4167ZM11.9165 26.1667C11.585 26.1667 11.267 26.2984 11.0326 26.5328C10.7982 26.7672 10.6665 27.0851 10.6665 27.4167C10.6665 27.7482 10.7982 28.0661 11.0326 28.3005C11.267 28.535 11.585 28.6667 11.9165 28.6667H21.0832C21.4147 28.6667 21.7326 28.535 21.9671 28.3005C22.2015 28.0661 22.3332 27.7482 22.3332 27.4167C22.3332 27.0851 22.2015 26.7672 21.9671 26.5328C21.7326 26.2984 21.4147 26.1667 21.0832 26.1667H11.9165ZM26.3565 11.0233L16.6415 1.31C16.6157 1.28605 16.5885 1.26378 16.5598 1.24333C16.5392 1.22742 16.5192 1.21074 16.4998 1.19333C16.3852 1.08512 16.2632 0.984882 16.1348 0.893332C16.0922 0.865802 16.0476 0.841298 16.0015 0.819999L15.9215 0.779999L15.8382 0.731666C15.7482 0.679999 15.6565 0.626665 15.5615 0.586665C15.2296 0.454104 14.8783 0.376423 14.5215 0.356665C14.4885 0.354519 14.4557 0.350625 14.4232 0.344999C14.3779 0.338012 14.3323 0.334114 14.2865 0.333332H3.99984C3.11578 0.333332 2.26794 0.684521 1.64281 1.30964C1.01769 1.93476 0.666504 2.78261 0.666504 3.66667V30.3333C0.666504 31.2174 1.01769 32.0652 1.64281 32.6904C2.26794 33.3155 3.11578 33.6667 3.99984 33.6667H23.9998C24.8839 33.6667 25.7317 33.3155 26.3569 32.6904C26.982 32.0652 27.3332 31.2174 27.3332 30.3333V13.38C27.333 12.496 26.9817 11.6483 26.3565 11.0233ZM24.8332 30.3333C24.8332 30.5543 24.7454 30.7663 24.5891 30.9226C24.4328 31.0789 24.2208 31.1667 23.9998 31.1667H3.99984C3.77882 31.1667 3.56686 31.0789 3.41058 30.9226C3.2543 30.7663 3.1665 30.5543 3.1665 30.3333V3.66667C3.1665 3.44565 3.2543 3.23369 3.41058 3.07741C3.56686 2.92113 3.77882 2.83333 3.99984 2.83333H13.9998V10.3333C13.9998 11.2174 14.351 12.0652 14.9761 12.6904C15.6013 13.3155 16.4491 13.6667 17.3332 13.6667H24.8332V30.3333ZM16.4998 4.70166L22.9632 11.1667H17.3332C17.1122 11.1667 16.9002 11.0789 16.7439 10.9226C16.5876 10.7663 16.4998 10.5543 16.4998 10.3333V4.70166Z" fill="currentColor"
fill="black" 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> </div>
<div className="flex w-full pr-10 flex-col flex-1"> {/* Konten bawah */}
<div className="text-gray-500 dark:text-gray-400 flex flex-row items-center text-xs gap-0 lg:gap-1 mt-1 lg:text-sm"> <div className="p-4 flex flex-col gap-2">
{formatDateToIndonesian( {/* Kategori merah */}
new Date(text?.createdAt) <div className="text-[12px] font-bold text-red-600 uppercase">{text?.categoryName?.toUpperCase() ?? "Text"}</div>
)}
{text?.timezone ? text?.timezone : "WIB"}| {/* Judul */}
<Icon <div className="font-semibold text-gray-900 text-xl leading-snug line-clamp-2">{text?.title}</div>
icon="formkit:eye"
width="15" {/* Meta info */}
height="15" {/* <div className="text-gray-500 flex items-center text-xs gap-2">
/> <span>
{formatDateToIndonesian(new Date(text?.createdAt))}
{text?.timezone ? text?.timezone : "WIB"}
</span>
<span className="flex items-center gap-1">
<Icon icon="formkit:eye" width={14} height={14} />
{text?.clickCount} {text?.clickCount}
</div> </span>
<div className="font-semibold text-gray-900 dark:text-white mt-1 text-sm h-5 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible "> </div> */}
{text?.title}
</div> {/* Download */}
<div className="flex gap-2 items-center text-sm text-red-500 dark:text-red-500"> {/* <div className="flex items-center gap-2 text-sm text-red-500 mt-2">
<svg <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512">
xmlns="http://www.w3.org/2000/svg" <path fill="#f00" d="M224 30v256h-64l96 128l96-128h-64V30zM32 434v48h448v-48z" />
width="1em"
height="1em"
viewBox="0 0 512 512"
>
<path
fill="#f00"
d="M224 30v256h-64l96 128l96-128h-64V30zM32 434v48h448v-48z"
/>
</svg> </svg>
Download {t("document")} Download {t("document")}
</div> </div> */}
</div>
</div> </div>
</div> </div>
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>
{/* Pagination Dots */}
<div className="flex justify-center mt-4">
{Array.from({ length: count }).map((_, index) => (
<button key={index} className={`w-3 h-3 mx-1 rounded-full ${index === current ? "bg-gray-800" : "bg-gray-300"}`} onClick={() => api?.scrollTo(index)} aria-label={`Slide ${index + 1}`} />
))}
</div>
<CarouselPrevious /> <CarouselPrevious />
<CarouselNext /> <CarouselNext />
</Carousel> </Carousel>
) : ( ) : (
<p className="flex items-center justify-center"> <p className="flex items-center justify-center">
<Image <Image width={1920} height={1080} src="/assets/empty-data.png" alt="empty" className="h-52 w-52 my-4" />
width={1920}
height={1080}
src="/assets/empty-data.png"
alt="empty"
className="h-52 w-52 my-4"
/>
</p> </p>
)} )}
</div> </div>
)} )}
</div> </div>
<div className="flex items-center flex-row justify-center"> {/* <div className="flex items-center flex-row justify-center">
<div <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]">
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]"
>
{t("seeAll")} {t("seeAll")}
</div> </div>
</div> </div> */}
</Reveal> </Reveal>
</div> </div>
); );

View File

@ -4,14 +4,7 @@ import { useParams, useRouter } from "next/navigation";
import router from "next/router"; import router from "next/router";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { Icon } from "@iconify/react/dist/iconify.js"; import { Icon } from "@iconify/react/dist/iconify.js";
import { import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "../ui/select";
import Image from "next/image"; import Image from "next/image";
import { getHeroData } from "@/service/landing/landing"; import { getHeroData } from "@/service/landing/landing";
import { title } from "process"; import { title } from "process";
@ -57,26 +50,31 @@ const ScrollableContent = () => {
}; };
return ( return (
<> <>
<div className="text-center"> <div className="">
<h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white"> <h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white">
<span className="text-[#bb3523] dark:text-white"> <span className="text-[#c03724] dark:text-white">
{t("exploration")} {t("exploration")}&nbsp;{t("and")}
</span>
<span className="text-[#c03724] dark:text-white">
&nbsp;{t("download")}&nbsp;{t("coverage")}
</span>{" "} </span>{" "}
{t("and")}{" "}
<span className="text-[#bb3523] dark:text-white">
{t("download")}
</span>{" "}
{t("coverage")}{" "}
</h1> </h1>
<div className="w-[80%] h-1 bg-[#bb3523] mx-auto mt-2"></div> <div className="w-[10%] h-1 bg-[#bb3523] mt-2"></div>
<p className="text-sm md:text-base text-gray-500 dark:text-gray-100 mt-4"> <div className="w-full h-1 bg-[#bb3523] mx-auto"></div>
{t("officialCoverage")} <p className="text-sm md:text-base text-black dark:text-gray-100 mt-4">{t("officialCoverage")}</p>
</p>
<div className="mt-6 flex flex-col md:flex-row justify-center gap-4"> <div className="mt-6 flex flex-col md:flex-row justify-center gap-4">
<div className="flex flex-row items-center w-full rounded-lg gap-2 overflow-hidden"> <div className="flex flex-row items-center w-full rounded-lg gap-2 overflow-hidden">
<Select value={contentType} onValueChange={setContentType}> <Select value={contentType} onValueChange={setContentType}>
<SelectTrigger className="w-[180px]"> <SelectTrigger className="w-[180px] h-[55px]">
<span className="text-black">
<svg className="mx-2 dark:" width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M20 7.5H5C4.6023 7.5004 4.221 7.65856 3.93978 7.93978C3.65856 8.221 3.5004 8.6023 3.5 9V19.5C3.5004 19.8977 3.65856 20.279 3.93978 20.5602C4.221 20.8414 4.6023 20.9996 5 21H20C20.3977 20.9996 20.779 20.8414 21.0602 20.5602C21.3414 20.279 21.4996 19.8977 21.5 19.5V9C21.4996 8.6023 21.3414 8.221 21.0602 7.93978C20.779 7.65856 20.3977 7.5004 20 7.5ZM10.25 17.25V11.25L15.5 14.25L10.25 17.25ZM5 4.5H20V6H5V4.5ZM6.5 1.5H18.5V3H6.5V1.5Z"
fill="currentColor"
/>
</svg>
</span>
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
@ -91,55 +89,32 @@ const ScrollableContent = () => {
</Select> </Select>
<div className="flex items-center flex-1 border border-gray-300 rounded-lg overflow-hidden"> <div className="flex items-center flex-1 border border-gray-300 rounded-lg overflow-hidden">
<span className="material-icons text-black dark:text-white px-4"> <span className="material-icons text-black dark:text-white px-4">
<svg <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 24 24"
>
<path <path
fill="currentColor" fill="currentColor"
d="m19.6 21l-6.3-6.3q-.75.6-1.725.95T9.5 16q-2.725 0-4.612-1.888T3 9.5t1.888-4.612T9.5 3t4.613 1.888T16 9.5q0 1.1-.35 2.075T14.7 13.3l6.3 6.3zM9.5 14q1.875 0 3.188-1.312T14 9.5t-1.312-3.187T9.5 5T6.313 6.313T5 9.5t1.313 3.188T9.5 14" d="m19.6 21l-6.3-6.3q-.75.6-1.725.95T9.5 16q-2.725 0-4.612-1.888T3 9.5t1.888-4.612T9.5 3t4.613 1.888T16 9.5q0 1.1-.35 2.075T14.7 13.3l6.3 6.3zM9.5 14q1.875 0 3.188-1.312T14 9.5t-1.312-3.187T9.5 5T6.313 6.313T5 9.5t1.313 3.188T9.5 14"
/> />
</svg> </svg>
</span> </span>
<input <input type="text" placeholder={t("searchCoverageHere")} className="w-full py-4 px-2 text-sm text-gray-700 dark:text-gray-100 focus:outline-none" onChange={(e) => setSearch(e.target.value)} />
type="text"
placeholder={t("search")}
className="w-full py-2 px-2 text-sm text-gray-700 dark:text-gray-100 focus:outline-none"
onChange={(e) => setSearch(e.target.value)}
/>
</div> </div>
</div> </div>
<button <button onClick={() => router.push(`/${contentType}/filter?title=${search}`)} className="flex justify-center items-center px-6 w-full lg:w-[20%] py-4 bg-[#bb3523] gap-2 text-white rounded-lg hover:bg-red-700">
onClick={() =>
router.push(`/${contentType}/filter?title=${search}`)
}
className="flex justify-center items-center px-6 w-full lg:w-[20%] py-2 bg-[#bb3523] gap-2 text-white rounded-lg hover:bg-red-700"
>
{t("searchCoverage")} {t("searchCoverage")}
<Icon icon="ri:arrow-right-s-line" fontSize={20} /> <Icon icon="ri:arrow-right-s-line" fontSize={20} />
</button> </button>
</div> </div>
</div> </div>
<div className="flex flex-col md:flex-row gap-6 py-8"> <div className="flex flex-col md:flex-row gap-6 py-8">
{/* Berita Polda */}
<div className="w-full md:w-1/2 px-4"> <div className="w-full md:w-1/2 px-4">
<h2 className="text-lg md:text-xl font-bold text-[#bb3523] border-b-2 border-[#bb3523] mb-4 uppercase"> <h2 className="text-lg md:text-xl font-bold text-[#bb3523] mb-2 uppercase">Berita Polda</h2>
Berita Polda <div className="w-[10%] h-1 bg-[#bb3523]"></div>
</h2> <div className="w-full h-1 bg-[#bb3523] mx-auto mb-4"></div>
<div className="grid gap-4"> <div className="grid gap-4">
{content?.slice(0, 4).map((item: any, index: number) => ( {content?.slice(0, 4).map((item: any, index: number) => (
<div <div key={index} className={`bg-white rounded-lg shadow-md overflow-hidden ${index === 0 ? "" : "flex"}`}>
key={index} <div className={`relative ${index === 0 ? "w-full h-48" : " w-1/2 h-[150px]"}`}>
className={`bg-white rounded-lg shadow-md overflow-hidden ${
index === 0 ? "" : "flex"
}`}
>
<div
className={`relative ${
index === 0 ? "w-full h-48" : " w-1/2 h-[150px]"
}`}
>
<Link <Link
href={ href={
Number(item?.fileTypeId) == 1 Number(item?.fileTypeId) == 1
@ -151,21 +126,16 @@ const ScrollableContent = () => {
: `${locale}/audio/detail/${item?.slug}` : `${locale}/audio/detail/${item?.slug}`
} }
> >
<Image <Image src={item.thumbnailLink} alt={item.title} layout="fill" objectFit="cover" />
src={item.thumbnailLink} <div className="absolute top-2 right-2 bg-[#c03724] rounded-full p-1 shadow">
alt={item.title} <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
layout="fill" <g fill="none">
objectFit="cover" <path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path
fill="white"
d="M20 6a2 2 0 0 1 2 2v11.333a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2zm-8.268 7.944L7.136 18.54l-.066.06l-.07.054v.68h13v-.68l-.07-.053l-.066-.06l-2.24-2.24l-.353.354l.055.055a1 1 0 0 1-1.32 1.497l-.094-.083zM17 3a2 2 0 0 1 1.995 1.85L19 5H5a1 1 0 0 0-.993.883L4 6v12a2 2 0 0 1-1.995-1.85L2 16V6a3 3 0 0 1 2.824-2.995L5 3zm3 5H7v7.848L10.848 12a1.25 1.25 0 0 1 1.768 0l3.241 3.24l.884-.883a1.25 1.25 0 0 1 1.768 0L20 15.848zm-3.5 1.5a1.5 1.5 0 1 1 0 3a1.5 1.5 0 0 1 0-3"
/> />
<div className="absolute top-2 right-2 bg-white rounded-full p-1 shadow"> </g>
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.5em"
height="1.5em"
viewBox="0 0 24 24"
fill="currentColor"
>
<path d="M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2m-2 0H5V5h14ZM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5Z" />
</svg> </svg>
</div> </div>
</Link> </Link>
@ -182,46 +152,35 @@ const ScrollableContent = () => {
} }
> */} > */}
<div className={`${index === 0 ? "p-4" : "p-3 w-[50%]"}`}> <div className={`${index === 0 ? "p-4" : "p-3 w-[50%]"}`}>
<p className="text-sm text-[#bb3523] font-bold mb-1"> <p className="text-sm text-[#bb3523] font-bold mb-1">{item.categoryName}</p>
{item.categoryName} <h3 className="text-sm font-semibold text-gray-800">{item.title}</h3>
</p> <p className="text-xs text-gray-500 mt-1 truncate">{htmlToString(item.description)}</p>
<h3 className="text-sm font-semibold text-gray-800">
{item.title}
</h3>
<p className="text-xs text-gray-500 mt-1 truncate">
{htmlToString(item.description)}
</p>
</div> </div>
{/* </Link> */}
</div> </div>
))} ))}
<button className="w-full mt-2 py-2 border border-[#bb3523] text-[#bb3523] rounded-lg font-semibold hover:bg-[#bb3523] hover:text-white transition"> <button className="w-fit px-2 mt-2 py-2 border flex flex-row gap-2 border-[#bb3523] bg-white text-[#bb3523] rounded-lg font-semibold hover:bg-[#bb3523] hover:border-white hover:text-white transition">
LIHAT SEMUA LEBIH SEDIKIT
</button> <span className="text-[#bb3523] hover:text-white">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="m10 17l5-5m0 0l-5-5" />
</svg>
</span>
</button>{" "}
</div> </div>
</div> </div>
{/* Berita SATKER */} {/* Berita SATKER */}
<div className="w-full md:w-1/2 px-4"> <div className="w-full md:w-1/2 px-4">
<h2 className="text-lg md:text-xl font-bold text-[#bb3523] border-b-2 border-[#bb3523] mb-4 uppercase"> <h2 className="text-lg md:text-xl font-bold mb-2 text-[#bb3523] uppercase">Berita Satker</h2>
Berita Satker <div className="w-[10%] h-1 bg-[#bb3523]"></div>
</h2> <div className="w-full h-1 bg-[#bb3523] mx-auto mb-4"></div>
<div className="grid gap-4"> <div className="grid gap-4">
{content {content
?.filter((item: any) => item.isPublishOnPolda === true) ?.filter((item: any) => item.isPublishOnPolda === true)
.slice(0, 4) .slice(0, 4)
.map((item: any, index: number) => ( .map((item: any, index: number) => (
<div <div key={index} className={`bg-white rounded-lg shadow-md overflow-hidden ${index === 0 ? "" : "flex"}`}>
key={index} <div className={`relative ${index === 0 ? "w-full h-48" : " w-1/2 h-[150px]"}`}>
className={`bg-white rounded-lg shadow-md overflow-hidden ${
index === 0 ? "" : "flex"
}`}
>
<div
className={`relative ${
index === 0 ? "w-full h-48" : " w-1/2 h-[150px]"
}`}
>
<Link <Link
href={ href={
Number(item?.fileTypeId) == 1 Number(item?.fileTypeId) == 1
@ -233,40 +192,34 @@ const ScrollableContent = () => {
: `${locale}/audio/detail/${item?.slug}` : `${locale}/audio/detail/${item?.slug}`
} }
> >
<Image <Image src={item.thumbnailLink} alt={item.title} layout="fill" objectFit="cover" />
src={item.thumbnailLink} <div className="absolute top-2 right-2 bg-[#c03724] rounded-full p-1 shadow">
alt={item.title} <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
layout="fill" <g fill="none">
objectFit="cover" <path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path
fill="white"
d="M20 6a2 2 0 0 1 2 2v11.333a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2zm-8.268 7.944L7.136 18.54l-.066.06l-.07.054v.68h13v-.68l-.07-.053l-.066-.06l-2.24-2.24l-.353.354l.055.055a1 1 0 0 1-1.32 1.497l-.094-.083zM17 3a2 2 0 0 1 1.995 1.85L19 5H5a1 1 0 0 0-.993.883L4 6v12a2 2 0 0 1-1.995-1.85L2 16V6a3 3 0 0 1 2.824-2.995L5 3zm3 5H7v7.848L10.848 12a1.25 1.25 0 0 1 1.768 0l3.241 3.24l.884-.883a1.25 1.25 0 0 1 1.768 0L20 15.848zm-3.5 1.5a1.5 1.5 0 1 1 0 3a1.5 1.5 0 0 1 0-3"
/> />
<div className="absolute top-2 right-2 bg-white rounded-full p-1 shadow"> </g>
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.5em"
height="1.5em"
viewBox="0 0 24 24"
fill="currentColor"
>
<path d="M21 19V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2m-2 0H5V5h14ZM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5Z" />
</svg> </svg>
</div> </div>
</Link> </Link>
</div> </div>
<div className={`${index === 0 ? "p-4" : "p-3 w-[50%]"}`}> <div className={`${index === 0 ? "p-4" : "p-3 w-[50%]"}`}>
<p className="text-sm text-[#bb3523] font-bold mb-1"> <p className="text-sm text-[#bb3523] font-bold mb-1">{item.categoryName}</p>
{item.categoryName} <h3 className="text-sm font-semibold text-gray-800">{item.title}</h3>
</p> <p className="text-xs text-gray-500 mt-1 truncate">{htmlToString(item.description)}</p>
<h3 className="text-sm font-semibold text-gray-800">
{item.title}
</h3>
<p className="text-xs text-gray-500 mt-1 truncate">
{htmlToString(item.description)}
</p>
</div> </div>
</div> </div>
))} ))}
<button className="w-full mt-2 py-2 border border-[#bb3523] text-[#bb3523] rounded-lg font-semibold hover:bg-[#bb3523] hover:text-white transition"> <button className="w-fit px-2 mt-2 py-2 border flex flex-row gap-2 border-[#bb3523] bg-white text-[#bb3523] rounded-lg font-semibold hover:bg-[#bb3523] hover:text-white transition">
LIHAT SEMUA LEBIH SEDIKIT
<span className="text-[#bb3523] hover:text-white">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="m10 17l5-5m0 0l-5-5" />
</svg>
</span>
</button> </button>
</div> </div>
</div> </div>

View File

@ -1,12 +1,5 @@
import search from "@/app/[locale]/(protected)/app/chat/components/search"; import search from "@/app/[locale]/(protected)/app/chat/components/search";
import { import { Select, SelectTrigger, SelectValue, SelectContent, SelectGroup, SelectItem } from "@radix-ui/react-select";
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectGroup,
SelectItem,
} from "@radix-ui/react-select";
import { Icon } from "lucide-react"; import { Icon } from "lucide-react";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
@ -39,12 +32,12 @@ const SearchSection = () => {
const router = useRouter(); const router = useRouter();
const t = useTranslations("LandingPage"); const t = useTranslations("LandingPage");
return ( return (
<div className="flex w-full min-h-screen bg-gray-100 dark:bg-zinc-800"> <div className="flex w-full min-h-screen bg-center bg-cover bg-no-repeat" style={{ backgroundImage: "url('/assets/background.png')" }}>
<div className="hidden xl:block w-[15%] pr-4 py-5 sticky top-[150px] space-y-4 self-start"> <div className="hidden xl:block w-[15%] pr-4 py-5 sticky top-[150px] space-y-4 self-start">
<LeftBanner /> <LeftBanner />
</div> </div>
<div className="w-full xl:w-[70%] px-4 py-8"> <div className="w-full xl:w-[70%] px-4 py-8 bg-white">
<ScrollableContent /> <ScrollableContent />
<NewContent group="mabes" type="latest" /> <NewContent group="mabes" type="latest" />
<NewContent group="mabes" type="popular" /> <NewContent group="mabes" type="popular" />

View File

@ -1,13 +1,5 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { import { Dialog, DialogClose, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "../ui/dialog";
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../ui/dialog";
import FormSurvey from "./survey"; import FormSurvey from "./survey";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { Textarea } from "../ui/textarea"; import { Textarea } from "../ui/textarea";
@ -54,49 +46,16 @@ const UserSurveyBox = () => {
}); });
const options = { const options = {
accessFrequency: [ accessFrequency: ["Setiap hari", "Beberapa kali seminggu", "Beberapa kali dalam sebulan", "Baru pertama kali"],
"Setiap hari",
"Beberapa kali seminggu",
"Beberapa kali dalam sebulan",
"Baru pertama kali",
],
uiExperienceDesign: ["Sangat baik", "Baik", "Cukup", "Kurang", "Buruk"], uiExperienceDesign: ["Sangat baik", "Baik", "Cukup", "Kurang", "Buruk"],
uiExperienceNavigation: [ uiExperienceNavigation: ["Sangat mudah", "Mudah", "Cukup", "Sulit", "Sangat sulit"],
"Sangat mudah", uiExperienceSpeed: ["Sangat cepat", "Cepat", "Cukup", "Lambat", "Sangat lambat"],
"Mudah",
"Cukup",
"Sulit",
"Sangat sulit",
],
uiExperienceSpeed: [
"Sangat cepat",
"Cepat",
"Cukup",
"Lambat",
"Sangat lambat",
],
infoAccuracy: ["Sangat puas", "Puas", "Cukup", "Kurang puas", "Tidak puas"], infoAccuracy: ["Sangat puas", "Puas", "Cukup", "Kurang puas", "Tidak puas"],
infoCompleteness: [ infoCompleteness: ["Sangat lengkap", "Lengkap", "Cukup", "Kurang lengkap", "Tidak lengkap"],
"Sangat lengkap", usefulness: ["Sangat membantu", "Membantu", "Cukup membantu", "Kurang membantu", "Tidak membantu"],
"Lengkap",
"Cukup",
"Kurang lengkap",
"Tidak lengkap",
],
usefulness: [
"Sangat membantu",
"Membantu",
"Cukup membantu",
"Kurang membantu",
"Tidak membantu",
],
}; };
const renderControllerGroup = ( const renderControllerGroup = (name: keyof SurveySchema, question: string, choices: string[]) => (
name: keyof SurveySchema,
question: string,
choices: string[]
) => (
<div className="space-y-2"> <div className="space-y-2">
<p className="font-medium">{question}</p> <p className="font-medium">{question}</p>
<div className="grid grid-cols-2 gap-2"> <div className="grid grid-cols-2 gap-2">
@ -107,21 +66,14 @@ const UserSurveyBox = () => {
control={control} control={control}
render={({ field }) => ( render={({ field }) => (
<label className="flex items-center space-x-2"> <label className="flex items-center space-x-2">
<Checkbox <Checkbox checked={field.value === choice} onCheckedChange={() => field.onChange(choice)} />
checked={field.value === choice}
onCheckedChange={() => field.onChange(choice)}
/>
<span>{choice}</span> <span>{choice}</span>
</label> </label>
)} )}
/> />
))} ))}
</div> </div>
{errors[name] && ( {errors[name] && <p className="text-red-500 text-sm">{errors[name]?.message as string}</p>}
<p className="text-red-500 text-sm">
{errors[name]?.message as string}
</p>
)}
</div> </div>
); );
@ -138,107 +90,61 @@ const UserSurveyBox = () => {
} }
}; };
return ( return (
<div className="mt-8 rounded-lg bg-white dark:bg-zinc-900 p-4 shadow"> <div className="relative mt-8 rounded-lg bg-white dark:bg-zinc-900 p-6 shadow overflow-hidden">
<h2 className="text-lg font-bold mb-2"> {/* Garis menyerong */}
SURVEI KEPUASAN PENGGUNA MEDIAHUB POLRI <div className="hidden lg:block absolute right-64 top-0">
</h2> <img src="/assets/line1.png" alt="line" className="" />
<p className="text-sm text-gray-700 dark:text-gray-300 mb-4"> </div>
Kami menghargai pendapat Anda! Survei ini bertujuan untuk meningkatkan <div className="hidden lg:block absolute right-60 top-0">
kualitas layanan MediaHub Polri. Mohon luangkan waktu beberapa menit <img src="/assets/line1.png" alt="line" className="" />
untuk mengisi survei ini. </div>
</p> <div className="hidden lg:block absolute right-56 top-0">
<img src="/assets/line1.png" alt="line" className="" />
</div>
{/* Grid konten */}
<div className="relative z-10 grid grid-cols-1 md:grid-cols-2 gap-4 items-center">
{/* Kiri: Teks dan tombol */}
<div>
<h2 className="text-2xl font-bold mb-2">SURVEI KEPUASAN PENGGUNA MEDIAHUB POLRI</h2>
<p className="text-sm text-gray-700 dark:text-gray-300 mb-6">Kami menghargai pendapat Anda! Survei ini bertujuan untuk meningkatkan kualitas layanan MediaHub Polri. Mohon luangkan waktu beberapa menit untuk mengisi survei ini.</p>
<Dialog open={openPolda} onOpenChange={setOpenPolda}> <Dialog open={openPolda} onOpenChange={setOpenPolda}>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button <Button size="md" onClick={() => setOpenPolda(true)} className="bg-[#bb3523] hover:bg-[#9e2e1e] text-white font-bold px-6 py-3 rounded shadow-md transition-all duration-300">
size="md" SURVEY SEKARANG
onClick={() => setOpenPolda(true)}
className="flex flex-col gap-2 justify-center items-center shadow-lg group rounded-xl py-5 px-24 border-2 bg-[#bb3523] hover:bg-white] transition-all duration-300"
>
<p className="text-base font-bold">Survey Sekarang</p>
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent size="md" className="max-h-[90vh] overflow-auto flex flex-col">
size="md"
className="max-h-[90vh] overflow-auto flex flex-col "
>
<DialogHeader> <DialogHeader>
<DialogTitle className="text-lg font-bold"> <DialogTitle className="text-lg font-bold">SURVEI KEPUASAN PENGGUNA MEDIAHUB POLRI</DialogTitle>
SURVEI KEPUASAN PENGGUNA MEDIAHUB POLRI <DialogDescription className="text-sm">Kami menghargai pendapat Anda! Survei ini bertujuan untuk meningkatkan kualitas layanan MediaHub Polri.</DialogDescription>
</DialogTitle>
<DialogDescription className="text-sm">
Kami menghargai pendapat Anda! Survei ini bertujuan untuk
meningkatkan kualitas layanan MediaHub Polri.
</DialogDescription>
</DialogHeader> </DialogHeader>
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6 mt-4"> <form onSubmit={handleSubmit(onSubmit)} className="space-y-6 mt-4">
{renderControllerGroup( {renderControllerGroup("accessFrequency", "1. Seberapa sering Anda mengakses MediaHub Polri?", options.accessFrequency)}
"accessFrequency",
"1. Seberapa sering Anda mengakses MediaHub Polri?",
options.accessFrequency
)}
<div> <div>
<p className="font-medium"> <p className="font-medium">2. Bagaimana pengalaman Anda dalam mengakses website ini?</p>
2. Bagaimana pengalaman Anda dalam mengakses website ini?
</p>
<div className="space-y-3 mt-2"> <div className="space-y-3 mt-2">
{renderControllerGroup( {renderControllerGroup("uiExperienceDesign", "a) Tampilan dan desain website", options.uiExperienceDesign)}
"uiExperienceDesign", {renderControllerGroup("uiExperienceNavigation", "b) Kemudahan navigasi", options.uiExperienceNavigation)}
"a) Tampilan dan desain website", {renderControllerGroup("uiExperienceSpeed", "c) Kecepatan akses website", options.uiExperienceSpeed)}
options.uiExperienceDesign
)}
{renderControllerGroup(
"uiExperienceNavigation",
"b) Kemudahan navigasi",
options.uiExperienceNavigation
)}
{renderControllerGroup(
"uiExperienceSpeed",
"c) Kecepatan akses website",
options.uiExperienceSpeed
)}
</div> </div>
</div> </div>
<div> <div>
<p className="font-medium"> <p className="font-medium">3. Seberapa puas Anda dengan informasi yang tersedia di MediaHub Polri?</p>
3. Seberapa puas Anda dengan informasi yang tersedia di MediaHub
Polri?
</p>
<div className="space-y-3 mt-2"> <div className="space-y-3 mt-2">
{renderControllerGroup( {renderControllerGroup("infoAccuracy", "a) Akurat dan terpercaya", options.infoAccuracy)}
"infoAccuracy", {renderControllerGroup("infoCompleteness", "b) Kelengkapan berita dan informasi", options.infoCompleteness)}
"a) Akurat dan terpercaya",
options.infoAccuracy
)}
{renderControllerGroup(
"infoCompleteness",
"b) Kelengkapan berita dan informasi",
options.infoCompleteness
)}
</div> </div>
</div> </div>
{renderControllerGroup( {renderControllerGroup("usefulness", "4. Apakah Anda merasa website ini membantu dalam mendapatkan informasi terkait Polri?", options.usefulness)}
"usefulness",
"4. Apakah Anda merasa website ini membantu dalam mendapatkan informasi terkait Polri?",
options.usefulness
)}
<div> <div>
<p className="font-medium">5. Apa saran atau masukan Anda?</p> <p className="font-medium">5. Apa saran atau masukan Anda?</p>
<Controller <Controller name="suggestion" control={control} render={({ field }) => <Textarea placeholder="Tulis pesan Anda..." value={field.value} onChange={field.onChange} />} />
name="suggestion"
control={control}
render={({ field }) => (
<Textarea
placeholder="Tulis pesan Anda..."
value={field.value}
onChange={field.onChange}
/>
)}
/>
</div> </div>
<div className="flex justify-end gap-2"> <div className="flex justify-end gap-2">
@ -253,6 +159,13 @@ const UserSurveyBox = () => {
</DialogContent> </DialogContent>
</Dialog> </Dialog>
</div> </div>
{/* Kanan: Gambar survey */}
<div className="hidden lg:flex justify-center md:justify-end">
<img src="/assets/survey.png" alt="Survey Illustration" className="w-48 h-auto" />
</div>
</div>
</div>
); );
}; };

View File

@ -26,10 +26,10 @@ const WelcomePolda = () => {
return ( return (
<section className="w-full py-8 px-4 "> <section className="w-full py-8 px-4 ">
<div className="max-w-screen-xl mx-auto text-center"> <div className="">
{/* Heading */} {/* Heading */}
<h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white"> <h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white">
{t("welcome")} <span className="text-[#bb3523] dark:text-white">Polda</span> <span className="capitalize">{poldaName.replace("-", " ")}</span> <span className="text-[#bb3523] dark:text-white">{t("welcome")} Di Polda</span> <span className="capitalize text-[#bb3523] dark:text-white">{poldaName.replace("-", " ")}</span>
</h1> </h1>
<div className="w-[80%] h-1 bg-[#bb3523] mx-auto mt-2"></div> <div className="w-[80%] h-1 bg-[#bb3523] mx-auto mt-2"></div>
<p className="text-sm md:text-base text-gray-500 dark:text-gray-100 mt-4"> <p className="text-sm md:text-base text-gray-500 dark:text-gray-100 mt-4">

View File

@ -351,6 +351,7 @@
}, },
"LandingPage": { "LandingPage": {
"content": "Content", "content": "Content",
"searchCoverageHere": "Find Coverage Here...",
"new": "Latest", "new": "Latest",
"schedule": "Schedule", "schedule": "Schedule",
"index": "Index", "index": "Index",

View File

@ -356,13 +356,14 @@
"schedule": "Jadwal", "schedule": "Jadwal",
"index": "Indeks", "index": "Indeks",
"search": "Pencarian", "search": "Pencarian",
"exploration": "Eksplorasi", "exploration": "EKSPLORASI",
"and": "dan", "and": "DAN",
"download": "Unduh", "download": "DOWNLOAD",
"coverage": "Liputan Resmi Kami", "coverage": "LIPUTAN RESMI KAMI",
"officialCoverage": "Liputan resmi yang bersumber dari kegiatan Polri di Mabes dan Polda seluruh Indonesia", "officialCoverage": "Liputan resmi yang bersumber dari kegiatan Polri di Mabes dan Polda seluruh Indonesia",
"allContent": "Semua Konten", "allContent": "Semua Konten",
"searchCoverage": "Cari Liputan", "searchCoverage": "Cari Liputan",
"searchCoverageHere": "Cari Liputan Disini",
"newContent": "Konten Terbaru", "newContent": "Konten Terbaru",
"video": "Audio Visual", "video": "Audio Visual",
"audio": "Audio", "audio": "Audio",

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

BIN
public/assets/divkum.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

BIN
public/assets/line1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

BIN
public/assets/survey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

View File

@ -1,12 +1 @@
#!/bin/sh ../typescript/bin/tsc
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
else
exec node "$basedir/../typescript/bin/tsc" "$@"
fi

View File

@ -1,17 +0,0 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\typescript\bin\tsc" %*

View File

@ -1,28 +0,0 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../typescript/bin/tsc" $args
} else {
& "$basedir/node$exe" "$basedir/../typescript/bin/tsc" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../typescript/bin/tsc" $args
} else {
& "node$exe" "$basedir/../typescript/bin/tsc" $args
}
$ret=$LASTEXITCODE
}
exit $ret

View File

@ -1,12 +1 @@
#!/bin/sh ../typescript/bin/tsserver
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
else
exec node "$basedir/../typescript/bin/tsserver" "$@"
fi

View File

@ -1,17 +0,0 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\typescript\bin\tsserver" %*

View File

@ -1,28 +0,0 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../typescript/bin/tsserver" $args
} else {
& "$basedir/node$exe" "$basedir/../typescript/bin/tsserver" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../typescript/bin/tsserver" $args
} else {
& "node$exe" "$basedir/../typescript/bin/tsserver" $args
}
$ret=$LASTEXITCODE
}
exit $ret

0
vendor/ckeditor5/node_modules/typescript/bin/tsc generated vendored Normal file → Executable file
View File

0
vendor/ckeditor5/node_modules/typescript/bin/tsserver generated vendored Normal file → Executable file
View File