64 lines
1.6 KiB
TypeScript
64 lines
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { getFileUrl } from "@/shared/utils/file";
|
|
import { ArrowRight } from "lucide-react";
|
|
import Image from "next/image";
|
|
import Link from "next/link";
|
|
import DOMPurify from "dompurify";
|
|
|
|
function truncateHtml(html: string, maxLength: number): string {
|
|
const tempEl = document.createElement("div");
|
|
tempEl.innerHTML = html;
|
|
const textContent = tempEl.textContent || "";
|
|
return textContent.length > maxLength
|
|
? textContent.slice(0, maxLength) + "..."
|
|
: textContent;
|
|
}
|
|
|
|
export default function NewsCard({
|
|
title,
|
|
description,
|
|
link,
|
|
image,
|
|
}: {
|
|
title: string;
|
|
description: string;
|
|
link: string;
|
|
image?: string;
|
|
}) {
|
|
const safeHtml = DOMPurify.sanitize(truncateHtml(description, 300));
|
|
|
|
return (
|
|
<div className="relative flex flex-col gap-4 rounded-xl border border-slate-400 p-4 shadow-sm">
|
|
{image && (
|
|
<div className="relative w-full" style={{ height: 379 }}>
|
|
<Image
|
|
src={getFileUrl(image)}
|
|
alt="news"
|
|
fill
|
|
className="rounded-md object-cover"
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
<div className="relative flex flex-col gap-4 pb-20">
|
|
<h2 className="text-2xl leading-snug font-semibold text-slate-700">
|
|
{title}
|
|
</h2>
|
|
|
|
<div
|
|
className="text-sm text-slate-500"
|
|
dangerouslySetInnerHTML={{ __html: safeHtml }}
|
|
/>
|
|
</div>
|
|
<Link
|
|
href={link}
|
|
className="text-primary absolute bottom-4 left-4 flex items-center text-sm font-medium hover:underline"
|
|
>
|
|
Lihat selengkapnya
|
|
<ArrowRight size={16} className="ml-1" />
|
|
</Link>
|
|
</div>
|
|
);
|
|
}
|