270 lines
8.8 KiB
TypeScript
270 lines
8.8 KiB
TypeScript
|
|
"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>
|
|||
|
|
</>
|
|||
|
|
);
|
|||
|
|
}
|