fix
This commit is contained in:
parent
8782ac0e99
commit
ce5c494743
|
|
@ -0,0 +1,22 @@
|
|||
import BreakingNews from "@/components/landing-page/breaking-news";
|
||||
import Footer from "@/components/landing-page/footer";
|
||||
import Header from "@/components/landing-page/header";
|
||||
import HeaderLatest from "@/components/landing-page/header-latest";
|
||||
import Navbar from "@/components/landing-page/navbar";
|
||||
import News from "@/components/landing-page/news";
|
||||
import Opini from "@/components/landing-page/opini";
|
||||
import PopularNews from "@/components/landing-page/popular-news";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col font-[family-name:var(--font-geist-sans)] bg-white">
|
||||
<Navbar />
|
||||
<div className="flex-1">
|
||||
<HeaderLatest />
|
||||
</div>
|
||||
<BreakingNews />
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import BreakingNews from "@/components/landing-page/breaking-news";
|
||||
import Footer from "@/components/landing-page/footer";
|
||||
import Header from "@/components/landing-page/header";
|
||||
import HeaderLatest from "@/components/landing-page/header-latest";
|
||||
import Navbar from "@/components/landing-page/navbar";
|
||||
import News from "@/components/landing-page/news";
|
||||
import Opini from "@/components/landing-page/opini";
|
||||
import PopularNews from "@/components/landing-page/popular-news";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col font-[family-name:var(--font-geist-sans)] bg-white">
|
||||
<Navbar />
|
||||
<div className="flex-1">
|
||||
<HeaderLatest />
|
||||
</div>
|
||||
<BreakingNews />
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import BreakingNews from "@/components/landing-page/breaking-news";
|
||||
import Footer from "@/components/landing-page/footer";
|
||||
import Header from "@/components/landing-page/header";
|
||||
import HeaderLatest from "@/components/landing-page/header-latest";
|
||||
import Navbar from "@/components/landing-page/navbar";
|
||||
import News from "@/components/landing-page/news";
|
||||
import Opini from "@/components/landing-page/opini";
|
||||
import PopularNews from "@/components/landing-page/popular-news";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col font-[family-name:var(--font-geist-sans)] bg-white">
|
||||
<Navbar />
|
||||
<div className="flex-1">
|
||||
<HeaderLatest />
|
||||
</div>
|
||||
<BreakingNews />
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import DetailContent from "@/components/details/details-content";
|
||||
import Footer from "@/components/landing-page/footer";
|
||||
import Navbar from "@/components/landing-page/navbar";
|
||||
import Image from "next/image";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="relative min-h-screen font-[family-name:var(--font-geist-sans)]">
|
||||
<div className="relative z-10 bg-[#F2F4F3] max-w-7xl mx-auto">
|
||||
<Navbar />
|
||||
<div className="flex-1">
|
||||
<DetailContent />
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ type Article = {
|
|||
title: string;
|
||||
}[];
|
||||
files: {
|
||||
file_url: string;
|
||||
fileUrl: string;
|
||||
file_alt: string;
|
||||
}[];
|
||||
};
|
||||
|
|
@ -56,6 +56,8 @@ export default function DetailContent() {
|
|||
null
|
||||
);
|
||||
|
||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||
|
||||
const [tabArticles, setTabArticles] = useState<Article[]>([]);
|
||||
|
||||
const [activeTab, setActiveTab] = useState<TabKey>("trending");
|
||||
|
|
@ -154,16 +156,17 @@ export default function DetailContent() {
|
|||
|
||||
useEffect(() => {
|
||||
initState();
|
||||
}, [page, showData, startDateValue, selectedCategories]);
|
||||
}, [page, showData]);
|
||||
|
||||
async function initState() {
|
||||
// loading();
|
||||
const req = {
|
||||
limit: showData,
|
||||
page,
|
||||
search,
|
||||
categorySlug: Array.from(selectedCategories).join(","),
|
||||
page: 1,
|
||||
search: "",
|
||||
categorySlug: "",
|
||||
sort: "desc",
|
||||
isPublish: true,
|
||||
sortBy: "created_at",
|
||||
};
|
||||
|
||||
|
|
@ -188,22 +191,20 @@ export default function DetailContent() {
|
|||
setThumbnail(data?.thumbnailUrl);
|
||||
setDiseId(data?.aiArticleId);
|
||||
setDetailFiles(data?.files);
|
||||
setArticleDetail(data); // <-- Add this
|
||||
setArticleDetail(data);
|
||||
close();
|
||||
}
|
||||
|
||||
if (!articleDetail?.files || articleDetail.files.length === 0) {
|
||||
return (
|
||||
<div className="w-full h-[400px] bg-gray-100 flex items-center justify-center rounded-lg">
|
||||
<p className="text-gray-400 text-sm">Gambar tidak tersedia</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-center bg-[#F2F4F3] w-full overflow-hidden mb-4 py-6 px-8">
|
||||
<Image
|
||||
src={"/mikul.png"}
|
||||
alt="Background"
|
||||
width={272}
|
||||
height={90}
|
||||
className="w-full md:w-[272px] h-[90px] object-cover border"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
<div className="bg-white grid grid-cols-1 md:grid-cols-3 gap-6 px-8 py-8">
|
||||
<div className="md:col-span-2">
|
||||
<p className="text-sm text-gray-500 mb-2">Home {">"}Detail</p>
|
||||
|
|
@ -211,7 +212,7 @@ export default function DetailContent() {
|
|||
{articleDetail?.title}
|
||||
</h1>
|
||||
<div className="flex items-center space-x-2 text-sm text-gray-500 mb-4">
|
||||
<div className="text-[#31942E]">
|
||||
<div className="text-blue-400">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
|
|
@ -231,7 +232,7 @@ export default function DetailContent() {
|
|||
</svg>
|
||||
</div>
|
||||
|
||||
<span className="text-[#31942E] font-medium">
|
||||
<span className="text-blue-400 font-medium">
|
||||
{articleDetail?.createdByName}
|
||||
</span>
|
||||
<span>•</span>
|
||||
|
|
@ -252,19 +253,41 @@ export default function DetailContent() {
|
|||
</div>
|
||||
|
||||
<div className="w-full h-auto mb-6">
|
||||
{articleDetail?.files?.[0]?.file_url ? (
|
||||
{/* Gambar utama */}
|
||||
<div className="w-full">
|
||||
<Image
|
||||
src={articleDetail.files[0].file_url}
|
||||
alt="Berita"
|
||||
src={articleDetail.files[selectedIndex].fileUrl}
|
||||
alt={articleDetail.files[selectedIndex].fileAlt || "Berita"}
|
||||
width={800}
|
||||
height={400}
|
||||
className="rounded-lg w-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-[400px] bg-gray-100 flex items-center justify-center rounded-lg">
|
||||
<p className="text-gray-400 text-sm">Gambar tidak tersedia</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Thumbnail */}
|
||||
<div className="flex gap-2 mt-3 overflow-x-auto">
|
||||
{articleDetail.files.map((file: any, index: number) => (
|
||||
<button
|
||||
key={file.id || index}
|
||||
onClick={() => setSelectedIndex(index)}
|
||||
className={`border-2 rounded-lg overflow-hidden ${
|
||||
selectedIndex === index
|
||||
? "border-red-500"
|
||||
: "border-transparent"
|
||||
}`}
|
||||
>
|
||||
<Image
|
||||
src={file.fileUrl}
|
||||
alt={file.fileAlt || "Thumbnail"}
|
||||
width={100}
|
||||
height={80}
|
||||
className="object-cover"
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Slug */}
|
||||
<p className="text-sm text-gray-500 mt-2 text-end">
|
||||
{articleDetail?.slug}
|
||||
</p>
|
||||
|
|
@ -336,13 +359,13 @@ export default function DetailContent() {
|
|||
</Link>
|
||||
</div>
|
||||
<div className="flex-1 overflow-y-auto">
|
||||
<p className="text-gray-700 leading-relaxed text-justify">
|
||||
<span className="text-black font-bold text-md">
|
||||
Mikulnews.com -
|
||||
</span>
|
||||
|
||||
{articleDetail?.description}
|
||||
</p>
|
||||
<div className="text-gray-700 leading-relaxed text-justify">
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: articleDetail?.htmlDescription || "",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Author />
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<span className="font-semibold text-sm text-gray-700">
|
||||
|
|
@ -360,34 +383,12 @@ export default function DetailContent() {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative mb-2 h-[120px] overflow-hidden flex items-center border my-8">
|
||||
<Image
|
||||
src={"/image-kolom.png"}
|
||||
alt="Berita Utama"
|
||||
fill
|
||||
className="object-contain"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-10">
|
||||
<div className="flex items-center space-x-4 p-4 border rounded-lg mb-6">
|
||||
<Image
|
||||
src={"/author.png"}
|
||||
alt="Author"
|
||||
width={60}
|
||||
height={60}
|
||||
className="rounded-full"
|
||||
/>
|
||||
<div>
|
||||
<p className="text-green-600 font-bold text-lg">
|
||||
christine natalia
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-10">
|
||||
<h2 className="text-2xl font-bold mb-2">Tinggalkan Balasan</h2>
|
||||
<p className="text-gray-600 mb-4 text-sm">
|
||||
Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib
|
||||
ditandai <span className="text-green-600">*</span>
|
||||
ditandai <span className="text-blue-600">*</span>
|
||||
</p>
|
||||
|
||||
<form className="space-y-6 mt-6">
|
||||
|
|
@ -396,7 +397,7 @@ export default function DetailContent() {
|
|||
htmlFor="komentar"
|
||||
className="block text-sm font-medium mb-1"
|
||||
>
|
||||
Komentar <span className="text-green-600">*</span>
|
||||
Komentar <span className="text-blue-600">*</span>
|
||||
</label>
|
||||
<textarea
|
||||
id="komentar"
|
||||
|
|
@ -410,7 +411,7 @@ export default function DetailContent() {
|
|||
htmlFor="nama"
|
||||
className="block text-sm font-medium mb-1"
|
||||
>
|
||||
Nama <span className="text-green-600">*</span>
|
||||
Nama <span className="text-blue-600">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
|
|
@ -426,7 +427,7 @@ export default function DetailContent() {
|
|||
htmlFor="email"
|
||||
className="block text-sm font-medium mb-1"
|
||||
>
|
||||
Email <span className="text-green-600">*</span>
|
||||
Email <span className="text-blue-600">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
|
|
@ -465,7 +466,7 @@ export default function DetailContent() {
|
|||
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-green-600 hover:bg-green-700 text-white font-semibold px-6 py-2 rounded-md transition mt-2"
|
||||
className="bg-blue-600 hover:bg-blue-700 text-white font-semibold px-6 py-2 rounded-md transition mt-2"
|
||||
>
|
||||
KIRIM KOMENTAR
|
||||
</button>
|
||||
|
|
@ -584,82 +585,64 @@ export default function DetailContent() {
|
|||
</h3>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="relative">
|
||||
<Image
|
||||
src={"/gaza.png"}
|
||||
alt="Recommended Article"
|
||||
width={400}
|
||||
height={200}
|
||||
className="rounded-lg w-full h-auto object-cover"
|
||||
/>
|
||||
<div className="absolute bottom-0 left-0 right-0 bg-black bg-opacity-60 text-white p-3 rounded-b-lg">
|
||||
<p className="text-sm font-semibold leading-tight">
|
||||
Bom Bunuh Diri Guncang Gereja di Damaskus, 20 Orang Tewas
|
||||
dan Puluhan Terluka
|
||||
</p>
|
||||
<p className="text-xs text-gray-300 mt-1">
|
||||
📅 23 JUNI 2025
|
||||
</p>
|
||||
{/* Artikel utama (featured) */}
|
||||
{articles.length > 0 && (
|
||||
<div className="relative">
|
||||
<Image
|
||||
src={articles[0]?.thumbnailUrl || "/default.jpg"}
|
||||
alt={articles[0]?.title || "Recommended Article"}
|
||||
width={400}
|
||||
height={200}
|
||||
className="rounded-lg w-full h-auto object-cover"
|
||||
/>
|
||||
<div className="absolute bottom-0 left-0 right-0 bg-black bg-opacity-60 text-white p-3 rounded-b-lg">
|
||||
<p className="text-sm font-semibold leading-tight">
|
||||
{articles[0]?.title}
|
||||
</p>
|
||||
<p className="text-xs text-gray-300 mt-1">
|
||||
📅{" "}
|
||||
{new Date(articles[0]?.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "2-digit",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* List artikel lain */}
|
||||
<div className="space-y-3">
|
||||
<div className="flex space-x-3">
|
||||
<Image
|
||||
src={"/perang.png"}
|
||||
alt="OPM Serang Gereja"
|
||||
width={80}
|
||||
height={60}
|
||||
className="rounded object-cover w-[80px] h-[60px]"
|
||||
/>
|
||||
<div>
|
||||
<p className="text-sm font-semibold leading-snug">
|
||||
OPM Mulai Kehilangan Simpati dari Masyarakat Papua Usai
|
||||
Serang Gereja
|
||||
</p>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
📅 15 JUNI 2025
|
||||
</p>
|
||||
{articles.slice(1, 4).map((item) => (
|
||||
<div key={item.id} className="flex space-x-3">
|
||||
<Image
|
||||
src={item.thumbnailUrl || "/default.jpg"}
|
||||
alt={item.title}
|
||||
width={80}
|
||||
height={60}
|
||||
className="rounded object-cover w-[80px] h-[60px]"
|
||||
/>
|
||||
<div>
|
||||
<p className="text-sm font-semibold leading-snug">
|
||||
{item.title}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
📅{" "}
|
||||
{new Date(item.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "2-digit",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex space-x-3">
|
||||
<Image
|
||||
src={"/jateng.png"}
|
||||
alt="Denda Merokok"
|
||||
width={80}
|
||||
height={60}
|
||||
className="rounded object-cover w-[80px] h-[60px]"
|
||||
/>
|
||||
<div>
|
||||
<p className="text-sm font-semibold leading-snug">
|
||||
Jakarta Terapkan Denda Rp 250.000 bagi Warga yang
|
||||
Merokok Sembarangan
|
||||
</p>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
📅 13 JUNI 2025
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex space-x-3">
|
||||
<Image
|
||||
src={"/investasi.jpg"}
|
||||
alt="Pengguna Internet"
|
||||
width={80}
|
||||
height={60}
|
||||
className="rounded object-cover w-[80px] h-[60px]"
|
||||
/>
|
||||
<div>
|
||||
<p className="text-sm font-semibold leading-snug">
|
||||
Warga Indonesia Jadi Pengguna Internet via Ponsel
|
||||
Terbanyak di Dunia
|
||||
</p>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
📅 26 MEI 2025
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { getListArticle } from "@/service/article";
|
||||
import Link from "next/link";
|
||||
|
||||
type Article = {
|
||||
id: number;
|
||||
|
|
@ -16,7 +17,7 @@ type Article = {
|
|||
title: string;
|
||||
}[];
|
||||
files: {
|
||||
file_url: string;
|
||||
fileUrl: string;
|
||||
file_alt: string;
|
||||
}[];
|
||||
};
|
||||
|
|
@ -72,29 +73,31 @@ export default function BreakingNews() {
|
|||
<div className="md:col-span-2 space-y-6">
|
||||
{articles.map((item) => (
|
||||
<div key={item.id} className="flex gap-4 border-b pb-4">
|
||||
<Image
|
||||
src={item.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={item.title}
|
||||
width={160}
|
||||
height={100}
|
||||
className="object-cover rounded-md w-40 h-28"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-base font-semibold hover:text-blue-600 cursor-pointer">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
By {item.createdByName} •{" "}
|
||||
{new Date(item.createdAt).toLocaleDateString("id-ID", {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
})}
|
||||
</p>
|
||||
<p className="text-sm text-gray-600 mt-2 line-clamp-2">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
<Link className="flex gap-4" href={`/detail/${item?.id}`}>
|
||||
<Image
|
||||
src={item.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={item.title}
|
||||
width={160}
|
||||
height={100}
|
||||
className="object-cover rounded-md w-40 h-28"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-base font-semibold hover:text-blue-600 cursor-pointer">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
By {item.createdByName} •{" "}
|
||||
{new Date(item.createdAt).toLocaleDateString("id-ID", {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
})}
|
||||
</p>
|
||||
<p className="text-sm text-gray-600 mt-2 line-clamp-2">
|
||||
{item.description}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -148,25 +151,30 @@ export default function BreakingNews() {
|
|||
<div className="space-y-5">
|
||||
{/* Item pertama tampil besar */}
|
||||
<div className="relative">
|
||||
<Image
|
||||
src={popular[0]?.files?.[0]?.file_url || "/dummy.jpg"}
|
||||
alt={
|
||||
popular[0]?.files?.[0]?.file_alt ||
|
||||
popular[0]?.title ||
|
||||
"No Title"
|
||||
}
|
||||
width={400}
|
||||
height={200}
|
||||
className="w-full h-48 object-cover rounded-md"
|
||||
/>
|
||||
<div className="mt-2">
|
||||
<h5 className="text-sm font-semibold hover:text-blue-600 cursor-pointer">
|
||||
{popular[0]?.title}
|
||||
</h5>
|
||||
<span className="absolute top-2 right-2 text-4xl font-bold text-gray-300/80">
|
||||
01
|
||||
</span>
|
||||
</div>
|
||||
<Link
|
||||
className="flex flex-col gap-4"
|
||||
href={`/detail/${popular[0]?.id}`}
|
||||
>
|
||||
<Image
|
||||
src={popular[0]?.files?.[0]?.fileUrl || "/dummy.jpg"}
|
||||
alt={
|
||||
popular[0]?.files?.[0]?.file_alt ||
|
||||
popular[0]?.title ||
|
||||
"No Title"
|
||||
}
|
||||
width={400}
|
||||
height={200}
|
||||
className="w-full h-48 object-cover rounded-md"
|
||||
/>
|
||||
<div className="mt-2">
|
||||
<h5 className="text-sm font-semibold hover:text-blue-600 cursor-pointer">
|
||||
{popular[0]?.title}
|
||||
</h5>
|
||||
<span className="absolute top-2 right-2 text-4xl font-bold text-gray-300/80">
|
||||
01
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Item sisanya */}
|
||||
|
|
@ -176,15 +184,17 @@ export default function BreakingNews() {
|
|||
key={item.id}
|
||||
className="flex gap-3 items-start border-b pb-2 last:border-b-0"
|
||||
>
|
||||
<span className="text-lg font-bold text-gray-400">
|
||||
0{i + 2}
|
||||
</span>
|
||||
<div>
|
||||
<h5 className="text-sm font-medium hover:text-blue-600 cursor-pointer">
|
||||
{item.title}
|
||||
</h5>
|
||||
<p className="text-xs text-gray-400">0 Shares</p>
|
||||
</div>
|
||||
<Link className="flex gap-4" href={`/detail/${item?.id}`}>
|
||||
<span className="text-lg font-bold text-gray-400">
|
||||
0{i + 2}
|
||||
</span>
|
||||
<div>
|
||||
<h5 className="text-sm font-medium hover:text-blue-600 cursor-pointer">
|
||||
{item.title}
|
||||
</h5>
|
||||
<p className="text-xs text-gray-400">0 Shares</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { getListArticle } from "@/service/article";
|
||||
import Link from "next/link";
|
||||
|
||||
type Article = {
|
||||
id: number;
|
||||
|
|
@ -50,26 +51,28 @@ export default function HeaderLatest() {
|
|||
return (
|
||||
<header className="w-full pt-3 flex justify-center">
|
||||
<div className="relative max-w-screen-xl w-full h-[320px] md:h-[480px] mx-3 md:mx-5 overflow-hidden group">
|
||||
{/* Gambar utama */}
|
||||
<Image
|
||||
src={article?.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={article?.title || "No Title"}
|
||||
fill
|
||||
className="object-cover transition-transform duration-500 group-hover:scale-110"
|
||||
/>
|
||||
<Link className="flex" href={`/detail/${article?.id}`}>
|
||||
{/* Gambar utama */}
|
||||
<Image
|
||||
src={article?.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={article?.title || "No Title"}
|
||||
fill
|
||||
className="object-cover transition-transform duration-500 group-hover:scale-110"
|
||||
/>
|
||||
|
||||
{/* Overlay gradient */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent" />
|
||||
{/* Overlay gradient */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent" />
|
||||
|
||||
{/* Konten teks */}
|
||||
<div className="absolute bottom-5 left-5 text-white max-w-[80%]">
|
||||
<span className="bg-orange-600 text-white text-[10px] md:text-xs px-2 py-1 mb-3 inline-block font-semibold uppercase tracking-wide">
|
||||
{article?.categoryName || "Berita Terkini"}
|
||||
</span>
|
||||
<h1 className="text-lg md:text-2xl font-semibold leading-snug md:leading-tight">
|
||||
{article?.title || "Memuat..."}
|
||||
</h1>
|
||||
</div>
|
||||
{/* Konten teks */}
|
||||
<div className="absolute bottom-5 left-5 text-white max-w-[80%]">
|
||||
<span className="bg-orange-600 text-white text-[10px] md:text-xs px-2 py-1 mb-3 inline-block font-semibold uppercase tracking-wide">
|
||||
{article?.categoryName || "Berita Terkini"}
|
||||
</span>
|
||||
<h1 className="text-lg md:text-2xl font-semibold leading-snug md:leading-tight">
|
||||
{article?.title || "Memuat..."}
|
||||
</h1>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { getListArticle } from "@/service/article";
|
||||
import Link from "next/link";
|
||||
|
||||
type Article = {
|
||||
id: number;
|
||||
|
|
@ -48,31 +49,33 @@ export default function HeaderNews() {
|
|||
<div className="py-6 grid grid-cols-1 md:grid-cols-2 gap-4 h-[600px]">
|
||||
{/* Kiri - berita utama */}
|
||||
<div className="relative overflow-hidden h-full">
|
||||
<Image
|
||||
src={articles[0]?.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={articles[0]?.title || "No Title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
|
||||
<div className="absolute bottom-4 left-4 right-4 text-white">
|
||||
<span className="bg-black/70 text-xs px-2 py-1 rounded">
|
||||
{articles[0]?.categories?.[0]?.title || "Uncategorized"}
|
||||
</span>
|
||||
<h2 className="text-2xl font-bold mt-2">{articles[0]?.title}</h2>
|
||||
<p className="text-sm mt-1">
|
||||
<span className="font-semibold">
|
||||
{articles[0]?.createdByName}
|
||||
</span>{" "}
|
||||
•{" "}
|
||||
{articles[0]?.createdAt &&
|
||||
new Date(articles[0].createdAt).toLocaleDateString("id-ID", {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
<Link className="flex" href={`/detail/${articles[0]?.id}`}>
|
||||
<Image
|
||||
src={articles[0]?.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={articles[0]?.title || "No Title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
|
||||
<div className="absolute bottom-4 left-4 right-4 text-white">
|
||||
<span className="bg-black/70 text-xs px-2 py-1 rounded">
|
||||
{articles[0]?.categories?.[0]?.title || "Uncategorized"}
|
||||
</span>
|
||||
<h2 className="text-2xl font-bold mt-2">{articles[0]?.title}</h2>
|
||||
<p className="text-sm mt-1">
|
||||
<span className="font-semibold">
|
||||
{articles[0]?.createdByName}
|
||||
</span>{" "}
|
||||
•{" "}
|
||||
{articles[0]?.createdAt &&
|
||||
new Date(articles[0].createdAt).toLocaleDateString("id-ID", {
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Kanan - 3 berita */}
|
||||
|
|
@ -86,33 +89,38 @@ export default function HeaderNews() {
|
|||
key={item.id || `dummy-${idx}`}
|
||||
className="relative overflow-hidden"
|
||||
>
|
||||
<Image
|
||||
src={item.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={item.title || "No Title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
|
||||
<div className="absolute bottom-2 left-2 right-2 text-white">
|
||||
<span className="bg-black/70 text-[10px] px-2 py-1 rounded">
|
||||
{item.categories?.[0]?.title || "Uncategorized"}
|
||||
</span>
|
||||
<h3 className="text-sm font-semibold mt-1 line-clamp-2">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-[10px]">
|
||||
<span className="font-semibold">
|
||||
{item.createdByName}
|
||||
</span>{" "}
|
||||
•{" "}
|
||||
{item.createdAt &&
|
||||
new Date(item.createdAt).toLocaleDateString("id-ID", {
|
||||
day: "numeric",
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
})}
|
||||
</p>
|
||||
</div>
|
||||
<Link className="flex" href={`/detail/${item?.id}`}>
|
||||
<Image
|
||||
src={item.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={item.title || "No Title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
|
||||
<div className="absolute bottom-2 left-2 right-2 text-white">
|
||||
<span className="bg-black/70 text-[10px] px-2 py-1 rounded">
|
||||
{item.categories?.[0]?.title || "Uncategorized"}
|
||||
</span>
|
||||
<h3 className="text-sm font-semibold mt-1 line-clamp-2">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="text-[10px]">
|
||||
<span className="font-semibold">
|
||||
{item.createdByName}
|
||||
</span>{" "}
|
||||
•{" "}
|
||||
{item.createdAt &&
|
||||
new Date(item.createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
|
|
@ -121,36 +129,38 @@ export default function HeaderNews() {
|
|||
{/* Bawah: 1 berita besar */}
|
||||
{articles[3] && (
|
||||
<div className="relative overflow-hidden">
|
||||
<Image
|
||||
src={articles[3]?.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={articles[3]?.title || "No Title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
|
||||
<div className="absolute bottom-2 left-2 right-2 text-white">
|
||||
<span className="bg-black/70 text-xs px-2 py-1 rounded">
|
||||
{articles[3]?.categories?.[0]?.title || "Uncategorized"}
|
||||
</span>
|
||||
<h3 className="text-base font-semibold mt-1">
|
||||
{articles[3]?.title}
|
||||
</h3>
|
||||
<p className="text-xs">
|
||||
<span className="font-semibold">
|
||||
{articles[3]?.createdByName}
|
||||
</span>{" "}
|
||||
•{" "}
|
||||
{articles[3]?.createdAt &&
|
||||
new Date(articles[3].createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<Link className="flex" href={`/detail/${articles[3]?.id}`}>
|
||||
<Image
|
||||
src={articles[3]?.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={articles[3]?.title || "No Title"}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
|
||||
<div className="absolute bottom-2 left-2 right-2 text-white">
|
||||
<span className="bg-black/70 text-xs px-2 py-1 rounded">
|
||||
{articles[3]?.categories?.[0]?.title || "Uncategorized"}
|
||||
</span>
|
||||
<h3 className="text-base font-semibold mt-1">
|
||||
{articles[3]?.title}
|
||||
</h3>
|
||||
<p className="text-xs">
|
||||
<span className="font-semibold">
|
||||
{articles[3]?.createdByName}
|
||||
</span>{" "}
|
||||
•{" "}
|
||||
{articles[3]?.createdAt &&
|
||||
new Date(articles[3].createdAt).toLocaleDateString(
|
||||
"id-ID",
|
||||
{
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -20,12 +20,21 @@ export default function Navbar() {
|
|||
|
||||
{/* Menu (opsional kalau nanti ada navigasi) */}
|
||||
<nav className="hidden md:flex items-center gap-6 text-sm font-medium text-gray-700">
|
||||
<a href="#" className="hover:text-blue-600">
|
||||
<a href="/" className="hover:text-blue-600">
|
||||
Home
|
||||
</a>
|
||||
<a href="/category/latest-news" className="hover:text-blue-600">
|
||||
Berita Terbaru
|
||||
</a>
|
||||
<a href="/category/popular-news" className="hover:text-blue-600">
|
||||
Berita Populer
|
||||
</a>
|
||||
<a href="/category/protect" className="hover:text-blue-600">
|
||||
Jaga Negeri
|
||||
</a>
|
||||
<a href="/category/opinion-news" className="hover:text-blue-600">
|
||||
Berita Opini
|
||||
</a>
|
||||
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<Link
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { getListArticle } from "@/service/article";
|
||||
import Link from "next/link";
|
||||
|
||||
type Article = {
|
||||
id: number;
|
||||
|
|
@ -53,21 +54,23 @@ export default function Story() {
|
|||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
{articles.map((item) => (
|
||||
<div key={item.id} className="relative overflow-hidden h-72">
|
||||
<Image
|
||||
src={item.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={item.title}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/40"></div>
|
||||
<div className="absolute inset-0 flex flex-col items-center justify-center text-center px-4 text-white">
|
||||
<span className="bg-black/70 text-xs px-3 py-1 rounded mb-2">
|
||||
{item.categories[0]?.title || "Uncategorized"}
|
||||
</span>
|
||||
<h3 className="text-sm font-semibold leading-snug line-clamp-3">
|
||||
{item.title}
|
||||
</h3>
|
||||
</div>
|
||||
<Link className="flex" href={`/detail/${item?.id}`}>
|
||||
<Image
|
||||
src={item.thumbnailUrl || "/dummy.jpg"}
|
||||
alt={item.title}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/40"></div>
|
||||
<div className="absolute inset-0 flex flex-col items-center justify-center text-center px-4 text-white">
|
||||
<span className="bg-black/70 text-xs px-3 py-1 rounded mb-2">
|
||||
{item.categories[0]?.title || "Uncategorized"}
|
||||
</span>
|
||||
<h3 className="text-sm font-semibold leading-snug line-clamp-3">
|
||||
{item.title}
|
||||
</h3>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ import {
|
|||
TableCell,
|
||||
} from "@/components/ui/table";
|
||||
import CustomPagination from "../layout/custom-pagination";
|
||||
import { $ZodNumberDef } from "zod/v4/core";
|
||||
|
||||
const columns = [
|
||||
{ name: "No", uid: "no" },
|
||||
|
|
@ -173,11 +174,11 @@ export default function ArticleTable() {
|
|||
initState();
|
||||
};
|
||||
|
||||
const copyUrlArticle = async (id: number, slug: string) => {
|
||||
const copyUrlArticle = async (id: $ZodNumberDef) => {
|
||||
const url =
|
||||
`${window.location.protocol}//${window.location.host}` +
|
||||
"/news/detail/" +
|
||||
`${id}-${slug}`;
|
||||
"/detail/" +
|
||||
`${id}`;
|
||||
try {
|
||||
await navigator.clipboard.writeText(url);
|
||||
successToast("Success", "Article Copy to Clipboard");
|
||||
|
|
@ -228,9 +229,7 @@ export default function ArticleTable() {
|
|||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56">
|
||||
<DropdownMenuItem
|
||||
onClick={() => copyUrlArticle(article.id, article.slug)}
|
||||
>
|
||||
<DropdownMenuItem onClick={() => copyUrlArticle(article.id)}>
|
||||
<CopyIcon className="mr-2 h-4 w-4" />
|
||||
Copy Url Article
|
||||
</DropdownMenuItem>
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
Loading…
Reference in New Issue