satupeta-main/app/(modules)/(landing)/components/news-section/news-card.tsx

64 lines
1.6 KiB
TypeScript
Raw Normal View History

2026-01-27 02:31:12 +00:00
"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>
);
}