fixing landing page polda and satker
This commit is contained in:
parent
9ec6319b8f
commit
4a716dd637
|
|
@ -17,6 +17,8 @@ import HeroNew from "@/components/landing-page/hero-new";
|
||||||
import Navbar from "@/components/landing-page/navbar";
|
import Navbar from "@/components/landing-page/navbar";
|
||||||
import SearchSection from "@/components/landing-page/search-section";
|
import SearchSection from "@/components/landing-page/search-section";
|
||||||
import Footer from "@/components/landing-page/footer";
|
import Footer from "@/components/landing-page/footer";
|
||||||
|
import SearchSectionPolda from "@/components/landing-page/search-section-polda";
|
||||||
|
import HeroNewPolda from "@/components/landing-page/hero-new-polda";
|
||||||
|
|
||||||
const page = () => {
|
const page = () => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
|
@ -43,12 +45,10 @@ const page = () => {
|
||||||
// <ContentCategory type="" group="polda" />
|
// <ContentCategory type="" group="polda" />
|
||||||
// </div>
|
// </div>
|
||||||
<div>
|
<div>
|
||||||
<Navbar />
|
<HeroNewPolda />
|
||||||
<HeroNew group="polda" />
|
|
||||||
<div className="flex-1 ">
|
<div className="flex-1 ">
|
||||||
<SearchSection />
|
<SearchSectionPolda />
|
||||||
</div>
|
</div>
|
||||||
<Footer />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,29 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import ContentCategory from "@/components/landing-page/content-category";
|
import ContentCategory from "@/components/landing-page/content-category";
|
||||||
|
import Footer from "@/components/landing-page/footer";
|
||||||
import HeaderBannerSatker from "@/components/landing-page/header-banner-satker";
|
import HeaderBannerSatker from "@/components/landing-page/header-banner-satker";
|
||||||
|
import HeroNewSatker from "@/components/landing-page/hero-new-satker";
|
||||||
import NewContent from "@/components/landing-page/new-content";
|
import NewContent from "@/components/landing-page/new-content";
|
||||||
|
import SearchSectionSatker from "@/components/landing-page/search-section-satker";
|
||||||
import WelcomeSatker from "@/components/landing-page/welcome-satker";
|
import WelcomeSatker from "@/components/landing-page/welcome-satker";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
const page = () => {
|
const page = () => {
|
||||||
return (
|
return (
|
||||||
|
// <div>
|
||||||
|
// <HeaderBannerSatker />
|
||||||
|
// <WelcomeSatker />
|
||||||
|
// <NewContent group="satker" type="latest" />
|
||||||
|
// <NewContent group="satker" type="popular" />
|
||||||
|
// <ContentCategory group="satker" type="latest" />
|
||||||
|
// </div>
|
||||||
<div>
|
<div>
|
||||||
<HeaderBannerSatker />
|
<HeroNewSatker />
|
||||||
<WelcomeSatker />
|
<div className="flex-1 ">
|
||||||
<NewContent group="satker" type="latest" />
|
<SearchSectionSatker />
|
||||||
<NewContent group="satker" type="popular" />
|
</div>
|
||||||
<ContentCategory group="satker" type="latest" />
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,9 @@ const ContentCategory = (props: { group?: string; type: string }) => {
|
||||||
const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
|
const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="px-4 py-10">
|
<div className="px-4 lg:px-0 py-10">
|
||||||
<Reveal>
|
<Reveal>
|
||||||
<div className="flex flex-col p-4">
|
<div className="flex flex-col">
|
||||||
<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" ? (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,370 @@
|
||||||
|
import { formatDateToIndonesian, shimmer, toBase64 } from "@/utils/globals";
|
||||||
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
|
import "swiper/css/bundle";
|
||||||
|
import "swiper/css/navigation";
|
||||||
|
import { getHeroData, listStaticBanner } from "@/service/landing/landing";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useParams, usePathname, useRouter } from "next/navigation";
|
||||||
|
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel";
|
||||||
|
import { Skeleton } from "../ui/skeleton";
|
||||||
|
import Image from "next/image";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs";
|
||||||
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../ui/card";
|
||||||
|
import { Label } from "../ui/label";
|
||||||
|
import { Input } from "../ui/input";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { Textarea } from "../ui/textarea";
|
||||||
|
import { Checkbox } from "../ui/checkbox";
|
||||||
|
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../ui/dialog";
|
||||||
|
import { Autoplay, Navigation, Pagination } from "swiper/modules";
|
||||||
|
import { Swiper, SwiperClass, SwiperSlide } from "swiper/react";
|
||||||
|
import "swiper/css";
|
||||||
|
import "swiper/css/navigation";
|
||||||
|
import "swiper/css/pagination";
|
||||||
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
|
|
||||||
|
type HeroModalProps = {
|
||||||
|
onClose: () => void;
|
||||||
|
group: string;
|
||||||
|
poldaName?: string;
|
||||||
|
satkerName?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const HeroModal = ({ onClose, group, poldaName, satkerName }: HeroModalProps) => {
|
||||||
|
const [heroData, setHeroData] = useState<any>();
|
||||||
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const swiperRef = useRef<SwiperClass | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchCategories() {
|
||||||
|
const url = "https://netidhub.com/api/csrf";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fetch error: ", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchCategories();
|
||||||
|
initFetch();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.body.classList.add("overflow-hidden");
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.body.classList.remove("overflow-hidden");
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const initFetch = async () => {
|
||||||
|
if (group === "polda" && poldaName && String(poldaName).length > 1) {
|
||||||
|
const response = await listStaticBanner(poldaName);
|
||||||
|
|
||||||
|
const banners =
|
||||||
|
response?.data?.data?.map((item: any) => {
|
||||||
|
const media = item?.mediaUpload;
|
||||||
|
if (media?.fileType) {
|
||||||
|
media.fileTypeId = media.fileType.id;
|
||||||
|
}
|
||||||
|
return media;
|
||||||
|
}) || [];
|
||||||
|
|
||||||
|
console.log("banner Modal", banners);
|
||||||
|
setHeroData(banners);
|
||||||
|
} else {
|
||||||
|
console.log("Test");
|
||||||
|
setHeroData([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="fixed inset-0 flex items-center justify-center backdrop-brightness-50 z-50 ">
|
||||||
|
<div className="relative dark:bg-gray-900 rounded-lg w-[90%] md:w-[600px] p-4 shadow-none">
|
||||||
|
{heroData?.length > 0 && (
|
||||||
|
<>
|
||||||
|
<button className="absolute left-3 top-1/2 z-10 -translate-y-1/2 text-white text-3xl" onClick={() => swiperRef.current?.slidePrev()}>
|
||||||
|
<ChevronLeft />
|
||||||
|
</button>
|
||||||
|
<button className="absolute right-3 top-1/2 z-10 -translate-y-1/2 text-white text-3xl" onClick={() => swiperRef.current?.slideNext()}>
|
||||||
|
<ChevronRight />
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<Swiper pagination={{ dynamicBullets: true }} modules={[Pagination, Autoplay]} onSwiper={(swiper) => (swiperRef.current = swiper)} autoplay={{ delay: 3000 }} className="mySwiper w-full">
|
||||||
|
<div className="relative h-[310px] lg:h-[420px]">
|
||||||
|
<button onClick={onClose} className="absolute top-3 right-3 text-gray-700 dark:text-gray-300 hover:text-black dark:hover:text-white border border-white bg-white rounded-full h-8 w-8 z-10">
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{heroData && heroData.length > 0 ? (
|
||||||
|
heroData.map((list: any, index: number) => (
|
||||||
|
<SwiperSlide key={list?.id}>
|
||||||
|
<div className="relative h-[310px] lg:h-[420px]">
|
||||||
|
<Image src={list?.thumbnailLink} alt="gambar-utama" width={1920} height={1080} placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} className="w-full h-[310px] lg:h-[420px] rounded-lg object-cover" />
|
||||||
|
|
||||||
|
<div className="absolute bottom-0 left-0 right-0 bg-black/30 backdrop-brightness-50 text-white pb-4 px-4 pt-8 rounded-bl-2xl rounded-tr-2xl mx-3 mb-2">
|
||||||
|
<div className="absolute top-0 left-0 bottom-0 w-2 bg-[#bb3523] rounded-bl-lg"></div>
|
||||||
|
<span className="absolute top-0 left-0 mt-2 mb-3 mx-3 bg-[#bb3523] text-white text-xs font-semibold uppercase px-2 py-1 rounded">{list?.categoryName || "Liputan Kegiatan"}</span>
|
||||||
|
|
||||||
|
<Link href={`${locale}/image/detail/${list?.slug}`}>
|
||||||
|
<h2 className="text-lg leading-tight">{list?.title}</h2>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<p className="text-xs flex items-center gap-1 mt-2 opacity-80">
|
||||||
|
{formatDateToIndonesian(new Date(list?.createdAt))} {list?.timezone || "WIB"} |{" "}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" className="inline-block">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M11.5 18c4 0 7.46-2.22 9.24-5.5C18.96 9.22 15.5 7 11.5 7s-7.46 2.22-9.24 5.5C4.04 15.78 7.5 18 11.5 18m0-12c4.56 0 8.5 2.65 10.36 6.5C20 16.35 16.06 19 11.5 19S3 16.35 1.14 12.5C3 8.65 6.94 6 11.5 6m0 2C14 8 16 10 16 12.5S14 17 11.5 17S7 15 7 12.5S9 8 11.5 8m0 1A3.5 3.5 0 0 0 8 12.5a3.5 3.5 0 0 0 3.5 3.5a3.5 3.5 0 0 0 3.5-3.5A3.5 3.5 0 0 0 11.5 9"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
{list?.clickCount}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SwiperSlide>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center justify-center h-full">
|
||||||
|
<Image width={1920} height={1080} src="/assets/empty-data.png" alt="empty" className="h-52 w-52 my-4" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style jsx global>{`
|
||||||
|
.swiper-pagination-bullet {
|
||||||
|
background: white !important;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
.swiper-pagination-bullet-active {
|
||||||
|
background: white !important;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</Swiper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ONE_MONTH = 30 * 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
|
const HeroNewPolda = (props: { group?: string }) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const pathname = usePathname();
|
||||||
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const [isLoading, setIsLoading] = useState<any>(true);
|
||||||
|
const [heroData, setHeroData] = useState<any>();
|
||||||
|
const [content, setContent] = useState<any>();
|
||||||
|
const [showModal, setShowModal] = useState(false);
|
||||||
|
const [showSurveyModal, setShowSurveyModal] = useState(false);
|
||||||
|
const [showFormModal, setShowFormModal] = useState(false);
|
||||||
|
const poldaName = params?.polda_name;
|
||||||
|
const satkerName = params?.satker_name;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const roleId = Cookies.get("urie");
|
||||||
|
if (!roleId) {
|
||||||
|
setShowModal(true);
|
||||||
|
}
|
||||||
|
initFetch();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// const roleId = Cookies.get("urie");
|
||||||
|
// const lastShown = Cookies.get("surveyLastShown");
|
||||||
|
// const now = new Date().getTime();
|
||||||
|
|
||||||
|
// if (roleId && roleId !== "2") {
|
||||||
|
// if (!lastShown || now - parseInt(lastShown) > ONE_MONTH) {
|
||||||
|
// setShowSurveyModal(true);
|
||||||
|
// Cookies.set("surveyLastShown", now.toString(), { expires: 30 });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// initFetch();
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const roleId = Cookies.get("urie");
|
||||||
|
const lastShown = Cookies.get("surveyLastShown");
|
||||||
|
const now = new Date().getTime();
|
||||||
|
|
||||||
|
const allowedRoles = ["1", "2", "3"];
|
||||||
|
|
||||||
|
if (roleId && allowedRoles.includes(roleId)) {
|
||||||
|
if (!lastShown || now - parseInt(lastShown) > ONE_MONTH) {
|
||||||
|
setShowSurveyModal(true);
|
||||||
|
Cookies.set("surveyLastShown", now.toString(), { expires: 30 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initFetch();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchCategories() {
|
||||||
|
const url = "https://netidhub.com/api/csrf";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fetch error: ", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchCategories();
|
||||||
|
initFetch();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const initFetch = async () => {
|
||||||
|
const response = await getHeroData();
|
||||||
|
console.log(response);
|
||||||
|
let data = response?.data?.data?.content;
|
||||||
|
setHeroData(data);
|
||||||
|
|
||||||
|
if (data && props.group === "polda" && poldaName && String(poldaName)?.length > 1) {
|
||||||
|
const resStatic = await listStaticBanner(poldaName);
|
||||||
|
|
||||||
|
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
||||||
|
const media = resStatic?.data.data[i]?.mediaUpload;
|
||||||
|
media.fileTypeId = media.fileType?.id;
|
||||||
|
data = data.filter((item: any) => item.id != media.id);
|
||||||
|
data.splice(0, 0, media);
|
||||||
|
}
|
||||||
|
|
||||||
|
setContent(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const shimmer = (w: number, h: number) => `
|
||||||
|
<svg width="${w}" height="${h}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="g">
|
||||||
|
<stop stop-color="#bcbcbd" offset="20%" />
|
||||||
|
<stop stop-color="#f9fafb" offset="50%" />
|
||||||
|
<stop stop-color="#bcbcbd" offset="70%" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="${w}" height="${h}" fill="#bcbcbd" />
|
||||||
|
<rect id="r" width="${w}" height="${h}" fill="url(#g)" />
|
||||||
|
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
|
||||||
|
</svg>`;
|
||||||
|
|
||||||
|
const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex items-start justify-center mx-auto w-auto">
|
||||||
|
<div className="relative">{showModal && <HeroModal onClose={() => setShowModal(false)} group="polda" />}</div>
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex flex-col space-y-3 mx-auto w-full lg:w-2/3">
|
||||||
|
<Skeleton className="h-[310px] lg:h-[420px]" />
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Skeleton className="h-4 w-[250px]" />
|
||||||
|
<Skeleton className="h-4 w-[200px]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="relative w-full h-full">
|
||||||
|
<Carousel className="lg:w-full lg:h-full">
|
||||||
|
<CarouselContent>
|
||||||
|
{content?.map((list: any) => (
|
||||||
|
<CarouselItem key={list?.id}>
|
||||||
|
<div className="relative h-[310px] lg:h-[700px] mt-1">
|
||||||
|
<Image src={list?.thumbnailLink} alt="gambar-utama" width={1920} height={1080} placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} className="w-full h-[320px] lg:h-[700px] object-cover" />
|
||||||
|
<div className="absolute inset-0 bg-black bg-opacity-40" />
|
||||||
|
|
||||||
|
<Link
|
||||||
|
href={
|
||||||
|
Number(list?.fileTypeId) == 1
|
||||||
|
? `${locale}/image/detail/${list?.slug}`
|
||||||
|
: Number(list?.fileTypeId) == 2
|
||||||
|
? `${locale}/video/detail/${list?.slug}`
|
||||||
|
: Number(list?.fileTypeId) == 3
|
||||||
|
? `${locale}/document/detail/${list?.slug}`
|
||||||
|
: `${locale}/audio/detail/${list?.slug}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="absolute bottom-20 left-32 w-[60%] lg:w-[45%] text-white px-4 pt-10 pb-4">
|
||||||
|
<span className="absolute top-0 left-3 text-red-600 text-lg font-bold uppercase px-1 py-2 rounded">{list?.categoryName || "Liputan Kegiatan"}</span>
|
||||||
|
<h2 className="text-xl font-bold leading-tight">{list?.title}</h2>
|
||||||
|
<p className="text-base flex items-center gap-1 mt-2 opacity-80">
|
||||||
|
{formatDateToIndonesian(new Date(list?.createdAt))} {list?.timezone || "WIB"} | 👁 {list?.clickCount}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</CarouselItem>
|
||||||
|
))}
|
||||||
|
</CarouselContent>
|
||||||
|
</Carousel>
|
||||||
|
|
||||||
|
<div className="hidden lg:flex flex-col gap-3 absolute bottom-4 right-4 w-[520px] bg-black/40 p-4 rounded-lg z-10">
|
||||||
|
{heroData?.slice(0, 3).map((item: any) => (
|
||||||
|
<li key={item?.id} className="flex gap-4 flex-row lg:w-full mx-2">
|
||||||
|
<div className="flex-shrink-0 w-32 rounded-lg">
|
||||||
|
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={720} height={480} src={item?.thumbnailLink} alt={item?.title} className="w-full h-[100px] object-cover rounded-lg" />
|
||||||
|
</div>
|
||||||
|
<div className="w-[280px] lg:w-[200px]">
|
||||||
|
<Link
|
||||||
|
href={
|
||||||
|
Number(item?.fileTypeId) == 1
|
||||||
|
? `${locale}/image/detail/${item?.slug}`
|
||||||
|
: Number(item?.fileTypeId) == 2
|
||||||
|
? `${locale}/video/detail/${item?.slug}`
|
||||||
|
: Number(item?.fileTypeId) == 3
|
||||||
|
? `${locale}/document/detail/${item?.slug}`
|
||||||
|
: `${locale}/audio/detail/${item?.slug}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span className="py-1 rounded-lg flex text-red-600 font-bold uppercase w-fit">{item?.categoryName}</span>
|
||||||
|
<h3 className="text-base text-white font-bold h-6 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible">{item?.title}</h3>
|
||||||
|
<p className="text-[10px] flex flex-row items-center gap-1 text-white mt-1">
|
||||||
|
{formatDateToIndonesian(new Date(item?.createdAt))} {item?.timezone || "WIB"} |{" "}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M11.5 18c4 0 7.46-2.22 9.24-5.5C18.96 9.22 15.5 7 11.5 7s-7.46 2.22-9.24 5.5C4.04 15.78 7.5 18 11.5 18m0-12c4.56 0 8.5 2.65 10.36 6.5C20 16.35 16.06 19 11.5 19S3 16.35 1.14 12.5C3 8.65 6.94 6 11.5 6m0 2C14 8 16 10 16 12.5S14 17 11.5 17S7 15 7 12.5S9 8 11.5 8m0 1A3.5 3.5 0 0 0 8 12.5a3.5 3.5 0 0 0 3.5 3.5a3.5 3.5 0 0 0 3.5-3.5A3.5 3.5 0 0 0 11.5 9"
|
||||||
|
/>
|
||||||
|
</svg>{" "}
|
||||||
|
{item?.clickCount}
|
||||||
|
</p>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HeroNewPolda;
|
||||||
|
|
@ -0,0 +1,370 @@
|
||||||
|
import { formatDateToIndonesian, shimmer, toBase64 } from "@/utils/globals";
|
||||||
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
|
import "swiper/css/bundle";
|
||||||
|
import "swiper/css/navigation";
|
||||||
|
import { getHeroData, listStaticBanner } from "@/service/landing/landing";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useParams, usePathname, useRouter } from "next/navigation";
|
||||||
|
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel";
|
||||||
|
import { Skeleton } from "../ui/skeleton";
|
||||||
|
import Image from "next/image";
|
||||||
|
import Cookies from "js-cookie";
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs";
|
||||||
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../ui/card";
|
||||||
|
import { Label } from "../ui/label";
|
||||||
|
import { Input } from "../ui/input";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { Textarea } from "../ui/textarea";
|
||||||
|
import { Checkbox } from "../ui/checkbox";
|
||||||
|
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../ui/dialog";
|
||||||
|
import { Autoplay, Navigation, Pagination } from "swiper/modules";
|
||||||
|
import { Swiper, SwiperClass, SwiperSlide } from "swiper/react";
|
||||||
|
import "swiper/css";
|
||||||
|
import "swiper/css/navigation";
|
||||||
|
import "swiper/css/pagination";
|
||||||
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
|
|
||||||
|
type HeroModalProps = {
|
||||||
|
onClose: () => void;
|
||||||
|
group: string;
|
||||||
|
poldaName?: string;
|
||||||
|
satkerName?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const HeroModal = ({ onClose, group, poldaName, satkerName }: HeroModalProps) => {
|
||||||
|
const [heroData, setHeroData] = useState<any>();
|
||||||
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const swiperRef = useRef<SwiperClass | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchCategories() {
|
||||||
|
const url = "https://netidhub.com/api/csrf";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fetch error: ", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchCategories();
|
||||||
|
initFetch();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.body.classList.add("overflow-hidden");
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.body.classList.remove("overflow-hidden");
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const initFetch = async () => {
|
||||||
|
if (group === "satker" && satkerName && String(satkerName).length > 1) {
|
||||||
|
const response = await listStaticBanner(satkerName);
|
||||||
|
|
||||||
|
const banners =
|
||||||
|
response?.data?.data?.map((item: any) => {
|
||||||
|
const media = item?.mediaUpload;
|
||||||
|
if (media?.fileType) {
|
||||||
|
media.fileTypeId = media.fileType.id;
|
||||||
|
}
|
||||||
|
return media;
|
||||||
|
}) || [];
|
||||||
|
|
||||||
|
console.log("banner Modal", banners);
|
||||||
|
setHeroData(banners);
|
||||||
|
} else {
|
||||||
|
console.log("Test");
|
||||||
|
setHeroData([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="fixed inset-0 flex items-center justify-center backdrop-brightness-50 z-50 ">
|
||||||
|
<div className="relative dark:bg-gray-900 rounded-lg w-[90%] md:w-[600px] p-4 shadow-none">
|
||||||
|
{heroData?.length > 0 && (
|
||||||
|
<>
|
||||||
|
<button className="absolute left-3 top-1/2 z-10 -translate-y-1/2 text-white text-3xl" onClick={() => swiperRef.current?.slidePrev()}>
|
||||||
|
<ChevronLeft />
|
||||||
|
</button>
|
||||||
|
<button className="absolute right-3 top-1/2 z-10 -translate-y-1/2 text-white text-3xl" onClick={() => swiperRef.current?.slideNext()}>
|
||||||
|
<ChevronRight />
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<Swiper pagination={{ dynamicBullets: true }} modules={[Pagination, Autoplay]} onSwiper={(swiper) => (swiperRef.current = swiper)} autoplay={{ delay: 3000 }} className="mySwiper w-full">
|
||||||
|
<div className="relative h-[310px] lg:h-[420px]">
|
||||||
|
<button onClick={onClose} className="absolute top-3 right-3 text-gray-700 dark:text-gray-300 hover:text-black dark:hover:text-white border border-white bg-white rounded-full h-8 w-8 z-10">
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{heroData && heroData.length > 0 ? (
|
||||||
|
heroData.map((list: any, index: number) => (
|
||||||
|
<SwiperSlide key={list?.id}>
|
||||||
|
<div className="relative h-[310px] lg:h-[420px]">
|
||||||
|
<Image src={list?.thumbnailLink} alt="gambar-utama" width={1920} height={1080} placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} className="w-full h-[310px] lg:h-[420px] rounded-lg object-cover" />
|
||||||
|
|
||||||
|
<div className="absolute bottom-0 left-0 right-0 bg-black/30 backdrop-brightness-50 text-white pb-4 px-4 pt-8 rounded-bl-2xl rounded-tr-2xl mx-3 mb-2">
|
||||||
|
<div className="absolute top-0 left-0 bottom-0 w-2 bg-[#bb3523] rounded-bl-lg"></div>
|
||||||
|
<span className="absolute top-0 left-0 mt-2 mb-3 mx-3 bg-[#bb3523] text-white text-xs font-semibold uppercase px-2 py-1 rounded">{list?.categoryName || "Liputan Kegiatan"}</span>
|
||||||
|
|
||||||
|
<Link href={`${locale}/image/detail/${list?.slug}`}>
|
||||||
|
<h2 className="text-lg leading-tight">{list?.title}</h2>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<p className="text-xs flex items-center gap-1 mt-2 opacity-80">
|
||||||
|
{formatDateToIndonesian(new Date(list?.createdAt))} {list?.timezone || "WIB"} |{" "}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" className="inline-block">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M11.5 18c4 0 7.46-2.22 9.24-5.5C18.96 9.22 15.5 7 11.5 7s-7.46 2.22-9.24 5.5C4.04 15.78 7.5 18 11.5 18m0-12c4.56 0 8.5 2.65 10.36 6.5C20 16.35 16.06 19 11.5 19S3 16.35 1.14 12.5C3 8.65 6.94 6 11.5 6m0 2C14 8 16 10 16 12.5S14 17 11.5 17S7 15 7 12.5S9 8 11.5 8m0 1A3.5 3.5 0 0 0 8 12.5a3.5 3.5 0 0 0 3.5 3.5a3.5 3.5 0 0 0 3.5-3.5A3.5 3.5 0 0 0 11.5 9"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
{list?.clickCount}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SwiperSlide>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center justify-center h-full">
|
||||||
|
<Image width={1920} height={1080} src="/assets/empty-data.png" alt="empty" className="h-52 w-52 my-4" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style jsx global>{`
|
||||||
|
.swiper-pagination-bullet {
|
||||||
|
background: white !important;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
.swiper-pagination-bullet-active {
|
||||||
|
background: white !important;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</Swiper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ONE_MONTH = 30 * 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
|
const HeroNewSatker = (props: { group?: string }) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const pathname = usePathname();
|
||||||
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const [isLoading, setIsLoading] = useState<any>(true);
|
||||||
|
const [heroData, setHeroData] = useState<any>();
|
||||||
|
const [content, setContent] = useState<any>();
|
||||||
|
const [showModal, setShowModal] = useState(false);
|
||||||
|
const [showSurveyModal, setShowSurveyModal] = useState(false);
|
||||||
|
const [showFormModal, setShowFormModal] = useState(false);
|
||||||
|
const poldaName = params?.polda_name;
|
||||||
|
const satkerName = params?.satker_name;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setIsLoading(false);
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const roleId = Cookies.get("urie");
|
||||||
|
if (!roleId) {
|
||||||
|
setShowModal(true);
|
||||||
|
}
|
||||||
|
initFetch();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// const roleId = Cookies.get("urie");
|
||||||
|
// const lastShown = Cookies.get("surveyLastShown");
|
||||||
|
// const now = new Date().getTime();
|
||||||
|
|
||||||
|
// if (roleId && roleId !== "2") {
|
||||||
|
// if (!lastShown || now - parseInt(lastShown) > ONE_MONTH) {
|
||||||
|
// setShowSurveyModal(true);
|
||||||
|
// Cookies.set("surveyLastShown", now.toString(), { expires: 30 });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// initFetch();
|
||||||
|
// }, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const roleId = Cookies.get("urie");
|
||||||
|
const lastShown = Cookies.get("surveyLastShown");
|
||||||
|
const now = new Date().getTime();
|
||||||
|
|
||||||
|
const allowedRoles = ["1", "2", "3"];
|
||||||
|
|
||||||
|
if (roleId && allowedRoles.includes(roleId)) {
|
||||||
|
if (!lastShown || now - parseInt(lastShown) > ONE_MONTH) {
|
||||||
|
setShowSurveyModal(true);
|
||||||
|
Cookies.set("surveyLastShown", now.toString(), { expires: 30 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initFetch();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchCategories() {
|
||||||
|
const url = "https://netidhub.com/api/csrf";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fetch error: ", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchCategories();
|
||||||
|
initFetch();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const initFetch = async () => {
|
||||||
|
const response = await getHeroData();
|
||||||
|
console.log(response);
|
||||||
|
let data = response?.data?.data?.content;
|
||||||
|
setHeroData(data);
|
||||||
|
|
||||||
|
if (data && props.group === "satker" && satkerName && String(satkerName)?.length > 1) {
|
||||||
|
const resStatic = await listStaticBanner(satkerName);
|
||||||
|
|
||||||
|
for (let i = 0; i < resStatic?.data?.data?.length; i++) {
|
||||||
|
const media = resStatic?.data.data[i]?.mediaUpload;
|
||||||
|
media.fileTypeId = media.fileType?.id;
|
||||||
|
data = data.filter((item: any) => item.id != media.id);
|
||||||
|
data.splice(0, 0, media);
|
||||||
|
}
|
||||||
|
|
||||||
|
setContent(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const shimmer = (w: number, h: number) => `
|
||||||
|
<svg width="${w}" height="${h}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="g">
|
||||||
|
<stop stop-color="#bcbcbd" offset="20%" />
|
||||||
|
<stop stop-color="#f9fafb" offset="50%" />
|
||||||
|
<stop stop-color="#bcbcbd" offset="70%" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="${w}" height="${h}" fill="#bcbcbd" />
|
||||||
|
<rect id="r" width="${w}" height="${h}" fill="url(#g)" />
|
||||||
|
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
|
||||||
|
</svg>`;
|
||||||
|
|
||||||
|
const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex items-start justify-center mx-auto w-auto">
|
||||||
|
<div className="relative">{showModal && <HeroModal onClose={() => setShowModal(false)} group="satker" />}</div>
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="flex flex-col space-y-3 mx-auto w-full lg:w-2/3">
|
||||||
|
<Skeleton className="h-[310px] lg:h-[420px]" />
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Skeleton className="h-4 w-[250px]" />
|
||||||
|
<Skeleton className="h-4 w-[200px]" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="relative w-full h-full">
|
||||||
|
<Carousel className="lg:w-full lg:h-full">
|
||||||
|
<CarouselContent>
|
||||||
|
{content?.map((list: any) => (
|
||||||
|
<CarouselItem key={list?.id}>
|
||||||
|
<div className="relative h-[310px] lg:h-[700px] mt-1">
|
||||||
|
<Image src={list?.thumbnailLink} alt="gambar-utama" width={1920} height={1080} placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} className="w-full h-[320px] lg:h-[700px] object-cover" />
|
||||||
|
<div className="absolute inset-0 bg-black bg-opacity-40" />
|
||||||
|
|
||||||
|
<Link
|
||||||
|
href={
|
||||||
|
Number(list?.fileTypeId) == 1
|
||||||
|
? `${locale}/image/detail/${list?.slug}`
|
||||||
|
: Number(list?.fileTypeId) == 2
|
||||||
|
? `${locale}/video/detail/${list?.slug}`
|
||||||
|
: Number(list?.fileTypeId) == 3
|
||||||
|
? `${locale}/document/detail/${list?.slug}`
|
||||||
|
: `${locale}/audio/detail/${list?.slug}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="absolute bottom-20 left-32 w-[60%] lg:w-[45%] text-white px-4 pt-10 pb-4">
|
||||||
|
<span className="absolute top-0 left-3 text-red-600 text-lg font-bold uppercase px-1 py-2 rounded">{list?.categoryName || "Liputan Kegiatan"}</span>
|
||||||
|
<h2 className="text-xl font-bold leading-tight">{list?.title}</h2>
|
||||||
|
<p className="text-base flex items-center gap-1 mt-2 opacity-80">
|
||||||
|
{formatDateToIndonesian(new Date(list?.createdAt))} {list?.timezone || "WIB"} | 👁 {list?.clickCount}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</CarouselItem>
|
||||||
|
))}
|
||||||
|
</CarouselContent>
|
||||||
|
</Carousel>
|
||||||
|
|
||||||
|
<div className="hidden lg:flex flex-col gap-3 absolute bottom-4 right-4 w-[520px] bg-black/40 p-4 rounded-lg z-10">
|
||||||
|
{heroData?.slice(0, 3).map((item: any) => (
|
||||||
|
<li key={item?.id} className="flex gap-4 flex-row lg:w-full mx-2">
|
||||||
|
<div className="flex-shrink-0 w-32 rounded-lg">
|
||||||
|
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={720} height={480} src={item?.thumbnailLink} alt={item?.title} className="w-full h-[100px] object-cover rounded-lg" />
|
||||||
|
</div>
|
||||||
|
<div className="w-[280px] lg:w-[200px]">
|
||||||
|
<Link
|
||||||
|
href={
|
||||||
|
Number(item?.fileTypeId) == 1
|
||||||
|
? `${locale}/image/detail/${item?.slug}`
|
||||||
|
: Number(item?.fileTypeId) == 2
|
||||||
|
? `${locale}/video/detail/${item?.slug}`
|
||||||
|
: Number(item?.fileTypeId) == 3
|
||||||
|
? `${locale}/document/detail/${item?.slug}`
|
||||||
|
: `${locale}/audio/detail/${item?.slug}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span className="py-1 rounded-lg flex text-red-600 font-bold uppercase w-fit">{item?.categoryName}</span>
|
||||||
|
<h3 className="text-base text-white font-bold h-6 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible">{item?.title}</h3>
|
||||||
|
<p className="text-[10px] flex flex-row items-center gap-1 text-white mt-1">
|
||||||
|
{formatDateToIndonesian(new Date(item?.createdAt))} {item?.timezone || "WIB"} |{" "}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M11.5 18c4 0 7.46-2.22 9.24-5.5C18.96 9.22 15.5 7 11.5 7s-7.46 2.22-9.24 5.5C4.04 15.78 7.5 18 11.5 18m0-12c4.56 0 8.5 2.65 10.36 6.5C20 16.35 16.06 19 11.5 19S3 16.35 1.14 12.5C3 8.65 6.94 6 11.5 6m0 2C14 8 16 10 16 12.5S14 17 11.5 17S7 15 7 12.5S9 8 11.5 8m0 1A3.5 3.5 0 0 0 8 12.5a3.5 3.5 0 0 0 3.5 3.5a3.5 3.5 0 0 0 3.5-3.5A3.5 3.5 0 0 0 11.5 9"
|
||||||
|
/>
|
||||||
|
</svg>{" "}
|
||||||
|
{item?.clickCount}
|
||||||
|
</p>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HeroNewSatker;
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -92,9 +92,9 @@ const NewContent = (props: { group: string; type: string }) => {
|
||||||
const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
|
const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="px-4 py-4">
|
<div className="px-4 lg:px-0 py-4">
|
||||||
<Reveal>
|
<Reveal>
|
||||||
<div className="flex flex-col p-4">
|
<div className="flex flex-col">
|
||||||
<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" ? (
|
||||||
<>
|
<>
|
||||||
|
|
@ -194,8 +194,8 @@ const NewContent = (props: { group: string; type: string }) => {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CarouselPrevious className="hover:bg-black" />
|
<CarouselPrevious className="hover:bg-black ml-2" />
|
||||||
<CarouselNext className="hover:bg-black -mr-6" />
|
<CarouselNext className="hover:bg-black mr-2" />
|
||||||
</Carousel>
|
</Carousel>
|
||||||
) : (
|
) : (
|
||||||
<p className="flex items-center justify-center">
|
<p className="flex items-center justify-center">
|
||||||
|
|
@ -241,8 +241,8 @@ const NewContent = (props: { group: string; type: string }) => {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CarouselPrevious />
|
<CarouselPrevious className="hover:bg-black ml-2" />
|
||||||
<CarouselNext />
|
<CarouselNext className="hover:bg-black mr-2" />
|
||||||
</Carousel>
|
</Carousel>
|
||||||
) : (
|
) : (
|
||||||
<p className="flex items-center justify-center">
|
<p className="flex items-center justify-center">
|
||||||
|
|
@ -300,8 +300,8 @@ const NewContent = (props: { group: string; type: string }) => {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CarouselPrevious className="hover:bg-black" />
|
<CarouselPrevious className="hover:bg-black ml-2" />
|
||||||
<CarouselNext className="hover:bg-black -mr-6" />
|
<CarouselNext className="hover:bg-black mr-2" />
|
||||||
</Carousel>
|
</Carousel>
|
||||||
) : (
|
) : (
|
||||||
<p className="flex items-center justify-center">
|
<p className="flex items-center justify-center">
|
||||||
|
|
@ -364,8 +364,8 @@ const NewContent = (props: { group: string; type: string }) => {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CarouselPrevious />
|
<CarouselPrevious className="hover:bg-black ml-2" />
|
||||||
<CarouselNext />
|
<CarouselNext className="hover:bg-black mr-2" />
|
||||||
</Carousel>
|
</Carousel>
|
||||||
) : (
|
) : (
|
||||||
<p className="flex items-center justify-center">
|
<p className="flex items-center justify-center">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import Image from "next/image";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
|
||||||
|
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 Bangka Belitung", slug: "bangka-belitung", logo: "/logo/polda/polda-bangkabelitung.png" },
|
||||||
|
{ name: "Polda Banten", slug: "banten", 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", slug: "jawa-tengah", logo: "/logo/polda/polda-jawatengah.png" },
|
||||||
|
{ name: "Polda Jawa Timur", slug: "jawa-timur", logo: "/logo/polda/polda-jawatimur.png" },
|
||||||
|
{ name: "Polda Kalimantan Barat", slug: "kalimantan-barat", logo: "/logo/polda/polda-kalbar.png" },
|
||||||
|
{ name: "Polda Kalimantan Selatan", slug: "kalimantan-selatan", logo: "/logo/polda/polda-kalsel.png" },
|
||||||
|
{ name: "Polda Kalimantan Tengah", slug: "kalimantan-tengah", logo: "/logo/polda/polda-kalteng.png" },
|
||||||
|
{ name: "Polda Kalimantan Timur", slug: "kalimantan-timur", logo: "/logo/polda/polda-kaltim.png" },
|
||||||
|
{ name: "Polda Kalimantan Utara", slug: "kaltara", logo: "/logo/polda/polda-kaltara.png" },
|
||||||
|
{ name: "Polda Kepulauan Riau", slug: "kepulauan-riau", logo: "/logo/polda/polda-kepri.png" },
|
||||||
|
{ name: "Polda Lampung", slug: "lampung", logo: "/logo/polda/polda-lampung.png" },
|
||||||
|
{ name: "Polda Maluku", slug: "maluku", 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", slug: "sulawesi-barat", logo: "/logo/polda/polda-sulbar.png" },
|
||||||
|
{ name: "Polda Sulawesi Selatan", slug: "sulawesi-selatan", logo: "/logo/polda/polda-sulsel.png" },
|
||||||
|
{ name: "Polda Sulawesi Tengah", slug: "sulawesi-tengah", logo: "/logo/polda/polda-sulawesi-tengah.png" },
|
||||||
|
{ name: "Polda Sulawesi Tenggara", slug: "sulawesi-tenggara", logo: "/logo/polda/polda-sulawesi-tenggara.png" },
|
||||||
|
{ name: "Polda Sulawesi Utara", slug: "sulawesi-utara", logo: "/logo/polda/polda-sulawesi-utara.png" },
|
||||||
|
{ name: "Polda Sumatera Barat", slug: "sumatera-barat", logo: "/logo/polda/polda-sumatera-barat.png" },
|
||||||
|
{ name: "Polda Sumatera Selatan", slug: "sumatera-selatan", logo: "/logo/polda/polda-sumsel.png" },
|
||||||
|
{ name: "Polda Sumatera Utara", slug: "sumatera-utara", logo: "/logo/polda/polda-sumut.png" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function PoldaLogo() {
|
||||||
|
const params = useParams();
|
||||||
|
const poldaSlug = params?.slug ?? ""; // pastikan kamu di route [slug] atau [poldaSlug]
|
||||||
|
|
||||||
|
const region = regions.find((r) => r.slug === poldaSlug);
|
||||||
|
const logoSrc = region?.logo ?? "/logo/polda/default.png";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center items-center my-6">
|
||||||
|
<Image src={logoSrc} alt={region?.name || "Logo Polda"} width={128} height={128} className="object-contain" priority />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -54,15 +54,17 @@ const ScrollableContentPolda = () => {
|
||||||
<div className="">
|
<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-[#c03724] dark:text-white">
|
<span className="text-[#c03724] dark:text-white">
|
||||||
{t("welcome")} DI POLDA {poldaName?.replace("-", " ")}
|
{t("welcome")} Polda {poldaName?.replace("-", " ")}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-[#c03724] dark:text-white">
|
{/* <span className="text-[#c03724] dark:text-white">
|
||||||
{t("download")} {t("coverage")}
|
{t("download")} {t("coverage")}
|
||||||
</span>{" "}
|
</span>{" "} */}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="w-[10%] h-1 bg-[#bb3523] mt-2"></div>
|
<div className="w-[10%] h-1 bg-[#bb3523] mt-2"></div>
|
||||||
<div className="w-full h-1 bg-[#bb3523] mx-auto"></div>
|
<div className="w-full h-1 bg-[#bb3523] mx-auto"></div>
|
||||||
<p className="text-sm md:text-base text-black dark:text-gray-100 mt-4">{t("officialCoverage")}</p>
|
<p className="text-sm md:text-base text-black dark:text-gray-100 mt-4">
|
||||||
|
{t("officialPolda")} {poldaName?.replace("-", " ")}
|
||||||
|
</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">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
import search from "@/app/[locale]/(protected)/app/chat/components/search";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { useParams, useRouter } from "next/navigation";
|
||||||
|
import router from "next/router";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||||
|
import Image from "next/image";
|
||||||
|
import { getHeroData } from "@/service/landing/landing";
|
||||||
|
import { title } from "process";
|
||||||
|
import { htmlToString } from "@/utils/globals";
|
||||||
|
import { Link } from "@/i18n/routing";
|
||||||
|
|
||||||
|
const ScrollableContentSatker = () => {
|
||||||
|
const [contentType, setContentType] = useState("all");
|
||||||
|
const [search, setSearch] = useState("");
|
||||||
|
const router = useRouter();
|
||||||
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
const t = useTranslations("LandingPage");
|
||||||
|
const satkerName: any = params?.satker_name;
|
||||||
|
const [content, setContent] = useState<any>();
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchCategories() {
|
||||||
|
const url = "https://netidhub.com/api/csrf";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fetch error: ", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchCategories();
|
||||||
|
initFetch();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const initFetch = async () => {
|
||||||
|
const response = await getHeroData();
|
||||||
|
console.log(response);
|
||||||
|
let data = response?.data?.data?.content;
|
||||||
|
|
||||||
|
setContent(data);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="">
|
||||||
|
<h1 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-white">
|
||||||
|
<span className="text-[#c03724] dark:text-white">
|
||||||
|
{t("welcome")} Polda {satkerName?.replace("-", " ")}
|
||||||
|
</span>
|
||||||
|
{/* <span className="text-[#c03724] dark:text-white">
|
||||||
|
{t("download")} {t("coverage")}
|
||||||
|
</span>{" "} */}
|
||||||
|
</h1>
|
||||||
|
<div className="w-[10%] h-1 bg-[#bb3523] mt-2"></div>
|
||||||
|
<div className="w-full h-1 bg-[#bb3523] mx-auto"></div>
|
||||||
|
<p className="text-sm md:text-base text-black dark:text-gray-100 mt-4">
|
||||||
|
{t("officialPolda")} {satkerName?.replace("-", " ")}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<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">
|
||||||
|
<Select value={contentType} onValueChange={setContentType}>
|
||||||
|
<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 />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectItem value="all">{t("allContent")}</SelectItem>
|
||||||
|
<SelectItem value="image">{t("image")}</SelectItem>
|
||||||
|
<SelectItem value="video">{t("video")}</SelectItem>
|
||||||
|
<SelectItem value="document">{t("text")}</SelectItem>
|
||||||
|
<SelectItem value="audio">{t("audio")}</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<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">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
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"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<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)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<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">
|
||||||
|
{t("searchCoverage")}
|
||||||
|
<Icon icon="ri:arrow-right-s-line" fontSize={20} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ScrollableContentSatker;
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
import search from "@/app/[locale]/(protected)/app/chat/components/search";
|
||||||
|
import { Select, SelectTrigger, SelectValue, SelectContent, SelectGroup, SelectItem } from "@radix-ui/react-select";
|
||||||
|
import { Icon } from "lucide-react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import router from "next/router";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import ScrollableContent from "./search-section-new";
|
||||||
|
import NewContent from "./new-content";
|
||||||
|
import ContentCategory from "./content-category";
|
||||||
|
import AreaCoverageWorkUnits from "./area-coverage-and-work-units";
|
||||||
|
import EventCalender from "./event-calender";
|
||||||
|
import UserSurveyBox from "./survey-box";
|
||||||
|
import ScrollableContentPolda from "./scrollable-content-polda";
|
||||||
|
|
||||||
|
const LeftBanner = () => (
|
||||||
|
<div className="sticky top-0 space-y-4">
|
||||||
|
<img src="/images/all-img/kiri1.png" alt="Banner Kiri 1" />
|
||||||
|
<img src="/images/all-img/kiri2.png" alt="Banner Kiri 2" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const RightBanner = () => (
|
||||||
|
<div className="sticky top-0 space-y-4">
|
||||||
|
<img src="/images/all-img/kanan2.png" alt="Banner Kanan 1" />
|
||||||
|
<img src="/images/all-img/kanan1.png" alt="Banner Kanan 2" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const SearchSectionPolda = () => {
|
||||||
|
const [contentType, setContentType] = useState("all");
|
||||||
|
const [search, setSearch] = useState("");
|
||||||
|
const router = useRouter();
|
||||||
|
const t = useTranslations("LandingPage");
|
||||||
|
return (
|
||||||
|
<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">
|
||||||
|
<LeftBanner />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full xl:w-[70%] px-4 py-8 bg-white">
|
||||||
|
<ScrollableContentPolda />
|
||||||
|
<NewContent group="polda" type="latest" />
|
||||||
|
<NewContent group="polda" type="popular" />
|
||||||
|
<ContentCategory group="polda" type="popular" />
|
||||||
|
<AreaCoverageWorkUnits />
|
||||||
|
<EventCalender />
|
||||||
|
<UserSurveyBox />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="hidden xl:block w-[15%] pl-4 py-5 sticky top-[150px] space-y-4 self-start">
|
||||||
|
<RightBanner />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SearchSectionPolda;
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
import search from "@/app/[locale]/(protected)/app/chat/components/search";
|
||||||
|
import { Select, SelectTrigger, SelectValue, SelectContent, SelectGroup, SelectItem } from "@radix-ui/react-select";
|
||||||
|
import { Icon } from "lucide-react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import router from "next/router";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import ScrollableContent from "./search-section-new";
|
||||||
|
import NewContent from "./new-content";
|
||||||
|
import ContentCategory from "./content-category";
|
||||||
|
import AreaCoverageWorkUnits from "./area-coverage-and-work-units";
|
||||||
|
import EventCalender from "./event-calender";
|
||||||
|
import UserSurveyBox from "./survey-box";
|
||||||
|
import ScrollableContentPolda from "./scrollable-content-polda";
|
||||||
|
import ScrollableContentSatker from "./scrollable-content-satker";
|
||||||
|
|
||||||
|
const LeftBanner = () => (
|
||||||
|
<div className="sticky top-0 space-y-4">
|
||||||
|
<img src="/images/all-img/kiri1.png" alt="Banner Kiri 1" />
|
||||||
|
<img src="/images/all-img/kiri2.png" alt="Banner Kiri 2" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const RightBanner = () => (
|
||||||
|
<div className="sticky top-0 space-y-4">
|
||||||
|
<img src="/images/all-img/kanan2.png" alt="Banner Kanan 1" />
|
||||||
|
<img src="/images/all-img/kanan1.png" alt="Banner Kanan 2" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const SearchSectionSatker = () => {
|
||||||
|
const [contentType, setContentType] = useState("all");
|
||||||
|
const [search, setSearch] = useState("");
|
||||||
|
const router = useRouter();
|
||||||
|
const t = useTranslations("LandingPage");
|
||||||
|
return (
|
||||||
|
<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">
|
||||||
|
<LeftBanner />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full xl:w-[70%] px-4 py-8 bg-white">
|
||||||
|
<ScrollableContentSatker />
|
||||||
|
<NewContent group="satker" type="latest" />
|
||||||
|
<NewContent group="satker" type="popular" />
|
||||||
|
<ContentCategory group="satker" type="popular" />
|
||||||
|
<AreaCoverageWorkUnits />
|
||||||
|
<EventCalender />
|
||||||
|
<UserSurveyBox />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="hidden xl:block w-[15%] pl-4 py-5 sticky top-[150px] space-y-4 self-start">
|
||||||
|
<RightBanner />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SearchSectionSatker;
|
||||||
|
|
@ -39,10 +39,10 @@ const SearchSection = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full xl:w-[70%] px-4 py-8 bg-white">
|
<div className="w-full xl:w-[70%] px-4 py-8 bg-white">
|
||||||
<ScrollableContentPolda />
|
<ScrollableContent />
|
||||||
<NewContent group="polda" type="latest" />
|
<NewContent group="mabes" type="latest" />
|
||||||
<NewContent group="polda" type="popular" />
|
<NewContent group="mabes" type="popular" />
|
||||||
<ContentCategory group="polda" type="popular" />
|
<ContentCategory group="mabes" type="popular" />
|
||||||
<AreaCoverageWorkUnits />
|
<AreaCoverageWorkUnits />
|
||||||
<EventCalender />
|
<EventCalender />
|
||||||
<UserSurveyBox />
|
<UserSurveyBox />
|
||||||
|
|
|
||||||
|
|
@ -363,6 +363,7 @@
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"coverage": "Our Official Coverage",
|
"coverage": "Our Official Coverage",
|
||||||
"officialCoverage": "Official coverage sourced from Polri activities at the National Police Headquarters and Regional Police throughout Indonesia",
|
"officialCoverage": "Official coverage sourced from Polri activities at the National Police Headquarters and Regional Police throughout Indonesia",
|
||||||
|
"officialPolda": "Official Coverage Sourced From Police Activities At Polda",
|
||||||
"allContent": "All Content",
|
"allContent": "All Content",
|
||||||
"searchCoverage": "Search Coverage",
|
"searchCoverage": "Search Coverage",
|
||||||
"newContent": "Latest Content",
|
"newContent": "Latest Content",
|
||||||
|
|
|
||||||
|
|
@ -363,6 +363,7 @@
|
||||||
"download": "DOWNLOAD",
|
"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",
|
||||||
|
"officialPolda": "Liputan Resmi Yang Bersumber Dari Kegiatan Polri Di Polda",
|
||||||
"allContent": "Semua Konten",
|
"allContent": "Semua Konten",
|
||||||
"searchCoverage": "Cari Liputan",
|
"searchCoverage": "Cari Liputan",
|
||||||
"searchCoverageHere": "Cari Liputan Disini",
|
"searchCoverageHere": "Cari Liputan Disini",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue