278 lines
11 KiB
TypeScript
278 lines
11 KiB
TypeScript
"use client";
|
|
|
|
import { Instagram } from "lucide-react";
|
|
import Image from "next/image";
|
|
import { useState, useEffect } from "react";
|
|
import {
|
|
getPublicClients,
|
|
PublicClient,
|
|
} from "@/service/client/public-clients";
|
|
import { Swiper, SwiperSlide } from "swiper/react";
|
|
import { Navigation, Autoplay } from "swiper/modules";
|
|
import "swiper/css";
|
|
import "swiper/css/navigation";
|
|
import LocalSwitcher from "../partials/header/locale-switcher";
|
|
import { useTranslations } from "next-intl";
|
|
|
|
// Custom styles for Swiper
|
|
const swiperStyles = `
|
|
.client-swiper .swiper-button-next,
|
|
.client-swiper .swiper-button-prev {
|
|
background: white;
|
|
border-radius: 50%;
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
width: 32px;
|
|
height: 32px;
|
|
margin-top: 0;
|
|
}
|
|
|
|
.client-swiper .swiper-button-next:after,
|
|
.client-swiper .swiper-button-prev:after {
|
|
font-size: 14px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.client-swiper .swiper-button-disabled {
|
|
opacity: 0.3;
|
|
}
|
|
|
|
.client-swiper.swiper-centered .swiper-button-next,
|
|
.client-swiper.swiper-centered .swiper-button-prev {
|
|
display: none;
|
|
}
|
|
|
|
.client-swiper.swiper-centered .swiper-wrapper {
|
|
justify-content: center;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.client-swiper .swiper-button-next,
|
|
.client-swiper .swiper-button-prev {
|
|
display: none;
|
|
}
|
|
}
|
|
`;
|
|
|
|
// const logos = [
|
|
// { src: "/mabes.png", href: "/in/public/publication/kl" },
|
|
// { src: "/saw.png", href: "/" },
|
|
// { src: "/mpr.png", href: "/" },
|
|
// { src: "/dpr.png", href: "/" },
|
|
// { src: "/ma.png", href: "/" },
|
|
// { src: "/badan.png", href: "/" },
|
|
// { src: "/kpk.png", href: "/" },
|
|
// { src: "/pln.png", href: "/" },
|
|
// ];
|
|
|
|
const logos = [
|
|
{ src: "/mabes.png", slug: "mabes" },
|
|
{ src: "/saw.png", slug: "kejaksaan-agung" },
|
|
{ src: "/mpr.png", slug: "mpr-ri" },
|
|
{ src: "/dpr.png", slug: "dpr-ri" },
|
|
{ src: "/ma.png", slug: "mahkamah-agung" },
|
|
{ src: "/badan.png", slug: "kemenkeu" },
|
|
{ src: "/kpk.png", slug: "kpk" },
|
|
{ src: "/pln.png", slug: "pupr" },
|
|
];
|
|
|
|
export default function Footer() {
|
|
const t = useTranslations("MediaUpdate");
|
|
const [clients, setClients] = useState<PublicClient[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
// Fetch public clients
|
|
useEffect(() => {
|
|
async function fetchClients() {
|
|
try {
|
|
const response = await getPublicClients();
|
|
if (response?.data?.success && response.data.data) {
|
|
setClients(response.data.data);
|
|
}
|
|
} catch (error) {
|
|
console.error("Error fetching public clients:", error);
|
|
setClients([]);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
fetchClients();
|
|
}, []);
|
|
|
|
return (
|
|
<footer className="border-t bg-white dark:bg-default-50 text-center">
|
|
<style jsx>{swiperStyles}</style>
|
|
<div className="max-w-[1350px] mx-auto">
|
|
<div className="py-6">
|
|
<h2 className="text-2xl font-semibold mb-4 px-4 md:px-0">
|
|
{t("publication")}
|
|
</h2>
|
|
<div className="px-4 md:px-12">
|
|
<Swiper
|
|
modules={[Navigation, Autoplay]}
|
|
spaceBetween={24}
|
|
slidesPerView="auto"
|
|
centeredSlides={clients.length <= 4}
|
|
navigation={{
|
|
nextEl: ".swiper-button-next",
|
|
prevEl: ".swiper-button-prev",
|
|
}}
|
|
autoplay={{
|
|
delay: 3000,
|
|
disableOnInteraction: false,
|
|
}}
|
|
loop={clients.length > 4}
|
|
className={`client-swiper ${
|
|
clients.length <= 4 ? "swiper-centered" : ""
|
|
}`}
|
|
>
|
|
{loading
|
|
? // Loading skeleton
|
|
Array.from({ length: 8 }).map((_, idx) => (
|
|
<SwiperSlide key={idx} className="!w-auto">
|
|
<div className="w-[80px] h-[80px] md:w-[100px] md:h-[100px] bg-gray-200 rounded animate-pulse" />
|
|
</SwiperSlide>
|
|
))
|
|
: clients.length > 0
|
|
? // Dynamic clients from API
|
|
clients.map((client, idx) => (
|
|
<SwiperSlide key={idx} className="!w-auto">
|
|
<a
|
|
href={`/in/tenant/${client.slug}`}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="group block"
|
|
>
|
|
{client.logoUrl ? (
|
|
<Image
|
|
src={client.logoUrl}
|
|
alt={client.name}
|
|
width={100}
|
|
height={100}
|
|
className="md:w-[100px] md:h-[100px] object-contain hover:opacity-80 transition"
|
|
/>
|
|
) : (
|
|
// Fallback when no logo - menggunakan placeholder image
|
|
<div className="w-[80px] h-[80px] md:w-[100px] md:h-[100px] rounded flex items-center justify-center hover:from-blue-200 hover:to-blue-300 transition-all duration-200">
|
|
<Image
|
|
src="/logo-netidhub.png"
|
|
alt={`${client.name} placeholder`}
|
|
width={100}
|
|
height={100}
|
|
className="md:w-[100px] md:h-[100px] object-contain opacity-70"
|
|
/>
|
|
</div>
|
|
)}
|
|
</a>
|
|
</SwiperSlide>
|
|
))
|
|
: // Fallback to static logos if API fails or no data
|
|
logos.map((logo, idx) => (
|
|
<SwiperSlide key={idx} className="!w-auto">
|
|
<a
|
|
href={`/in/tenant/${logo.slug}`}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="block"
|
|
>
|
|
<Image
|
|
src={logo.src}
|
|
alt={`logo-${idx}`}
|
|
width={80}
|
|
height={80}
|
|
className="md:w-[100px] md:h-[100px] object-contain hover:opacity-80 transition"
|
|
/>
|
|
</a>
|
|
</SwiperSlide>
|
|
))}
|
|
</Swiper>
|
|
|
|
{/* Navigation Buttons */}
|
|
{/* <div className="swiper-button-prev !text-gray-600 !w-8 !h-8 !mt-0 !top-1/2 !left-0 !-translate-y-1/2"></div> */}
|
|
{/* <div className="swiper-button-next !text-gray-600 !w-8 !h-8 !mt-0 !top-1/2 !right-0 !-translate-y-1/2"></div> */}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="border-t my-6 w-full max-w-6xl mx-auto" />
|
|
|
|
<div className="flex flex-col md:flex-row items-center justify-between gap-4 px-4 pb-6 max-w-6xl mx-auto text-sm text-gray-600 dark:text-white">
|
|
<div className="flex items-center gap-2">
|
|
<span>ver 1.0.0 @2025 - {t("netidhub")}</span>
|
|
<Image
|
|
src="/qudo.png"
|
|
alt="qudoco"
|
|
width={80}
|
|
height={80}
|
|
className="object-contain"
|
|
/>
|
|
</div>
|
|
|
|
{/* Social Media */}
|
|
<div className="flex gap-3 text-gray-800 dark:text-white">
|
|
<Instagram className="hover:text-black" />
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="24"
|
|
height="24"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
fill="currentColor"
|
|
d="M14 13.5h2.5l1-4H14v-2c0-1.03 0-2 2-2h1.5V2.14c-.326-.043-1.557-.14-2.857-.14C11.928 2 10 3.657 10 6.7v2.8H7v4h3V22h4z"
|
|
/>
|
|
</svg>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="24"
|
|
height="24"
|
|
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="M4.594 4.984a1 1 0 0 1 .941.429C7.011 7.572 8.783 8.47 10.75 8.674c.096-.841.323-1.672.75-2.404c.626-1.074 1.644-1.864 3.098-2.156c2.01-.404 3.54.324 4.427 1.215l1.792-.335a1 1 0 0 1 1.053 1.478l-1.72 3.022c.157 4.361-1.055 7.405-3.639 9.502c-1.37 1.112-3.332 1.743-5.485 1.938c-2.17.196-4.623-.041-7.061-.753a1 1 0 0 1 .007-1.922c1.226-.349 2.16-.65 3.003-1.177c-1.199-.636-2.082-1.468-2.707-2.416c-.868-1.318-1.19-2.788-1.254-4.113S3.141 8 3.343 7.115c.115-.505.249-1.011.434-1.495a1 1 0 0 1 .818-.636Z"
|
|
/>
|
|
</g>
|
|
</svg>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="24"
|
|
height="24"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
fill="currentColor"
|
|
// fill-rule="evenodd"
|
|
d="M9.935 14.628v-5.62l5.403 2.82zM21.8 8.035s-.195-1.379-.795-1.986c-.76-.796-1.613-.8-2.004-.847C16.203 5 12.004 5 12.004 5h-.008s-4.198 0-6.997.202c-.391.047-1.243.05-2.004.847c-.6.607-.795 1.986-.795 1.986S2 9.653 2 11.272v1.517c0 1.618.2 3.237.2 3.237s.195 1.378.795 1.985c.76.797 1.76.771 2.205.855c1.6.153 6.8.2 6.8.2s4.203-.006 7.001-.208c.391-.047 1.244-.05 2.004-.847c.6-.607.795-1.985.795-1.985s.2-1.619.2-3.237v-1.517c0-1.619-.2-3.237-.2-3.237"
|
|
/>
|
|
</svg>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="24"
|
|
height="24"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<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="M14 2a2 2 0 0 1 2 2a3.004 3.004 0 0 0 2.398 2.94a2 2 0 0 1-.796 3.92A7 7 0 0 1 16 10.325V16a6 6 0 1 1-7.499-5.81a2 2 0 0 1 .998 3.873A2.002 2.002 0 0 0 10 18a2 2 0 0 0 2-2V4a2 2 0 0 1 2-2"
|
|
/>
|
|
</g>
|
|
</svg>
|
|
</div>
|
|
|
|
{/* button language */}
|
|
<div className={`relative text-left border rounded-lg`}>
|
|
<LocalSwitcher />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
);
|
|
}
|