fix: styling in hero and add imageblurry
This commit is contained in:
parent
7e1ffe2d2f
commit
fb976f01bb
|
|
@ -64,6 +64,17 @@ type Category = {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type PlacementType = "all" | "mabes" | "polda" | "international" | string;
|
||||||
|
|
||||||
|
interface FilePlacement {
|
||||||
|
mediaFileId: number;
|
||||||
|
placements?: PlacementType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TempFileItem {
|
||||||
|
id: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
type Detail = {
|
type Detail = {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
|
@ -255,6 +266,7 @@ export default function FormImageUpdate() {
|
||||||
setDetail(details);
|
setDetail(details);
|
||||||
|
|
||||||
setSelectedTarget(String(details.category.id));
|
setSelectedTarget(String(details.category.id));
|
||||||
|
setTempFile(details?.files);
|
||||||
|
|
||||||
setValue("title", details.title);
|
setValue("title", details.title);
|
||||||
setValue("description", details.htmlDescription);
|
setValue("description", details.htmlDescription);
|
||||||
|
|
@ -641,6 +653,77 @@ export default function FormImageUpdate() {
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
));
|
));
|
||||||
|
type PlacementType = "all" | "mabes" | "polda" | "international" | string;
|
||||||
|
|
||||||
|
interface FilePlacement {
|
||||||
|
mediaFileId: number;
|
||||||
|
placements?: PlacementType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TempFileItem {
|
||||||
|
id: number | string;
|
||||||
|
// tambahkan properti lain kalau ada
|
||||||
|
}
|
||||||
|
|
||||||
|
const [tempFile, setTempFile] = useState<TempFileItem[]>([]);
|
||||||
|
const [filePlacements, setFilePlacements] = useState<FilePlacement[]>([]);
|
||||||
|
|
||||||
|
|
||||||
|
const setupPlacement = (id: number | string, placement: PlacementType) => {
|
||||||
|
console.log(`FileDestination.leng:: ${id}_${placement}`);
|
||||||
|
const arrayFile: FilePlacement[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < tempFile?.length; i++) {
|
||||||
|
const element = tempFile[i];
|
||||||
|
|
||||||
|
if (element.id == id) {
|
||||||
|
const findPlacementIdx = filePlacements.findIndex(
|
||||||
|
(o) => Number(o.mediaFileId) === Number(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (findPlacementIdx > -1) {
|
||||||
|
const findPlacement = filePlacements[findPlacementIdx];
|
||||||
|
|
||||||
|
if (findPlacement?.placements?.includes(placement)) {
|
||||||
|
if (placement === "all") {
|
||||||
|
findPlacement.placements = undefined;
|
||||||
|
} else {
|
||||||
|
findPlacement.placements = findPlacement.placements.filter(
|
||||||
|
(val) => val !== placement
|
||||||
|
);
|
||||||
|
if (findPlacement.placements?.includes("all")) {
|
||||||
|
findPlacement.placements = findPlacement.placements.filter(
|
||||||
|
(val) => val !== "all"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (placement === "all") {
|
||||||
|
findPlacement.placements = [
|
||||||
|
"all",
|
||||||
|
"mabes",
|
||||||
|
"polda",
|
||||||
|
"international",
|
||||||
|
];
|
||||||
|
} else if (findPlacement.placements) {
|
||||||
|
findPlacement.placements = [...findPlacement.placements, placement];
|
||||||
|
} else {
|
||||||
|
findPlacement.placements = [placement];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const file: FilePlacement = {
|
||||||
|
mediaFileId: Number(element.id),
|
||||||
|
placements: [placement],
|
||||||
|
};
|
||||||
|
|
||||||
|
arrayFile.push(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalPlacements = [...filePlacements, ...arrayFile];
|
||||||
|
setFilePlacements(finalPlacements);
|
||||||
|
console.log("FileDestination.leng::", finalPlacements);
|
||||||
|
};
|
||||||
|
|
||||||
const handleCheckboxChangeImage = (fileId: number, value: string) => {
|
const handleCheckboxChangeImage = (fileId: number, value: string) => {
|
||||||
setSelectedOptions((prev: any) => {
|
setSelectedOptions((prev: any) => {
|
||||||
|
|
@ -894,11 +977,8 @@ export default function FormImageUpdate() {
|
||||||
checked={selectedOptions[
|
checked={selectedOptions[
|
||||||
file.id
|
file.id
|
||||||
]?.includes("all")}
|
]?.includes("all")}
|
||||||
onChange={() =>
|
onChange={(e) =>
|
||||||
handleCheckboxChangeImage(
|
setupPlacement(file.id, e.target.value)
|
||||||
file.id,
|
|
||||||
"all"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
className="form-checkbox"
|
className="form-checkbox"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,23 @@
|
||||||
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";
|
||||||
|
import ImageBlurry from "../ui/image-blurry";
|
||||||
|
|
||||||
const ContentCategory = (props: { group?: string; type: string }) => {
|
const ContentCategory = (props: { group?: string; type: string }) => {
|
||||||
const [categories, setCategories] = useState<any>();
|
const [categories, setCategories] = useState<any>();
|
||||||
|
|
@ -19,14 +29,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 +74,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-0 py-10">
|
<div className="px-4 lg:px-0 py-10">
|
||||||
|
|
@ -61,22 +86,34 @@ 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">{t("category", { defaultValue: "Category" })} </span>
|
<span className="text-[#bb3523] dark:text-white">
|
||||||
|
{t("category", { defaultValue: "Category" })}
|
||||||
|
</span>
|
||||||
{t("content", { defaultValue: "Content" })}
|
{t("content", { defaultValue: "Content" })}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<span className="text-[#bb3523] dark:text-white">{t("content", { defaultValue: "Content" })} </span>
|
<span className="text-[#bb3523] dark:text-white">
|
||||||
|
{t("content", { defaultValue: "Content" })}
|
||||||
|
</span>
|
||||||
{t("category", { defaultValue: "Category" })}
|
{t("category", { defaultValue: "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((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={() =>
|
||||||
|
router.push(
|
||||||
|
`${prefixPath}all/filter?category=${category?.id}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className="cursor-pointer relative group rounded-md overflow-hidden shadow-md hover:shadow-lg block"
|
||||||
|
>
|
||||||
|
{/* Gambar */}
|
||||||
|
{/* <Image
|
||||||
priority={true}
|
priority={true}
|
||||||
placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`}
|
placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`}
|
||||||
alt="category"
|
alt="category"
|
||||||
|
|
@ -84,25 +121,42 @@ const ContentCategory = (props: { group?: string; type: string }) => {
|
||||||
height={1440}
|
height={1440}
|
||||||
src={category?.smallThumbnailLink}
|
src={category?.smallThumbnailLink}
|
||||||
className="w-full lg:h-[300px] 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"
|
||||||
/>
|
/> */}
|
||||||
|
<ImageBlurry
|
||||||
|
src={category?.smallThumbnailLink}
|
||||||
|
alt="gambar-utama"
|
||||||
|
placeholder={`data:image/svg+xml;base64,${toBase64(
|
||||||
|
shimmer(700, 475)
|
||||||
|
)}`}
|
||||||
|
priority={true}
|
||||||
|
className="w-full lg:h-[300px] h-40 object-contain group-hover:scale-110 transition-transform duration-300"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Overlay gelap */}
|
{/* Overlay gelap */}
|
||||||
<div className="absolute inset-0 bg-black bg-opacity-50 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-1/2 transform -translate-x-1/2 text-white">
|
<div className="absolute bottom-5 left-1/2 transform -translate-x-1/2 text-white">
|
||||||
<h3 className="text-sm font-semibold text-center">{category?.name}</h3>
|
<h3 className="text-sm font-semibold text-center">
|
||||||
|
{category?.name}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
))}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tombol See More / See Less */}
|
{/* Tombol See More / See Less */}
|
||||||
{categories?.length > 4 && (
|
{categories?.length > 4 && (
|
||||||
<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 dark:bg-black hover:bg-[#bb3523] text-[#bb3523] hover:text-white border-2 border-[#bb3523]">
|
<Button
|
||||||
{seeAllValue ? t("seeLess", { defaultValue: "See Less" }) : t("seeMore", { defaultValue: "See More" })}
|
onClick={() => setSeeAllValue(!seeAllValue)}
|
||||||
|
className="bg-white dark:bg-black hover:bg-[#bb3523] text-[#bb3523] hover:text-white border-2 border-[#bb3523]"
|
||||||
|
>
|
||||||
|
{seeAllValue
|
||||||
|
? t("seeLess", { defaultValue: "See Less" })
|
||||||
|
: t("seeMore", { defaultValue: "See More" })}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
import { Link } from "@/i18n/routing";
|
import { Link } from "@/i18n/routing";
|
||||||
import { listBannerHero } from "@/service/settings/settings";
|
import { listBannerHero } from "@/service/settings/settings";
|
||||||
import ImageBlurry from "../ui/image-blurry";
|
import ImageBlurry from "../ui/image-blurry";
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
|
||||||
type HeroModalProps = {
|
type HeroModalProps = {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
|
@ -173,7 +174,7 @@ const HeroModal = ({
|
||||||
>
|
>
|
||||||
✕
|
✕
|
||||||
</button>
|
</button>
|
||||||
{/* <Image
|
<Image
|
||||||
priority={true}
|
priority={true}
|
||||||
src={list?.smallThumbnailLink}
|
src={list?.smallThumbnailLink}
|
||||||
alt="gambar-utama"
|
alt="gambar-utama"
|
||||||
|
|
@ -182,17 +183,14 @@ const HeroModal = ({
|
||||||
placeholder={`data:image/svg+xml;base64,${toBase64(
|
placeholder={`data:image/svg+xml;base64,${toBase64(
|
||||||
shimmer(700, 475)
|
shimmer(700, 475)
|
||||||
)}`}
|
)}`}
|
||||||
className="w-full h-[310px] lg:h-[420px] rounded-lg object-cover"
|
className="w-full h-[310px] lg:h-[420px] rounded-lg object-contain bg-black"
|
||||||
/> */}
|
/>
|
||||||
<ImageBlurry
|
{/* <ImageBlurry
|
||||||
|
priority={true}
|
||||||
src={list?.smallThumbnailLink}
|
src={list?.smallThumbnailLink}
|
||||||
alt="gambar-utama"
|
alt="gambar-utama"
|
||||||
style={{
|
className="w-full h-[310px] lg:h-[420px] rounded-lg object-contain"
|
||||||
objectFit: "contain",
|
/> */}
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<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 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>
|
<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">
|
<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">
|
||||||
|
|
@ -577,24 +575,29 @@ const HeroNew = (props: { group?: string }) => {
|
||||||
? `${prefixPath}/document/detail/${list?.slug}`
|
? `${prefixPath}/document/detail/${list?.slug}`
|
||||||
: `${prefixPath}/audio/detail/${list?.slug}`
|
: `${prefixPath}/audio/detail/${list?.slug}`
|
||||||
}
|
}
|
||||||
className="absolute bottom-20 left-8 lg:left-32 z-20 text-white w-[85%] lg:w-[45%] cursor-pointer"
|
className="absolute bottom-10 lg:bottom-20 left-8 lg:left-32 z-20 text-white w-[85%] lg:w-[45%] cursor-pointer"
|
||||||
>
|
>
|
||||||
<span className="text-red-600 text-lg font-bold uppercase">
|
<span className="text-red-600 text-[10px] lg:text-lg font-bold uppercase">
|
||||||
{list?.categoryName}
|
{list?.categoryName}
|
||||||
</span>
|
</span>
|
||||||
<h2 className="text-xl font-bold">{list?.title}</h2>
|
<h2 className="text-[14px] lg:text-xl font-bold">{list?.title}</h2>
|
||||||
<p className="text-sm mt-2">
|
<p className="text-[9px] lg:text-sm mt-2">
|
||||||
{formatDateToIndonesian(new Date(list?.createdAt))}{" "}
|
{formatDateToIndonesian(new Date(list?.createdAt))}{" "}
|
||||||
{list?.timezone || "WIB"} | 👁 {list?.clickCount}
|
{list?.timezone || "WIB"} | 👁 {list?.clickCount}
|
||||||
</p>
|
</p>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* Tombol navigasi */}
|
<div className="absolute left-2 top-[45%] z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full">
|
||||||
<div className="swiper-button-prev absolute left-6 top-[45%] z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full">
|
<Icon
|
||||||
<ChevronLeft className="w-5 h-5" />
|
icon="mdi:chevron-left"
|
||||||
|
className="w-5 lg:w-10 h-5 lg:h-10"
|
||||||
|
/>{" "}
|
||||||
</div>
|
</div>
|
||||||
<div className="swiper-button-next absolute right-6 top-[45%] z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full">
|
<div className="absolute right-2 top-[45%] z-30 -translate-y-1/2 hover:bg-black/70 text-white p-2 rounded-full">
|
||||||
<ChevronRight className="w-5 h-5" />
|
<Icon
|
||||||
|
icon="mdi:chevron-right"
|
||||||
|
className="w-5 lg:w-10 h-5 lg:h-10"
|
||||||
|
/>{" "}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ 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";
|
import { motion } from "framer-motion";
|
||||||
|
import ImageBlurry from "../ui/image-blurry";
|
||||||
|
|
||||||
const NewContent = (props: { group: string; type: string }) => {
|
const NewContent = (props: { group: string; type: string }) => {
|
||||||
const [newContent, setNewContent] = useState<any>();
|
const [newContent, setNewContent] = useState<any>();
|
||||||
|
|
@ -228,7 +229,7 @@ const NewContent = (props: { group: string; type: string }) => {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{" "}
|
{" "}
|
||||||
<Image
|
{/* <Image
|
||||||
priority={true}
|
priority={true}
|
||||||
placeholder={`data:image/svg+xml;base64,${toBase64(
|
placeholder={`data:image/svg+xml;base64,${toBase64(
|
||||||
shimmer(700, 475)
|
shimmer(700, 475)
|
||||||
|
|
@ -238,6 +239,15 @@ const NewContent = (props: { group: string; type: string }) => {
|
||||||
alt="image"
|
alt="image"
|
||||||
src={image?.smallThumbnailLink}
|
src={image?.smallThumbnailLink}
|
||||||
className="w-full h-full object-cover"
|
className="w-full h-full object-cover"
|
||||||
|
/> */}
|
||||||
|
<ImageBlurry
|
||||||
|
src={image?.smallThumbnailLink}
|
||||||
|
alt="image"
|
||||||
|
priority={true}
|
||||||
|
placeholder={`data:image/svg+xml;base64,${toBase64(
|
||||||
|
shimmer(700, 475)
|
||||||
|
)}`}
|
||||||
|
className="w-full h-full object-contain"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
@ -431,7 +441,7 @@ const NewContent = (props: { group: string; type: string }) => {
|
||||||
prefixPath + `/video/detail/${video?.slug}`
|
prefixPath + `/video/detail/${video?.slug}`
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Image
|
{/* <Image
|
||||||
priority={true}
|
priority={true}
|
||||||
placeholder={`data:image/svg+xml;base64,${toBase64(
|
placeholder={`data:image/svg+xml;base64,${toBase64(
|
||||||
shimmer(700, 475)
|
shimmer(700, 475)
|
||||||
|
|
@ -441,6 +451,15 @@ const NewContent = (props: { group: string; type: string }) => {
|
||||||
height={1440}
|
height={1440}
|
||||||
src={video?.smallThumbnailLink}
|
src={video?.smallThumbnailLink}
|
||||||
className="w-full h-full object-cover"
|
className="w-full h-full object-cover"
|
||||||
|
/> */}
|
||||||
|
<ImageBlurry
|
||||||
|
src={video?.smallThumbnailLink}
|
||||||
|
alt="video"
|
||||||
|
priority={true}
|
||||||
|
placeholder={`data:image/svg+xml;base64,${toBase64(
|
||||||
|
shimmer(700, 475)
|
||||||
|
)}`}
|
||||||
|
className="w-full h-full object-contain"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import { getHeroData } from "@/service/landing/landing";
|
||||||
import { htmlToString } from "@/utils/globals";
|
import { htmlToString } from "@/utils/globals";
|
||||||
import { Link, useRouter } from "@/i18n/routing";
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
|
import ImageBlurry from "../ui/image-blurry";
|
||||||
|
|
||||||
const ScrollableContent = () => {
|
const ScrollableContent = () => {
|
||||||
const [contentType, setContentType] = useState("all");
|
const [contentType, setContentType] = useState("all");
|
||||||
|
|
@ -161,7 +162,10 @@ const ScrollableContent = () => {
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
router.push(prefixPath + `/${contentType}/filter?title=${search.toLowerCase()}`)
|
router.push(
|
||||||
|
prefixPath +
|
||||||
|
`/${contentType}/filter?title=${search.toLowerCase()}`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
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 text-[14px]"
|
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 text-[14px]"
|
||||||
>
|
>
|
||||||
|
|
@ -206,12 +210,22 @@ const ScrollableContent = () => {
|
||||||
: `${prefixPath}/audio/detail/${item?.slug}`
|
: `${prefixPath}/audio/detail/${item?.slug}`
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Image
|
{/* <Image
|
||||||
priority={true}
|
priority={true}
|
||||||
src={item?.smallThumbnailLink}
|
src={item?.smallThumbnailLink}
|
||||||
alt={item?.title}
|
alt={item?.title}
|
||||||
fill
|
fill
|
||||||
objectFit="cover"
|
objectFit="cover"
|
||||||
|
/> */}
|
||||||
|
<ImageBlurry
|
||||||
|
priority={true}
|
||||||
|
src={item?.smallThumbnailLink}
|
||||||
|
alt="gambar-utama"
|
||||||
|
style={{
|
||||||
|
objectFit: "contain",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="absolute top-2 right-2 bg-[#c03724] rounded-full p-1 shadow">
|
<div className="absolute top-2 right-2 bg-[#c03724] rounded-full p-1 shadow">
|
||||||
<svg
|
<svg
|
||||||
|
|
@ -325,12 +339,22 @@ const ScrollableContent = () => {
|
||||||
: `${prefixPath}/audio/detail/${item?.slug}`
|
: `${prefixPath}/audio/detail/${item?.slug}`
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Image
|
{/* <Image
|
||||||
priority={true}
|
priority={true}
|
||||||
src={item?.smallThumbnailLink}
|
src={item?.smallThumbnailLink}
|
||||||
alt={item?.title}
|
alt={item?.title}
|
||||||
fill
|
fill
|
||||||
objectFit="cover"
|
objectFit="cover"
|
||||||
|
/> */}
|
||||||
|
<ImageBlurry
|
||||||
|
priority={true}
|
||||||
|
src={item?.smallThumbnailLink}
|
||||||
|
alt="gambar-utama"
|
||||||
|
style={{
|
||||||
|
objectFit: "contain",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="absolute top-2 right-2 bg-[#c03724] rounded-full p-1 shadow">
|
<div className="absolute top-2 right-2 bg-[#c03724] rounded-full p-1 shadow">
|
||||||
<svg
|
<svg
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,22 @@ import React, { useEffect, useState } from "react";
|
||||||
interface ImageBlurryProps {
|
interface ImageBlurryProps {
|
||||||
src: string;
|
src: string;
|
||||||
alt?: string;
|
alt?: string;
|
||||||
classname?: string;
|
className?: string;
|
||||||
key?: string | number;
|
key?: string | number;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
priority?: boolean;
|
priority?: boolean;
|
||||||
|
placeholder?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ImageBlurry: React.FC<ImageBlurryProps> = (props) => {
|
const ImageBlurry: React.FC<ImageBlurryProps> = ({
|
||||||
const { src, alt, classname, key, style, priority = false } = props;
|
src,
|
||||||
|
alt,
|
||||||
|
className,
|
||||||
|
key,
|
||||||
|
style,
|
||||||
|
priority = false,
|
||||||
|
placeholder,
|
||||||
|
}) => {
|
||||||
const [imgSrc, setImgSrc] = useState<string>(src);
|
const [imgSrc, setImgSrc] = useState<string>(src);
|
||||||
const [isError, setIsError] = useState<boolean>(false);
|
const [isError, setIsError] = useState<boolean>(false);
|
||||||
|
|
||||||
|
|
@ -26,7 +33,7 @@ const ImageBlurry: React.FC<ImageBlurryProps> = (props) => {
|
||||||
checkImage(pic);
|
checkImage(pic);
|
||||||
} else {
|
} else {
|
||||||
pic.addEventListener("load", function () {
|
pic.addEventListener("load", function () {
|
||||||
checkImage(this);
|
checkImage(this as HTMLImageElement);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -48,12 +55,10 @@ const ImageBlurry: React.FC<ImageBlurryProps> = (props) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// <div className="relative overflow-hidden bg-[#e9e9e9] blurry-wrapper">
|
|
||||||
// <div className="absolute -top-6 -bottom-6 left-0 -right-6 bg-[#e9e9e9] blur-[8px] scale-[1.8] bg-center bg-no-repeat bg-contain blur-bg" style={{ backgroundImage: `url(${imgSrc})` }}></div>
|
|
||||||
// <div className="absolute inset-0 bg-transparent bg-center bg-no-repeat bg-contain image-bg" style={{ backgroundImage: `url(${imgSrc})` }}></div>
|
|
||||||
// </div>
|
|
||||||
<div
|
<div
|
||||||
className="blurry-wrapper relative overflow-hidden bg-[#e9e9e9] rounded-t-lg"
|
className={`blurry-wrapper relative overflow-hidden bg-[#e9e9e9] rounded-t-lg ${
|
||||||
|
className || ""
|
||||||
|
}`}
|
||||||
key={key}
|
key={key}
|
||||||
style={style}
|
style={style}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ export async function listSPIT(
|
||||||
|
|
||||||
export async function deleteBulkSPIT(ids: any) {
|
export async function deleteBulkSPIT(ids: any) {
|
||||||
const url = `media/spit/bulk?ids=${ids}`;
|
const url = `media/spit/bulk?ids=${ids}`;
|
||||||
return httpDeleteInterceptor( url );
|
return httpDeleteInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function listNulisAI(limit: any, page: any, title: string = "") {
|
export async function listNulisAI(limit: any, page: any, title: string = "") {
|
||||||
|
|
@ -176,6 +176,11 @@ export async function createMedia(data: any) {
|
||||||
return httpPostInterceptor(url, data);
|
return httpPostInterceptor(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function updateFilePlacements(data: any) {
|
||||||
|
const url = "media/file/update-placement";
|
||||||
|
return httpPostInterceptor(url, data);
|
||||||
|
}
|
||||||
|
|
||||||
export async function uploadThumbnail(id: any, data: any) {
|
export async function uploadThumbnail(id: any, data: any) {
|
||||||
const url = `media/upload?id=${id}&operation=thumbnail`;
|
const url = `media/upload?id=${id}&operation=thumbnail`;
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue