qudoco-fe/components/landing-page/headers-news-services.tsx

270 lines
8.8 KiB
TypeScript
Raw Normal View History

2026-02-17 09:05:22 +00:00
"use client";
import Image from "next/image";
import { motion, AnimatePresence } from "framer-motion";
import { X, ChevronLeft, ChevronRight } from "lucide-react";
import { useEffect, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
const data = [
{
id: 1,
title:
"Bharatu Mardi Hadji Gugur Saat Bertugas, Diganjar Kenaikan Pangkat Luar Biasa",
image: "/image/bharatu.jpg",
},
{
id: 2,
title: "Pelayanan Publik Terus Ditingkatkan Demi Kenyamanan Masyarakat",
image: "/dummy/news-2.jpg",
},
{
id: 3,
title: "Inovasi Teknologi Jadi Fokus Pengembangan Layanan",
image: "/dummy/news-3.jpg",
},
];
const data1 = [
{
id: 1,
title: "Novita Hardini: Jangan Sampai Pariwisata Meminggirkan Warga Lokal",
image: "/image/novita2.png",
excerpt:
"PARLEMENTARIA, Mandalika Anggota Komisi VII DPR RI, Novita Hardini, menyoroti dampak sosial ekonomi dari pembangunan kawasan pariwisata...",
date: "7 November 2024",
category: "BERITA KOMISI 7",
tag: "DPR",
},
{
id: 2,
title: "Pelayanan Publik Terus Ditingkatkan Demi Kenyamanan Masyarakat",
image: "/dummy/news-2.jpg",
excerpt:
"Pelayanan publik terus ditingkatkan untuk menjawab kebutuhan masyarakat...",
date: "6 November 2024",
category: "BERITA",
tag: "NASIONAL",
},
{
id: 3,
title: "Inovasi Teknologi Jadi Fokus Pengembangan Layanan",
image: "/dummy/news-3.jpg",
excerpt:
"Transformasi digital menjadi fokus utama pengembangan layanan publik...",
date: "5 November 2024",
category: "TEKNOLOGI",
tag: "INOVASI",
},
];
export default function NewsAndServicesHeader() {
// 🔹 STATE DIPISAH
const [activeHeader, setActiveHeader] = useState(0);
const [activeModal, setActiveModal] = useState(0);
const [open, setOpen] = useState(false);
const [mounted, setMounted] = useState(false);
const searchParams = useSearchParams();
const router = useRouter();
useEffect(() => {
setMounted(true);
}, []);
// 🔹 AUTO OPEN MODAL
useEffect(() => {
if (!mounted) return;
const highlight = searchParams.get("highlight");
if (highlight === "1") {
setActiveModal(activeHeader); // clone posisi header
setOpen(true);
}
}, [mounted, searchParams, activeHeader]);
const closeModal = () => {
setOpen(false);
router.replace("/news-services");
};
// ===== HEADER NAV =====
const headerPrev = () =>
setActiveHeader((p) => (p === 0 ? data.length - 1 : p - 1));
const headerNext = () =>
setActiveHeader((p) => (p === data.length - 1 ? 0 : p + 1));
// ===== MODAL NAV =====
const modalPrev = () =>
setActiveModal((p) => (p === 0 ? data.length - 1 : p - 1));
const modalNext = () =>
setActiveModal((p) => (p === data.length - 1 ? 0 : p + 1));
if (!mounted) return null;
return (
<>
{/* ================= HEADER ================= */}
{/* ================= HEADER ================= */}
<section className="relative w-full bg-[#f8f8f8] py-24">
<div className="container mx-auto px-6 relative">
{/* ===== OUTER NAVIGATION ===== */}
<button
onClick={headerPrev}
className="hidden lg:flex absolute -left-6 top-1/2 -translate-y-1/2 w-12 h-12 rounded-full bg-white shadow-md items-center justify-center z-10"
>
<ChevronLeft />
</button>
<button
onClick={headerNext}
className="hidden lg:flex absolute -right-6 top-1/2 -translate-y-1/2 w-12 h-12 rounded-full bg-white shadow-md items-center justify-center z-10"
>
<ChevronRight />
</button>
<div className="flex flex-col lg:flex-row items-center gap-14">
{/* IMAGE */}
<div className="relative w-full lg:w-1/2">
<div className="relative h-[420px] rounded-3xl overflow-hidden">
<Image
src={data1[activeHeader].image}
alt={data1[activeHeader].title}
fill
className="object-cover"
priority
/>
</div>
{/* DOTS */}
<div className="flex justify-center gap-2 mt-4">
{data1.map((_, i) => (
<span
key={i}
className={`h-2.5 rounded-full transition-all ${
activeHeader === i
? "w-8 bg-[#b07c18]"
: "w-2.5 bg-gray-300"
}`}
/>
))}
</div>
</div>
{/* CONTENT */}
<div className="w-full lg:w-1/2">
<h1 className="text-4xl lg:text-5xl font-bold leading-tight mb-6">
{data1[activeHeader].title}
</h1>
<div className="flex flex-wrap items-center gap-3 text-sm text-gray-500 mb-5">
<span>{data1[activeHeader].date}</span>
<span></span>
<span>{data1[activeHeader].category}</span>
<span></span>
<span className="px-2 py-0.5 rounded bg-[#f2c94c] text-black text-xs font-semibold">
{data1[activeHeader].tag}
</span>
</div>
<p className="text-gray-700 leading-relaxed mb-8">
{data1[activeHeader].excerpt}
</p>
<button
onClick={() => setOpen(true)}
className="inline-flex items-center justify-center rounded-xl bg-[#b07c18] px-7 py-3 text-white font-medium hover:opacity-90 transition"
>
Baca Selengkapnya
</button>
</div>
</div>
{/* ===== SEARCH SECTION ===== */}
<div className="mt-20">
<div className="max-w-3xl mx-auto flex items-center bg-white rounded-2xl shadow-md overflow-hidden border">
<div className="px-4 text-gray-400">🔍</div>
<input
type="text"
placeholder="Cari berita, artikel, atau topik..."
className="flex-1 px-4 py-4 outline-none"
/>
<button className="bg-[#b07c18] text-white px-8 py-4 font-medium">
Cari
</button>
</div>
</div>
</div>
</section>
{/* ================= MODAL ================= */}
<AnimatePresence>
{open && (
<motion.div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<motion.div
className="relative w-[90%] max-w-5xl rounded-3xl overflow-hidden bg-[#9c8414]"
initial={{ scale: 0.95, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.95, opacity: 0 }}
>
<button
onClick={closeModal}
className="absolute top-4 right-4 z-10 w-10 h-10 rounded-full bg-black/40 text-white flex items-center justify-center"
>
<X />
</button>
<div className="relative h-[520px]">
<Image
src={data[activeModal].image}
alt={data[activeModal].title}
fill
className="object-cover"
priority
/>
<div className="absolute bottom-6 left-6 right-6 text-white">
<h2 className="text-xl md:text-2xl font-semibold">
{data[activeModal].title}
</h2>
</div>
<button
onClick={modalPrev}
className="absolute left-4 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-black/40 text-white"
>
<ChevronLeft />
</button>
<button
onClick={modalNext}
className="absolute right-4 top-1/2 -translate-y-1/2 w-10 h-10 rounded-full bg-black/40 text-white"
>
<ChevronRight />
</button>
</div>
<div className="flex justify-center gap-2 py-4">
{data.map((_, i) => (
<button
key={i}
onClick={() => setActiveModal(i)}
className={`w-2.5 h-2.5 rounded-full ${
activeModal === i ? "bg-white" : "bg-white/40"
}`}
/>
))}
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
</>
);
}