This commit is contained in:
Anang Yusman 2025-10-07 00:25:25 +08:00
parent 97653728d3
commit 7e1f6df655
9 changed files with 548 additions and 610 deletions

29
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,29 @@
stages:
- build
- deploy
build-dev:
stage: build
when: on_success
only:
- main
image: docker:stable
services:
- name: docker:dind
command: ["--insecure-registry=103.82.242.92:8900"]
script:
- docker logout
- docker login -u $DEPLOY_USERNAME -p $DEPLOY_TOKEN 103.82.242.92:8900
- docker build -t 103.82.242.92:8900/medols/web-fokus-aja:dev .
- docker push 103.82.242.92:8900/medols/web-fokus-aja:dev
auto-deploy:
stage: deploy
when: on_success
only:
- main
image: curlimages/curl:latest
services:
- docker:dind
script:
- curl --user admin:$JENKINS_PWD http://38.47.180.165:8080/job/auto-deploy-fokus-aja/build?token=autodeploymedols

36
Dockerfile Normal file
View File

@ -0,0 +1,36 @@
# Menggunakan image Node.js yang lebih ringan
FROM node:23.5.0-alpine
# Mengatur port
ENV PORT 3000
# Install pnpm secara global
RUN npm install -g pnpm
# Membuat direktori aplikasi dan mengatur sebagai working directory
WORKDIR /usr/src/app
# Menyalin file penting terlebih dahulu untuk caching
COPY package.json ./
# Menyalin direktori ckeditor5 jika diperlukan
COPY vendor/ckeditor5 ./vendor/ckeditor5
# Menyalin env
COPY .env .env
# Install dependencies
RUN pnpm install
# RUN pnpm install --frozen-lockfile
# Menyalin source code aplikasi
COPY . .
# Build aplikasi
RUN NODE_OPTIONS="--max-old-space-size=4096" pnpm next build
# Expose port untuk server
EXPOSE 3000
# Perintah untuk menjalankan aplikasi
CMD ["pnpm", "run", "start"]

View File

