145 lines
4.7 KiB
TypeScript
145 lines
4.7 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import { useEffect, useState } from "react";
|
||
|
|
import Image from "next/image";
|
||
|
|
import { getListArticle } from "@/service/article";
|
||
|
|
import { Calendar } from "lucide-react";
|
||
|
|
import Link from "next/link";
|
||
|
|
|
||
|
|
type Article = {
|
||
|
|
id: number;
|
||
|
|
title: string;
|
||
|
|
description: string;
|
||
|
|
categoryName: string;
|
||
|
|
createdAt: string;
|
||
|
|
createdByName: string;
|
||
|
|
thumbnailUrl: string;
|
||
|
|
categories: { title: string }[];
|
||
|
|
files: { fileUrl: string; file_alt: string }[];
|
||
|
|
};
|
||
|
|
|
||
|
|
export default function Header() {
|
||
|
|
const [articles, setArticles] = useState<Article[]>([]);
|
||
|
|
const [showData] = useState("5"); // default ambil 5 artikel
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
fetchArticles();
|
||
|
|
}, []);
|
||
|
|
|
||
|
|
async function fetchArticles() {
|
||
|
|
try {
|
||
|
|
const req = {
|
||
|
|
limit: showData,
|
||
|
|
page: 1,
|
||
|
|
search: "",
|
||
|
|
categorySlug: "",
|
||
|
|
sort: "desc",
|
||
|
|
isPublish: true,
|
||
|
|
sortBy: "created_at",
|
||
|
|
};
|
||
|
|
|
||
|
|
const res = await getListArticle(req);
|
||
|
|
setArticles(res?.data?.data || []);
|
||
|
|
} catch (error) {
|
||
|
|
console.error("Gagal memuat artikel:", error);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<section
|
||
|
|
className="py-6 px-4 md:px-8 bg-cover bg-center bg-no-repeat"
|
||
|
|
style={{
|
||
|
|
backgroundImage: "url('/bg.jpg')",
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<div className="max-w-[1350px] mx-auto flex flex-col gap-6">
|
||
|
|
{/* Bagian atas (2 artikel pertama) */}
|
||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
|
|
{articles.slice(0, 2).map((item) => (
|
||
|
|
<div
|
||
|
|
key={item.id}
|
||
|
|
className="relative w-full h-[220px] md:h-[400px] overflow-hidden"
|
||
|
|
>
|
||
|
|
<Link href={`/detail/${item?.id}`}>
|
||
|
|
<Image
|
||
|
|
src={item.thumbnailUrl || "/default.jpg"}
|
||
|
|
alt={item.title}
|
||
|
|
fill
|
||
|
|
className="object-cover"
|
||
|
|
/>
|
||
|
|
<div className="absolute inset-0 bg-black/10 p-4 flex flex-col justify-end text-white">
|
||
|
|
<span className="text-xs font-medium tracking-wide">
|
||
|
|
{item.categoryName}
|
||
|
|
</span>
|
||
|
|
<h2 className="text-base md:text-xl font-semibold leading-tight">
|
||
|
|
{item.title}
|
||
|
|
</h2>
|
||
|
|
<div className="flex flex-row item-center gap-3">
|
||
|
|
<div className="text-sm text-white/70">
|
||
|
|
{item.createdByName}{" "}
|
||
|
|
</div>
|
||
|
|
<div className="text-blue-400 mt-1">
|
||
|
|
<Calendar size={14} />
|
||
|
|
</div>
|
||
|
|
<div className="text-sm">
|
||
|
|
{new Date(item.createdAt).toLocaleDateString("en-GB", {
|
||
|
|
day: "2-digit",
|
||
|
|
month: "long",
|
||
|
|
year: "numeric",
|
||
|
|
})}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</Link>
|
||
|
|
</div>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Bagian bawah (2 artikel selanjutnya) */}
|
||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||
|
|
{articles.slice(2, 4).map((item) => (
|
||
|
|
<div
|
||
|
|
key={item.id}
|
||
|
|
className="flex flex-col md:flex-row gap-4 overflow-hidden"
|
||
|
|
>
|
||
|
|
<Link href={`/detail/${item?.id}`}>
|
||
|
|
<div className="relative w-full md:w-[200px] h-[180px] md:h-[175px] shrink-0">
|
||
|
|
<Image
|
||
|
|
src={item.thumbnailUrl || "/default.jpg"}
|
||
|
|
alt={item.title}
|
||
|
|
fill
|
||
|
|
className="object-cover"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div className="flex flex-col justify-center gap-2 px-1 md:px-0">
|
||
|
|
<span className="text-xs font-medium text-white">
|
||
|
|
{item.categoryName}
|
||
|
|
</span>
|
||
|
|
<h3 className="text-base md:text-xl font-semibold leading-snug text-white font-serif">
|
||
|
|
{item.title}
|
||
|
|
</h3>
|
||
|
|
<div className="flex flex-row item-center gap-3">
|
||
|
|
<div className="text-sm text-white">
|
||
|
|
{item.createdByName}{" "}
|
||
|
|
</div>
|
||
|
|
<div className="text-blue-400 mt-1">
|
||
|
|
<Calendar size={12} />
|
||
|
|
</div>
|
||
|
|
<div className="text-sm text-white">
|
||
|
|
{new Date(item.createdAt).toLocaleDateString("en-GB", {
|
||
|
|
day: "2-digit",
|
||
|
|
month: "long",
|
||
|
|
year: "numeric",
|
||
|
|
})}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</Link>
|
||
|
|
</div>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
);
|
||
|
|
}
|