feat:static banner

This commit is contained in:
Anang Yusman 2025-05-20 15:08:49 +08:00
parent 0817edd57a
commit ba5eb3aa7b
8 changed files with 181 additions and 120 deletions

View File

@ -59,12 +59,12 @@ const columns: ColumnDef<any>[] = [
), ),
}, },
{ {
accessorKey: "static", accessorKey: "isStaticBanner",
header: "Static Banner", header: "Static Banner",
cell: ({ row }) => ( cell: ({ row }) => (
<StaticToogle <StaticToogle
id={row.original.id} id={row.original.id}
initChecked={row.original.staticPage} initChecked={row.original.isStaticBanner}
/> />
), ),
}, },

View File

@ -96,22 +96,9 @@ const BannerListTable = () => {
let temp: any; let temp: any;
const response = await listBanner(); const response = await listBanner();
temp = response?.data?.data; const data = response?.data?.data?.content;
const response2 = await listStaticBanner(); console.log("banner", data);
console.log("sadadddd", response2?.data?.data.length); setGetData(data);
for (let i = 0; i < response2?.data?.data.length; i++) {
for (let j = 0; j < temp.length; j++) {
console.log("temp", j, temp[j].id);
if (response2?.data?.data[i].mediaUploadId === temp[j].id) {
temp[j].staticPage = true;
} else {
temp[j].staticPage = false;
}
}
}
console.log("tesmasdasdasdasd", temp);
setGetData(temp);
close(); close();
} }

View File

@ -45,19 +45,17 @@ const columns: ColumnDef<any>[] = [
), ),
}, },
{ {
accessorKey: "contentType", accessorKey: "mediaTypesString",
header: "Tipe Konten", header: "Tipe Konten",
cell: ({ row }) => ( cell: ({ row }) => (
<span className="normal-case">{row.getValue("contentType")}</span> <span className="normal-case">{row.getValue("mediaTypesString")}</span>
), ),
}, },
{ {
accessorKey: "isInternational", accessorKey: "publishedLocation",
header: "Wilayah", header: "Wilayah",
cell: ({ row }) => ( cell: ({ row }) => (
<span className="normal-case"> <span className="normal-case">{row.getValue("publishedLocation")}</span>
{row.getValue("isInternational") ? "INT" : "ID"}
</span>
), ),
}, },
{ {

View File

@ -20,7 +20,7 @@ const Home = ({ params: { locale } }: { params: { locale: string } }) => {
<ReactLenis root> <ReactLenis root>
<div className="pb-14"> <div className="pb-14">
<Navbar /> <Navbar />
<Hero /> <Hero group="mabes" />
<SearchSection /> <SearchSection />
<NewContent group="mabes" type="latest" /> <NewContent group="mabes" type="latest" />
<NewContent group="mabes" type="popular" /> <NewContent group="mabes" type="popular" />

View File

@ -1,11 +1,20 @@
import { getCategoryData, getPublicCategoryData } from "@/service/landing/landing"; import {
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 { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "../ui/carousel"; import {
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";
@ -19,14 +28,26 @@ 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 ? `/polda/${poldaName}` : satkerName ? `/satker/${satkerName}` : "/"; let prefixPath = poldaName
? `/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 == "polda" && poldaName && String(poldaName)?.length > 1 ? poldaName : props.group == "satker" && satkerName && String(satkerName)?.length > 1 ? "satker-" + satkerName : "", props.group == "mabes"
? ""
: 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
); );
@ -52,7 +73,10 @@ 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) => (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 lg:px-24 py-10"> <div className="px-4 lg:px-24 py-10">
@ -60,12 +84,16 @@ const ContentCategory = (props: { group?: string; type: string }) => {
<h2 className="text-center text-xl lg:text-3xl font-bold text-[#bb3523] mb-4"> <h2 className="text-center text-xl lg:text-3xl font-bold text-[#bb3523] mb-4">
{pathname?.split("/")[1] == "in" ? ( {pathname?.split("/")[1] == "in" ? (
<> <>
<span className="text-black dark:text-white">{t("category")}&nbsp;</span> <span className="text-black dark:text-white">
{t("category")}&nbsp;
</span>
{t("content")} {t("content")}
</> </>
) : ( ) : (
<> <>
<span className="text-black dark:text-white">{t("content")}&nbsp;</span> <span className="text-black dark:text-white">
{t("content")}&nbsp;
</span>
{t("category")} {t("category")}
</> </>
)} )}
@ -73,35 +101,51 @@ const ContentCategory = (props: { group?: string; type: string }) => {
<div className="h-1 w-52 bg-[#bb3523] mx-auto mb-6 rounded"></div> <div className="h-1 w-52 bg-[#bb3523] mx-auto mb-6 rounded"></div>
<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((category: any) => ( {(seeAllValue ? categories : categories?.slice(0, 4))?.map(
<div key={category?.id}> (category: any) => (
<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"> <div key={category?.id}>
{/* Gambar */} <div
<Image onClick={() =>
placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} router.push(
alt="category" `${prefixPath}all/filter?category=${category?.id}`
width={2560} )
height={1440} }
src={category?.thumbnailLink} className="cursor-pointer relative group rounded-md overflow-hidden shadow-md hover:shadow-lg block"
className="w-full lg:h-[250px] h-40 object-cover group-hover:scale-110 transition-transform duration-300" >
/> {/* Gambar */}
<Image
placeholder={`data:image/svg+xml;base64,${toBase64(
shimmer(700, 475)
)}`}
alt="category"
width={2560}
height={1440}
src={category?.thumbnailLink}
className="w-full lg:h-[250px] 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-25 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-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">
<h3 className="text-sm font-semibold truncate">{category?.name}</h3> <h3 className="text-sm font-semibold truncate">
{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 > 10 && (
<div className="flex items-center flex-row justify-center mt-6"> <div className="flex items-center flex-row justify-center mt-6">
<Button onClick={() => setSeeAllValue(!seeAllValue)} className="bg-white hover:bg-[#bb3523] text-[#bb3523] hover:text-white border-2 border-[#bb3523]"> <Button
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

@ -2,7 +2,7 @@ import { formatDateToIndonesian, shimmer, toBase64 } from "@/utils/globals";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import "swiper/css/bundle"; import "swiper/css/bundle";
import "swiper/css/navigation"; import "swiper/css/navigation";
import { getHeroData } from "@/service/landing/landing"; import { getHeroData, listStaticBanner } from "@/service/landing/landing";
import Link from "next/link"; import Link from "next/link";
import { useParams, usePathname, useRouter } from "next/navigation"; import { useParams, usePathname, useRouter } from "next/navigation";
import { import {
@ -190,16 +190,19 @@ const SurveyIntroModal = ({ onNext }: { onNext: () => void }) => {
const ONE_MONTH = 30 * 24 * 60 * 60 * 1000; const ONE_MONTH = 30 * 24 * 60 * 60 * 1000;
const Hero: React.FC = () => { const Hero = (props: { group?: string }) => {
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
const params = useParams(); const params = useParams();
const locale = params?.locale; const locale = params?.locale;
const [isLoading, setIsLoading] = useState<any>(true); const [isLoading, setIsLoading] = useState<any>(true);
const [heroData, setHeroData] = useState<any>(); const [heroData, setHeroData] = useState<any>();
const [content, setContent] = useState<any>();
const [showModal, setShowModal] = useState(false); const [showModal, setShowModal] = useState(false);
const [showSurveyModal, setShowSurveyModal] = useState(false); const [showSurveyModal, setShowSurveyModal] = useState(false);
const [showFormModal, setShowFormModal] = useState(false); const [showFormModal, setShowFormModal] = useState(false);
const poldaName = params?.polda_name;
const satkerName = params?.satker_name;
useEffect(() => { useEffect(() => {
const timer = setTimeout(() => { const timer = setTimeout(() => {
@ -274,7 +277,28 @@ const Hero: React.FC = () => {
const initFetch = async () => { const initFetch = async () => {
const response = await getHeroData(); const response = await getHeroData();
console.log(response); console.log(response);
let data = response?.data?.data?.content;
setHeroData(response?.data?.data?.content); setHeroData(response?.data?.data?.content);
if (data) {
const resStatic = await listStaticBanner(
props.group == "mabes"
? ""
: props.group == "polda" && poldaName && String(poldaName)?.length > 1
? poldaName
: props.group == "satker" &&
satkerName &&
String(satkerName)?.length > 1
? "satker-" + 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) => ` const shimmer = (w: number, h: number) => `
@ -322,7 +346,7 @@ const Hero: React.FC = () => {
) : ( ) : (
<Carousel className="lg:w-2/3 lg:h-full "> <Carousel className="lg:w-2/3 lg:h-full ">
<CarouselContent> <CarouselContent>
{heroData?.map((list: any) => ( {content?.map((list: any) => (
<CarouselItem key={list?.id}> <CarouselItem key={list?.id}>
<div className="relative h-[310px] lg:h-[460px] mt-1"> <div className="relative h-[310px] lg:h-[460px] mt-1">
<Image <Image

View File

@ -3470,70 +3470,70 @@ export function getMenuList(pathname: string, t: any): Group[] {
}, },
], ],
}, },
// { {
// groupLabel: "", groupLabel: "",
// id: "settings", id: "settings",
// menus: [ menus: [
// { {
// id: "settings", id: "settings",
// href: "/admin/settings", href: "/admin/settings",
// label: t("settings"), label: t("settings"),
// active: pathname.includes("/settinng"), active: pathname.includes("/settinng"),
// icon: "material-symbols:settings", icon: "material-symbols:settings",
// submenus: [ submenus: [
// { {
// href: "/admin/settings/category", href: "/admin/settings/category",
// label: t("category"), label: t("category"),
// active: pathname === "/admin/settings/category", active: pathname === "/admin/settings/category",
// icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
// children: [], children: [],
// }, },
// { {
// href: "/admin/settings/tag", href: "/admin/settings/tag",
// label: "Tag", label: "Tag",
// active: pathname === "/admin/settings/tag", active: pathname === "/admin/settings/tag",
// icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
// children: [], children: [],
// }, },
// { {
// href: "/admin/settings/banner", href: "/admin/settings/banner",
// label: "Banner", label: "Banner",
// active: pathname === "/admin/settings/banner", active: pathname === "/admin/settings/banner",
// icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
// children: [], children: [],
// }, },
// { {
// href: "/admin/settings/feedback", href: "/admin/settings/feedback",
// label: "Feedback", label: "Feedback",
// active: pathname === "/admin/settings/feedback", active: pathname === "/admin/settings/feedback",
// icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
// children: [], children: [],
// }, },
// { {
// href: "/admin/settings/faq", href: "/admin/settings/faq",
// label: "FAQ", label: "FAQ",
// active: pathname === "/admin/settings/faq", active: pathname === "/admin/settings/faq",
// icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
// children: [], children: [],
// }, },
// { {
// href: "https://nat-mediahub.polri.go.id/", href: "https://nat-mediahub.polri.go.id/",
// label: "Mediahub 2022", label: "Mediahub 2022",
// active: pathname === "/admin/settings/mediahub-2022", active: pathname === "/admin/settings/mediahub-2022",
// icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
// children: [], children: [],
// }, },
// { {
// href: "/admin/settings/privacy", href: "/admin/settings/privacy",
// label: t("privacy"), label: t("privacy"),
// active: pathname === "/admin/settings/privacy", active: pathname === "/admin/settings/privacy",
// icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
// children: [], children: [],
// }, },
// ], ],
// }, },
// ], ],
// }, },
]; ];
} else { } else {
menusSelected = [ menusSelected = [

View File

@ -37,6 +37,14 @@ export async function getHeroData() {
); );
} }
export async function listStaticBanner(
group: any = "",
isInt: Boolean = false
) {
const url = `media/static-banner?&group=${group}&isInt=${isInt}`;
return httpGetInterceptor(url);
}
export async function getPublicCategoryData( export async function getPublicCategoryData(
group: any = "", group: any = "",
type: string = "", type: string = "",