@ -6,17 +6,6 @@ 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="fixed top-0 left-0 w-full h-auto z-0">
<Image
src="/rumput.jpg"
alt="Background"
width={1450}
height={600}
className="w-full h-auto object-cover"
priority
/>
</div>
<div className="relative z-10 bg-[#F2F4F3] max-w-7xl mx-auto">
<Navbar />
<div className="flex-1">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@ -13,8 +13,8 @@ const geistMono = Geist_Mono({
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: "Fokus Aja",
description: "Fokus Aja",
};
export default function RootLayout({

View File

@ -5,6 +5,7 @@ import Link from "next/link";
import { getArticleById, getListArticle } from "@/service/article";
import { close, loading } from "@/config/swal";
import { useParams } from "next/navigation";
import { CommentIcon } from "../icons/sidebar-icon";
import { Link2, MailIcon } from "lucide-react";
type TabKey = "trending" | "comments" | "latest";
@ -13,7 +14,6 @@ type Article = {
id: number;
title: string;
description: string;
htmlDescription: string;
categoryName: string;
createdAt: string;
createdByName: string;
@ -41,9 +41,9 @@ export default function DetailContent() {
const [articles, setArticles] = useState<Article[]>([]);
const [articleDetail, setArticleDetail] = useState<any>(null);
const [showData, setShowData] = useState("5");
const [search, setSearch] = useState("-");
const [search, setSearch] = useState("");
const [listCategory, setListCategory] = useState<CategoryType[]>([]);
const [selectedCategories, setSelectedCategories] = useState<any>("-");
const [selectedCategories, setSelectedCategories] = useState<any>("");
const [startDateValue, setStartDateValue] = useState({
startDate: null,
endDate: null,
@ -69,46 +69,29 @@ export default function DetailContent() {
];
useEffect(() => {
fetchTabArticles();
}, [activeTab]);
initState();
}, [page, showData, startDateValue, selectedCategories]);
async function fetchTabArticles() {
const req: any = {
async function initState() {
// loading();
const req = {
limit: showData,
page,
search,
categorySlug: Array.from(selectedCategories).join(","),
sort: "desc",
isPublish: true,
sortBy: "created_at",
};
// Sesuaikan sortBy berdasarkan tab
if (activeTab === "trending") {
req.sortBy = "view_count";
} else if (activeTab === "comments") {
req.sortBy = "comment_count";
} else {
req.sortBy = "created_at";
}
// Hanya kirimkan search jika valid
if (search && search !== "-" && search !== "") {
req.search = search;
}
if (selectedCategories && selectedCategories !== "-") {
req.categorySlug = selectedCategories;
}
try {
const res = await getListArticle(req);
setTabArticles(res?.data?.data || []);
} catch (error) {
console.error("Failed fetching tab articles:", error);
setTabArticles([]); // Optional fallback
setArticles(res?.data?.data || []);
setTotalPage(res?.data?.meta?.totalPage || 1);
} finally {
// close();
}
}
const content: Record<
TabKey,
{ image: string; title: string; date: string }[]
@ -154,30 +137,6 @@ export default function DetailContent() {
],
};
useEffect(() => {
initState();
}, [page, showData, startDateValue, selectedCategories]);
async function initState() {
// loading();
const req = {
limit: showData,
page,
search,
categorySlug: Array.from(selectedCategories).join(","),
sort: "desc",
sortBy: "created_at",
};
try {
const res = await getListArticle(req);
setArticles(res?.data?.data || []);
setTotalPage(res?.data?.meta?.totalPage || 1);
} finally {
// close();
}
}
useEffect(() => {
initStateData();
}, [listCategory]);
@ -194,79 +153,65 @@ export default function DetailContent() {
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>
<h1 className="text-3xl md:text-4xl font-bold text-[#1a1a1a] leading-tight mb-4">
{articleDetail?.title}
</h1>
<div className="flex items-center space-x-2 text-sm text-gray-500 mb-4">
<div className="text-[#31942E]">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<g
fill="none"
// fill-rule="evenodd"
<div className="flex flex-row justify-between items-center space-x-2 text-sm text-black mb-4">
<div className="flex flex-row gap-3">
<div className="text-[#31942E]">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path d="m12.594 23.258l-.012.002l-.071.035l-.02.004l-.014-.004l-.071-.036q-.016-.004-.024.006l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.016-.018m.264-.113l-.014.002l-.184.093l-.01.01l-.003.011l.018.43l.005.012l.008.008l.201.092q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.003-.011l.018-.43l-.003-.012l-.01-.01z" />
<path
fill="currentColor"
d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10s10-4.477 10-10S17.523 2 12 2M8.5 9.5a3.5 3.5 0 1 1 7 0a3.5 3.5 0 0 1-7 0m9.758 7.484A7.99 7.99 0 0 1 12 20a7.99 7.99 0 0 1-6.258-3.016C7.363 15.821 9.575 15 12 15s4.637.821 6.258 1.984"
/>
</g>
</svg>
</div>
<g
fill="none"
// fill-rule="evenodd"
>
<path d="m12.594 23.258l-.012.002l-.071.035l-.02.004l-.014-.004l-.071-.036q-.016-.004-.024.006l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.016-.018m.264-.113l-.014.002l-.184.093l-.01.01l-.003.011l.018.43l.005.012l.008.008l.201.092q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.003-.011l.018-.43l-.003-.012l-.01-.01z" />
<path
fill="currentColor"
d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10s10-4.477 10-10S17.523 2 12 2M8.5 9.5a3.5 3.5 0 1 1 7 0a3.5 3.5 0 0 1-7 0m9.758 7.484A7.99 7.99 0 0 1 12 20a7.99 7.99 0 0 1-6.258-3.016C7.363 15.821 9.575 15 12 15s4.637.821 6.258 1.984"
/>
</g>
</svg>
</div>
<span className="text-[#31942E] font-medium">
{articleDetail?.createdByName}
</span>
<span></span>
<span>
<span>
{new Date(articleDetail?.createdAt).toLocaleDateString(
"id-ID",
{
day: "numeric",
month: "long",
year: "numeric",
}
)}
<span className="text-[#31942E] font-medium">
{articleDetail?.createdByName}
</span>
</span>
<span></span>
<span>{articleDetail?.categories?.[0]?.title}</span>
<span>-</span>
<span>
<span>
{new Date(articleDetail?.createdAt).toLocaleDateString(
"id-ID",
{
day: "numeric",
month: "long",
year: "numeric",
}
)}
</span>
</span>
<span className="text-gray-500">in</span>
<span>{articleDetail?.categories?.[0]?.title}</span>
</div>
<div className="flex items-center">
<CommentIcon />0
</div>
</div>
<div className="w-full h-auto mb-6">
{/* Gambar utama */}
<div className="w-full">
<Image
src={articleDetail.files[selectedIndex].fileUrl}
alt={articleDetail.files[selectedIndex].fileAlt || "Berita"}
src={articleDetail?.files[selectedIndex].fileUrl}
alt={articleDetail?.files[selectedIndex].fileAlt || "Berita"}
width={800}
height={400}
className="rounded-lg w-full object-cover"
@ -275,7 +220,7 @@ export default function DetailContent() {
{/* Thumbnail */}
<div className="flex gap-2 mt-3 overflow-x-auto">
{articleDetail.files.map((file: any, index: number) => (
{articleDetail?.files.map((file: any, index: number) => (
<button
key={file.id || index}
onClick={() => setSelectedIndex(index)}
@ -296,13 +241,15 @@ export default function DetailContent() {
))}
</div>
{/* Slug */}
<p className="text-sm text-gray-500 mt-2 text-end">
{articleDetail?.slug}
</p>
</div>
<div className="flex relative">
<div className=" flex flex-col w-fit rounded overflow-hidden mr-5">
<div className=" flex flex-row w-fit rounded overflow-hidden mr-5 gap-3 mt-3">
<div className="flex flex-col items-center gap-2">
<p className="text-red-500 font-semibold">0</p>
<p className="text-red-500 font-semibold">SHARES</p>
</div>
<div className="flex flex-col items-center gap-2">
<p className="text-black font-semibold">3</p>
<p className="text-black font-semibold">VIEWS</p>
</div>
<Link
href="#"
aria-label="Facebook"
@ -337,46 +284,88 @@ export default function DetailContent() {
<Link
href="#"
aria-label="Google"
className="bg-[#fce9e7] p-4 flex justify-center items-center text-white"
aria-label="WhatsApp"
className="bg-green-700 p-4 flex justify-center items-center text-white"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M7.796 14.333v-2.618h7.211c.066.382.12.763.12 1.265c0 4.364-2.923 7.462-7.33 7.462A7.63 7.63 0 0 1 .16 12.806a7.63 7.63 0 0 1 7.636-7.637c2.062 0 3.786.753 5.117 1.997L10.84 9.162c-.567-.546-1.56-1.178-3.044-1.178c-2.607 0-4.734 2.16-4.734 4.822s2.127 4.821 4.734 4.821c3.022 0 4.157-2.17 4.331-3.294zm13.27-2.6H23.2v2.134h-2.133V16h-2.134v-2.133H16.8v-2.134h2.133V9.6h2.134z" />
<g fill="none">
<g
// clip-path="url(#SVGXv8lpc2Y)"
>
<path
fill="currentColor"
// fill-rule="evenodd"
d="M17.415 14.382c-.298-.149-1.759-.867-2.031-.967s-.47-.148-.669.15c-.198.297-.767.966-.94 1.164c-.174.199-.347.223-.644.075c-.297-.15-1.255-.463-2.39-1.475c-.883-.788-1.48-1.761-1.653-2.059c-.173-.297-.019-.458.13-.606c.134-.133.297-.347.446-.52s.198-.298.297-.497c.1-.198.05-.371-.025-.52c-.074-.149-.668-1.612-.916-2.207c-.241-.579-.486-.5-.668-.51c-.174-.008-.372-.01-.57-.01s-.52.074-.792.372c-.273.297-1.04 1.016-1.04 2.479c0 1.462 1.064 2.875 1.213 3.074s2.095 3.2 5.076 4.487c.71.306 1.263.489 1.694.625c.712.227 1.36.195 1.872.118c.57-.085 1.758-.719 2.006-1.413s.247-1.289.173-1.413s-.272-.198-.57-.347m-5.422 7.403h-.004a9.87 9.87 0 0 1-5.032-1.378l-.36-.214l-3.742.982l.999-3.648l-.235-.374a9.86 9.86 0 0 1-1.511-5.26c.002-5.45 4.436-9.884 9.889-9.884a9.8 9.8 0 0 1 6.988 2.899a9.82 9.82 0 0 1 2.892 6.992c-.002 5.45-4.436 9.885-9.884 9.885m8.412-18.297A11.82 11.82 0 0 0 11.992 0C5.438 0 .102 5.335.1 11.892a11.86 11.86 0 0 0 1.587 5.945L0 24l6.304-1.654a11.9 11.9 0 0 0 5.684 1.448h.005c6.554 0 11.89-5.335 11.892-11.893a11.82 11.82 0 0 0-3.48-8.413"
// clip-rule="evenodd"
/>
</g>
<defs>
<clipPath id="SVGXv8lpc2Y">
<path fill="#fff" d="M0 0h24v24H0z" />
</clipPath>
</defs>
</g>
</svg>
</Link>
<Link
href="#"
aria-label="Share"
className="bg-[#cccccc] p-4 flex justify-center items-center text-white"
aria-label="Telegram"
className="bg-blue-400 p-4 flex justify-center items-center text-white"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
viewBox="0 0 24 24"
viewBox="0 0 256 256"
>
<path d="m21 12l-7-7v4C7 10 4 15 3 20c2.5-3.5 6-5.1 11-5.1V19z" />
<defs>
<linearGradient
id="SVGuySfwdaH"
x1="50%"
x2="50%"
y1="0%"
y2="100%"
>
<stop
offset="0%"
// stop-color="#2aabee"
/>
<stop
offset="100%"
// stop-color="#229ed9"
/>
</linearGradient>
</defs>
<path
fill="url(#SVGuySfwdaH)"
d="M128 0C94.06 0 61.48 13.494 37.5 37.49A128.04 128.04 0 0 0 0 128c0 33.934 13.5 66.514 37.5 90.51C61.48 242.506 94.06 256 128 256s66.52-13.494 90.5-37.49c24-23.996 37.5-56.576 37.5-90.51s-13.5-66.514-37.5-90.51C194.52 13.494 161.94 0 128 0"
/>
<path
fill="#fff"
d="M57.94 126.648q55.98-24.384 74.64-32.152c35.56-14.786 42.94-17.354 47.76-17.441c1.06-.017 3.42.245 4.96 1.49c1.28 1.05 1.64 2.47 1.82 3.467c.16.996.38 3.266.2 5.038c-1.92 20.24-10.26 69.356-14.5 92.026c-1.78 9.592-5.32 12.808-8.74 13.122c-7.44.684-13.08-4.912-20.28-9.63c-11.26-7.386-17.62-11.982-28.56-19.188c-12.64-8.328-4.44-12.906 2.76-20.386c1.88-1.958 34.64-31.748 35.26-34.45c.08-.338.16-1.598-.6-2.262c-.74-.666-1.84-.438-2.64-.258c-1.14.256-19.12 12.152-54 35.686c-5.1 3.508-9.72 5.218-13.88 5.128c-4.56-.098-13.36-2.584-19.9-4.708c-8-2.606-14.38-3.984-13.82-8.41c.28-2.304 3.46-4.662 9.52-7.072"
/>
</svg>
</Link>
</div>
<p className="text-sm text-gray-500 mt-2 text-start">
{articleDetail?.slug}
</p>
</div>
<div className="flex relative">
<div className="flex-1 overflow-y-auto">
<div className="prose max-w-none text-justify">
<div className="text-gray-700 leading-relaxed text-justify">
<div
dangerouslySetInnerHTML={{
__html: articleDetail?.htmlDescription || "",
}}
/>
</div>
{/* <Author /> */}
<div className="w-full bg-white py-6">
<p className="mx-10 text-2xl mb-4 ">AUTHOR</p>
<div className=" border border-black p-6 flex items-center gap-6 max-w-[1200px] mx-auto">
@ -443,25 +432,10 @@ export default function DetailContent() {
/>
</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> */}
<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-red-500">*</span>
</p>
<form className="space-y-6 mt-6">
@ -470,11 +444,11 @@ 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-red-500">*</span>
</label>
<textarea
id="komentar"
className="w-full border border-gray-300 rounded-md p-3 h-40 focus:outline-none focus:ring-2 focus:ring-green-600"
className="w-full border border-gray-300 rounded-md p-3 h-40 focus:outline-none focus:ring-2 focus:ring-red-600"
required
/>
</div>
@ -484,7 +458,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-red-500">*</span>
</label>
<input
type="text"
@ -500,7 +474,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-red-500">*</span>
</label>
<input
type="email"
@ -539,7 +513,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-red-500 hover:bg-red-700 text-white font-semibold px-6 py-2 rounded-md transition mt-2"
>
KIRIM KOMENTAR
</button>
@ -549,193 +523,49 @@ export default function DetailContent() {
<div className="md:col-span-1 space-y-6">
<div className="sticky top-0 space-y-6">
<div className="bg-white shadow p-4 rounded-lg">
<Image
src={"/kolom.png"}
alt="Iklan"
width={345}
height={345}
className="rounded"
/>
<button className="mt-4 w-full bg-black text-white py-2 rounded hover:opacity-90">
Learn More
</button>
</div>
<div className="space-y-6">
{articles?.map((article) => (
<div key={article.id}>
<div>
<Link
className="flex space-x-3 mb-2"
href={`/detail/${article.id}`}
>
<Image
src={article.thumbnailUrl || "/default-thumb.png"}
alt={article.title}
width={120}
height={80}
className="rounded object-cover w-[120px] h-[80px]"
/>
<div className="flex-1">
<p className="text-sm font-bold leading-snug hover:text-red-700">
{article.title}
</p>
<div className="bg-white shadow p-4 rounded-lg">
<h2 className="text-lg font-semibold mb-2">Connect with us</h2>
<div className="flex space-x-2">
<div className="bg-[#0057ff] text-white px-3 py-2 rounded">
<p className="text-sm font-bold"></p>
<p className="text-xs">139 Followers</p>
<div className="flex items-center text-xs text-gray-500 mt-1 space-x-2">
<span>
📅{" "}
{new Date(article.createdAt).toLocaleDateString(
"id-ID",
{
day: "2-digit",
month: "long",
year: "numeric",
}
)}
</span>
<span>💬 0</span>
</div>
</div>
</Link>
</div>
<p className="text-sm text-gray-700 line-clamp-2">
{article.description.slice(0, 120)}...
</p>
</div>
<div className="bg-[#ff0000] text-white px-3 py-2 rounded">
<p className="text-sm font-bold">YouTube</p>
<p className="text-xs">205k Subscribers</p>
</div>
<div className="bg-[#f9a825] text-white px-3 py-2 rounded">
<p className="text-sm font-bold">RSS</p>
<p className="text-xs">23.9k Followers</p>
</div>
</div>
</div>
<div className="bg-white shadow p-4 rounded-lg">
<div className="flex space-x-4 border-b mb-4">
{tabs.map((tab) => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`pb-2 text-sm font-medium ${
activeTab === tab.id
? "border-b-2 border-green-600 text-green-600"
: "text-gray-600"
}`}
>
{tab.label}
</button>
))}
</div>
<div className="space-y-4">
{tabArticles.map((item, idx) => (
<div key={idx} className="flex space-x-3">
<Image
src={item.thumbnailUrl || "/default-thumb.png"}
alt={item.title}
width={70}
height={70}
className="rounded w-[70px] h-[70px] object-cover"
/>
<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>
{tabArticles.length === 0 ? (
<p className="text-sm text-gray-500">
Artikel tidak ditemukan.
</p>
) : (
tabArticles.map((item, idx) => (
<div key={idx} className="flex space-x-3">
<Image
src={item.thumbnailUrl || "/default-thumb.png"}
alt={item.title}
width={70}
height={70}
className="rounded w-[70px] h-[70px] object-cover"
/>
<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="mt-6">
<h3 className="text-base font-semibold mb-2 text-gray-800 border-b pb-1 border-green-600 inline-block">
Recommended
</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>
</div>
</div>
<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>
</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>
</div>
</div>

View File

@ -1,6 +1,7 @@
"use client";
import { getListArticle } from "@/service/article";
import Image from "next/image";
import Link from "next/link";
import { useEffect, useState } from "react";
type Article = {
@ -64,22 +65,31 @@ export default function Header() {
key={index}
className="border border-gray-200 overflow-hidden shadow-sm bg-white h-[440px]"
>
<Image
src={article.thumbnailUrl}
alt={article.title}
width={267}
height={191}
className="w-full h-48 object-cover"
/>
<div className="p-4 text-center">
<p className="text-xs text-gray-400 font-medium tracking-wider uppercase py-2">
{article?.categories?.[0]?.title || "TANPA KATEGORI"}
</p>
<h3 className="text-lg font-semibold text-gray-900 mb-4 leading-snug px-8">
{article.title}
</h3>
<p className="text-xs text-gray-400">{article.createdAt}</p>
</div>
<Link href={`/detail/${article?.id}`}>
<Image
src={article.thumbnailUrl}
alt={article.title}
width={267}
height={191}
className="w-full h-48 object-cover"
/>
<div className="p-4 text-center">
<p className="text-xs text-gray-400 font-medium tracking-wider uppercase py-2">
{article?.categories?.[0]?.title || "TANPA KATEGORI"}
</p>
<h3 className="text-lg font-semibold text-gray-900 mb-4 leading-snug px-8">
{article.title}
</h3>
<p className="text-xs text-gray-400">
{" "}
{new Date(article.createdAt).toLocaleDateString("id-ID", {
day: "2-digit",
month: "long",
year: "numeric",
})}
</p>
</div>
</Link>
</div>
))}
</div>

View File

@ -4,6 +4,7 @@ import { Card } from "../ui/card";
import Image from "next/image";
import { useEffect, useRef, useState } from "react";
import { getListArticle } from "@/service/article";
import Link from "next/link";
type Article = {
id: number;
@ -80,18 +81,23 @@ export default function Beranda() {
</h2>
<ul className="space-y-4">
{articles.map((news, i) => (
<li key={i} className="flex gap-3 items-start">
<Image
src={news?.thumbnailUrl as string}
width={100}
height={71}
alt={news.title}
className="w-[100px] h-[71px] object-cover"
/>
<li key={i}>
<Link
className="flex gap-3 items-start"
href={`/detail/${news?.id}`}
>
<Image
src={news?.thumbnailUrl as string}
width={100}
height={71}
alt={news.title}
className="w-[100px] h-[71px] object-cover"
/>
<p className="text-sm leading-snug font-semibold px-2">
{news.title}
</p>
<p className="text-sm leading-snug font-semibold px-2">
{news.title}
</p>
</Link>
</li>
))}
</ul>
@ -100,28 +106,30 @@ export default function Beranda() {
<h2 className="text-lg font-semibold border-b ">Berita Opini</h2>
<ul className="space-y-3 ">
{articles.map((news, i) => (
<li
key={i}
className="flex items-start gap-2 text-sm font-medium border-b"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
<li key={i}>
<Link
className="flex items-start gap-2 text-sm font-medium border-b"
href={`/detail/${news?.id}`}
>
<g
fill="none"
// fill-rule="evenodd"
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path
fill="currentColor"
d="M5.669 4.76a1.47 1.47 0 0 1 2.04-1.177c1.062.454 3.442 1.533 6.462 3.276c3.021 1.744 5.146 3.267 6.069 3.958c.788.591.79 1.763.001 2.356c-.914.687-3.013 2.19-6.07 3.956c-3.06 1.766-5.412 2.832-6.464 3.28c-.906.387-1.92-.2-2.038-1.177c-.138-1.142-.396-3.735-.396-7.237c0-3.5.257-6.092.396-7.235"
/>
</g>
</svg>
{news.title}
<g
fill="none"
// fill-rule="evenodd"
>
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path
fill="currentColor"
d="M5.669 4.76a1.47 1.47 0 0 1 2.04-1.177c1.062.454 3.442 1.533 6.462 3.276c3.021 1.744 5.146 3.267 6.069 3.958c.788.591.79 1.763.001 2.356c-.914.687-3.013 2.19-6.07 3.956c-3.06 1.766-5.412 2.832-6.464 3.28c-.906.387-1.92-.2-2.038-1.177c-.138-1.142-.396-3.735-.396-7.237c0-3.5.257-6.092.396-7.235"
/>
</g>
</svg>
{news.title}
</Link>
</li>
))}
</ul>
@ -133,66 +141,82 @@ export default function Beranda() {
</h2>
<div className="space-y-4 ">
<div>
<div className="relative">
<img
src={articles[0]?.thumbnailUrl}
alt={articles[0]?.title}
className="w-full h-auto object-cover"
/>
<span className="absolute bottom-1 left-1 bg-black text-white text-xs px-2 py-1">
{articles[0]?.categories?.[0]?.title || "TANPA KATEGORI"}
</span>
</div>
<h3 className="text-base font-bold mt-2">{articles[0]?.title}</h3>
<p className="text-xs text-[#A0A0A0] mt-1 flex items-center gap-1">
{" "}
<span className="text-black">
{articles[0]?.createdByName}{" "}
</span>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
>
<g fill="none">
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path
fill="currentColor"
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
/>
</g>
</svg>{" "}
{articles[0]?.createdAt}
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
<Link href={`/detail/${articles[0]?.id}`}>
<div className="relative">
<img
src={articles[0]?.thumbnailUrl}
alt={articles[0]?.title}
className="w-full h-auto object-cover"
/>
</svg>
0
</p>
<p className="text-sm font-serif text-[#A0A0A0] mt-3 line-clamp-3">
{articles[0]?.description}
</p>
<span className="absolute bottom-1 left-1 bg-black text-white text-xs px-2 py-1">
{articles[0]?.categories?.[0]?.title || "TANPA KATEGORI"}
</span>
</div>
<h3 className="text-base font-bold mt-2">
{articles[0]?.title}
</h3>
<p className="text-xs text-[#A0A0A0] mt-1 flex items-center gap-1">
{" "}
<span className="text-black">
{articles[0]?.createdByName}{" "}
</span>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
>
<g fill="none">
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path
fill="currentColor"
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
/>
</g>
</svg>{" "}
{new Date(articles[0]?.createdAt).toLocaleDateString(
"id-ID",
{
day: "2-digit",
month: "long",
year: "numeric",
}
)}
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
/>
</svg>
0
</p>
<p className="text-sm font-serif text-[#A0A0A0] mt-3 line-clamp-3">
{articles[0]?.description}
</p>
</Link>
</div>
{articles.slice(1).map((item, i) => (
<div key={i} className="flex items-start gap-3">
<img
src={item.thumbnailUrl}
alt={item.title}
className="w-24 h-16 object-cover"
/>
<p className="text-sm font-semibold">{item.title}</p>
<div key={i}>
<Link
className="flex items-start gap-3"
href={`/detail/${item?.id}`}
>
<img
src={item.thumbnailUrl}
alt={item.title}
className="w-24 h-16 object-cover"
/>
<p className="text-sm font-semibold">{item.title}</p>
</Link>
</div>
))}
</div>
@ -222,18 +246,20 @@ export default function Beranda() {
>
{articles.length > 0 ? (
articles.map((article) => (
<div
key={article.id}
className="flex-shrink-0 flex items-start gap-3 w-[188px]"
>
<img
src={article.thumbnailUrl || "/placeholder.jpg"}
alt={article.title}
className="w-14 h-14 object-cover rounded"
/>
<p className="text-xs font-medium w-[150px] line-clamp-3">
{article.title}
</p>
<div key={article.id}>
<Link
className="flex-shrink-0 flex items-start gap-3 w-[188px]"
href={`/detail/${article?.id}`}
>
<img
src={article.thumbnailUrl || "/placeholder.jpg"}
alt={article.title}
className="w-14 h-14 object-cover rounded"
/>
<p className="text-xs font-medium w-[150px] line-clamp-3">
{article.title}
</p>
</Link>
</div>
))
) : (
@ -252,57 +278,59 @@ export default function Beranda() {
{articles.length > 0 ? (
articles.map((article) => (
<div key={article.id}>
<img
src={article.thumbnailUrl || "/komjen-pol.jpg"}
alt={article.title}
className="w-full h-64 object-cover mb-4"
/>
<div className="p-8">
<p className="text-xs text-gray-500 uppercase mb-1">
{article.categories?.map((cat) => cat.title).join(", ") ||
"Beranda"}
</p>
<h1 className="text-xl font-bold mt-1">{article.title}</h1>
<p className="text-[10px] md:text-sm text-gray-500 mt-1 flex items-center gap-3">
BY{" "}
<span className="text-black font-semibold text-[10px] md:text-sm">
{article.createdByName}
</span>{" "}
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
/>
</svg>{" "}
{new Date(article.createdAt).toLocaleDateString("id-ID")}
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
/>
</svg>
0
</p>
<p className="text-sm text-[#666666] mt-2 line-clamp-3">
{article.description}
</p>
<button className="mt-4 text-xs w-6/12 md:w-3/12 border px-3 hover:bg-gray-100 transition py-2">
READ MORE
</button>
</div>
<Link href={`/detail/${article?.id}`}>
<img
src={article.thumbnailUrl || "/komjen-pol.jpg"}
alt={article.title}
className="w-full h-64 object-cover mb-4"
/>
<div className="p-8">
<p className="text-xs text-gray-500 uppercase mb-1">
{article.categories?.map((cat) => cat.title).join(", ") ||
"Beranda"}
</p>
<h1 className="text-xl font-bold mt-1">{article.title}</h1>
<p className="text-[10px] md:text-sm text-gray-500 mt-1 flex items-center gap-3">
BY{" "}
<span className="text-black font-semibold text-[10px] md:text-sm">
{article.createdByName}
</span>{" "}
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
/>
</svg>{" "}
{new Date(article.createdAt).toLocaleDateString("id-ID")}
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
/>
</svg>
0
</p>
<p className="text-sm text-[#666666] mt-2 line-clamp-3">
{article.description}
</p>
<button className="mt-4 text-xs w-6/12 md:w-3/12 border px-3 hover:bg-gray-100 transition py-2">
READ MORE
</button>
</div>
</Link>
</div>
))
) : (
@ -325,38 +353,43 @@ export default function Beranda() {
key={i}
className="bg-white shadow-md rounded-none overflow-hidden border"
>
<div className="relative">
<img
src={news?.thumbnailUrl || "/komjen-pol.jpg"}
alt={news.title}
className="w-full h-[223px] object-cover"
/>
<span className="absolute bottom-0 left-1/2 -translate-x-1/2 bg-black text-white text-[10px] px-2 py-[2px] rounded-none uppercase">
{news?.categories?.[0]?.title || "TANPA KATEGORI"}
</span>
</div>
<div className="p-4 text-center">
<h3 className="text-lg font-semibold text-gray-900 mb-3 leading-snug px-9">
{news.title}
</h3>
<div className="flex flex-row items-center justify-center text-gray-500 gap-1">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
>
<g fill="none">
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path
fill="currentColor"
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
/>
</g>
</svg>{" "}
<p className="text-xs text-gray-400">{news.createdAt}</p>
<Link
className="bg-white shadow-md rounded-none overflow-hidden border"
href={`/detail/${news?.id}`}
>
<div className="relative">
<img
src={news?.thumbnailUrl || "/komjen-pol.jpg"}
alt={news.title}
className="w-full h-[223px] object-cover"
/>
<span className="absolute bottom-0 left-1/2 -translate-x-1/2 bg-black text-white text-[10px] px-2 py-[2px] rounded-none uppercase">
{news?.categories?.[0]?.title || "TANPA KATEGORI"}
</span>
</div>
</div>
<div className="p-4 text-center">
<h3 className="text-lg font-semibold text-gray-900 mb-3 leading-snug px-9">
{news.title}
</h3>
<div className="flex flex-row items-center justify-center text-gray-500 gap-1">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
>
<g fill="none">
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path
fill="currentColor"
d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m0 2a1 1 0 0 1 .993.883L13 7v4.586l2.707 2.707a1 1 0 0 1-1.32 1.497l-.094-.083l-3-3a1 1 0 0 1-.284-.576L11 12V7a1 1 0 0 1 1-1"
/>
</g>
</svg>{" "}
<p className="text-xs text-gray-400">{news.createdAt}</p>
</div>
</div>
</Link>
</div>
))}
</div>
@ -366,15 +399,17 @@ export default function Beranda() {
</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
{articles.map((news, i) => (
<div key={i} className="flex gap-4">
<img
src={news.thumbnailUrl}
alt={news.title}
className="w-[100px] h-[70px] object-cover flex-shrink-0"
/>
<p className="text-sm font-semibold text-gray-900 hover:underline leading-snug">
{news.title}
</p>
<div key={i}>
<Link className="flex gap-4" href={`/detail/${news?.id}`}>
<img
src={news.thumbnailUrl}
alt={news.title}
className="w-[100px] h-[70px] object-cover flex-shrink-0"
/>
<p className="text-sm font-semibold text-gray-900 hover:underline leading-snug">
{news.title}
</p>
</Link>
</div>
))}
</div>
@ -396,27 +431,32 @@ export default function Beranda() {
</h2>
{articles.map((recentNews, i) => (
<div key={i} className="flex flex-col sm:flex-row gap-4 mt-4">
<img
src={recentNews.thumbnailUrl || "/komjen-pol.jpg"}
alt={recentNews.title}
className="w-full sm:w-[220px] h-[157px] object-cover"
/>
<div className="flex-1">
<h3 className="text-base font-bold">{recentNews.title}</h3>
<p className="text-xs text-gray-500 mt-1 flex flex-wrap items-center gap-2 mb-3">
BY{" "}
<span className="font-semibold text-black">
{recentNews.createdByName}
</span>
<Clock className="w-3 h-3" />
{recentNews.createdAt}
<MessageCircle className="w-3 h-3" />0
</p>
<p className="text-sm text-gray-600 line-clamp-3">
{recentNews.description}
</p>
</div>
<div key={i}>
<Link
className="flex flex-col sm:flex-row gap-4 mt-4"
href={`/detail/${recentNews?.id}`}
>
<img
src={recentNews.thumbnailUrl || "/komjen-pol.jpg"}
alt={recentNews.title}
className="w-full sm:w-[220px] h-[157px] object-cover"
/>
<div className="flex-1">
<h3 className="text-base font-bold">{recentNews.title}</h3>
<p className="text-xs text-gray-500 mt-1 flex flex-wrap items-center gap-2 mb-3">
BY{" "}
<span className="font-semibold text-black">
{recentNews.createdByName}
</span>
<Clock className="w-3 h-3" />
{recentNews.createdAt}
<MessageCircle className="w-3 h-3" />0
</p>
<p className="text-sm text-gray-600 line-clamp-3">
{recentNews.description}
</p>
</div>
</Link>
</div>
))}
@ -438,39 +478,43 @@ export default function Beranda() {
<aside className="w-full md:w-full lg:w-full xl:w-[312px] space-y-6 shrink-0">
{articles.map((news, i) => (
<Card
key={i}
className="rounded-none overflow-hidden bg-white shadow-sm p-0 gap-1"
>
<div className="relative">
{news?.thumbnailUrl && (
<img
src={news?.thumbnailUrl}
alt={news.title}
className="w-full h-[224px] object-cover"
/>
)}
{news?.categories?.[0]?.title && (
<span className="absolute top-2 left-2 bg-black text-white text-[10px] px-2 py-1 rounded-none uppercase tracking-wide">
{news?.categories?.[0]?.title}
</span>
)}
</div>
<div className="p-4">
<h3 className="text-base font-bold leading-snug">{news.title}</h3>
{news.createdByName && news.createdAt && (
<p className="text-xs text-gray-500 mt-2 font-medium mb-4">
BY <span className="text-black">{news.createdByName}</span> ·{" "}
{news.createdAt}
</p>
)}
{news.description && (
<p className="text-sm text-gray-600 mt-2 line-clamp-5">
{news.description}
</p>
)}
</div>
</Card>
<div className="border" key={i}>
<Link
className="rounded-none overflow-hidden bg-white shadow-sm p-0 gap-1"
href={`/detail/${news?.id}`}
>
<div className="relative">
{news?.thumbnailUrl && (
<img
src={news?.thumbnailUrl}
alt={news.title}
className="w-full h-[224px] object-cover"
/>
)}
{news?.categories?.[0]?.title && (
<span className="absolute top-2 left-2 bg-black text-white text-[10px] px-2 py-1 rounded-none uppercase tracking-wide">
{news?.categories?.[0]?.title}
</span>
)}
</div>
<div className="p-4">
<h3 className="text-base font-bold leading-snug">
{news.title}
</h3>
{news.createdByName && news.createdAt && (
<p className="text-xs text-gray-500 mt-2 font-medium mb-4">
BY <span className="text-black">{news.createdByName}</span>{" "}
· {news.createdAt}
</p>
)}
{news.description && (
<p className="text-sm text-gray-600 mt-2 line-clamp-5">
{news.description}
</p>
)}
</div>
</Link>
</div>
))}
<div className="relative w-auto max-w-full h-[300px] overflow-hidden flex items-center mx-auto border my-6 rounded">
<Image

BIN
public/profile.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB