From ad22254cc81ab4019c59281f97ec4ea4f87bbc2f Mon Sep 17 00:00:00 2001 From: VuHoangThien Date: Fri, 15 May 2026 16:35:28 +0700 Subject: [PATCH] feat: add partners carousel, update sponsor section, add Nasalization font --- app/components/home/HomePageClient.tsx | 2 + app/components/home/PartnersCarousel.tsx | 103 ++++++++++++++++++ app/components/sponsor/SponsorContact.tsx | 34 +++--- app/components/sponsor/SponsorHero.tsx | 15 ++- app/components/sponsor/SponsorItemBased.tsx | 27 ++++- app/data/sponsor.json | 34 ++++-- app/data/sponsor.vi.json | 34 ++++-- app/globals.css | 32 +++++- public/assets/img/carousel/Alibaba-Logo.png | Bin 0 -> 94369 bytes .../assets/img/carousel/Equinix_logo.svg.png | Bin 0 -> 97253 bytes .../img/carousel/Huawei_Standard_logo.svg.png | Bin 0 -> 333302 bytes public/assets/img/carousel/Logonetflix.png | Bin 0 -> 32265 bytes public/assets/img/carousel/Maxis-logo.png | Bin 0 -> 11835 bytes public/assets/img/carousel/Microsoft-Logo.png | Bin 0 -> 20089 bytes .../assets/img/carousel/Nvidia_logo.svg.png | Bin 0 -> 196212 bytes .../assets/img/carousel/Singtel_logo.svg.png | Bin 0 -> 172799 bytes .../img/carousel/XL_Axiata-Logo.wine.png | Bin 0 -> 34647 bytes public/assets/img/carousel/airtrunk.png | Bin 0 -> 7988 bytes public/assets/img/carousel/celcomdigi.png | Bin 0 -> 35343 bytes public/assets/img/carousel/grab.png | Bin 0 -> 217041 bytes .../assets/img/carousel/logo_transparent.png | Bin 0 -> 25786 bytes public/assets/img/carousel/nida.png | Bin 0 -> 59554 bytes public/assets/img/carousel/tencent.png | Bin 0 -> 116112 bytes public/assets/img/carousel/vnnic.png | Bin 0 -> 135526 bytes public/assets/webfonts/Nasalization Rg.otf | Bin 0 -> 67384 bytes 25 files changed, 239 insertions(+), 42 deletions(-) create mode 100644 app/components/home/PartnersCarousel.tsx create mode 100644 public/assets/img/carousel/Alibaba-Logo.png create mode 100644 public/assets/img/carousel/Equinix_logo.svg.png create mode 100644 public/assets/img/carousel/Huawei_Standard_logo.svg.png create mode 100644 public/assets/img/carousel/Logonetflix.png create mode 100644 public/assets/img/carousel/Maxis-logo.png create mode 100644 public/assets/img/carousel/Microsoft-Logo.png create mode 100644 public/assets/img/carousel/Nvidia_logo.svg.png create mode 100644 public/assets/img/carousel/Singtel_logo.svg.png create mode 100644 public/assets/img/carousel/XL_Axiata-Logo.wine.png create mode 100644 public/assets/img/carousel/airtrunk.png create mode 100644 public/assets/img/carousel/celcomdigi.png create mode 100644 public/assets/img/carousel/grab.png create mode 100644 public/assets/img/carousel/logo_transparent.png create mode 100644 public/assets/img/carousel/nida.png create mode 100644 public/assets/img/carousel/tencent.png create mode 100644 public/assets/img/carousel/vnnic.png create mode 100644 public/assets/webfonts/Nasalization Rg.otf diff --git a/app/components/home/HomePageClient.tsx b/app/components/home/HomePageClient.tsx index 8cd89e1..ef236b2 100644 --- a/app/components/home/HomePageClient.tsx +++ b/app/components/home/HomePageClient.tsx @@ -5,6 +5,7 @@ import HeroSection from "@/app/components/home/HeroSection"; import VisionSection from "@/app/components/home/VisionSection"; import StatsSection from "@/app/components/home/StatsSection"; import AgendaSection from "@/app/components/home/AgendaSection"; +import PartnersCarousel from "@/app/components/home/PartnersCarousel"; export default function HomePageClient() { const { home } = useTranslation(); @@ -15,6 +16,7 @@ export default function HomePageClient() { + ); } diff --git a/app/components/home/PartnersCarousel.tsx b/app/components/home/PartnersCarousel.tsx new file mode 100644 index 0000000..2092c72 --- /dev/null +++ b/app/components/home/PartnersCarousel.tsx @@ -0,0 +1,103 @@ +"use client"; + +import { useEffect, useState } from "react"; + +// Tên file chính xác trong public/assets/img/carousel/ +const ROW_1 = [ + { name: "NVIDIA", file: "Nvidia_logo.svg.png" }, + { name: "Maxis", file: "Maxis-logo.png" }, + { name: "Singtel", file: "Singtel_logo.svg.png" }, + { name: "NIDA", file: "nida.png" }, + { name: "VNNIC", file: "vnnic.png" }, + { name: "Netflix", file: "Logonetflix.png" }, + { name: "Microsoft",file: "Microsoft-Logo.png" }, + { name: "Alibaba", file: "Alibaba-Logo.png" }, +]; + +const ROW_2 = [ + { name: "Tencent", file: "tencent.png" }, + { name: "AirTrunk", file: "airtrunk.png" }, + { name: "Celcomdigi",file: "celcomdigi.png" }, + { name: "Grab", file: "grab.png" }, + { name: "Logo 1", file: "logo_transparent.png" }, + { name: "Logo 2", file: "Equinix_logo.svg.png" }, + { name: "Logo 3", file: "XL_Axiata-Logo.wine.png" }, + { name: "Logo 4", file: "Huawei_Standard_logo.svg.png" }, +]; + +function CarouselRow({ + items, + base, + reverse = false, +}: { + items: { name: string; file: string }[]; + base: string; + reverse?: boolean; +}) { + // Lặp 3 lần để đảm bảo không bao giờ thấy khoảng trống + const tripled = [...items, ...items, ...items]; + // Mỗi item: w=150px, gap=20px → 1 set = items.length * 170 - 20 + const setWidth = items.length * 150 + (items.length - 1) * 20; + + return ( +
+
+ {tripled.map((item, i) => ( +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {item.name} +
+ ))} +
+
+ ); +} + +export default function PartnersCarousel() { + const [base, setBase] = useState(""); + + useEffect(() => { + const match = window.location.pathname.match(/^(\/ipv6)/); + setBase(match ? match[1] : ""); + }, []); + + return ( +
+
+

+ Partners & Sponsors +

+

+ Trusted by Industry Leaders +

+
+ +
+ + +
+
+ ); +} diff --git a/app/components/sponsor/SponsorContact.tsx b/app/components/sponsor/SponsorContact.tsx index be62118..8ec93a9 100644 --- a/app/components/sponsor/SponsorContact.tsx +++ b/app/components/sponsor/SponsorContact.tsx @@ -19,28 +19,28 @@ export default function SponsorContact({ data }: { data: SponsorContactData }) {
{/* Left Content */} -
+
-

+

{data.title}

-

+

{data.description}

-
+
{/* Phone */}
-
-
- call +
+
+ call
-
-

+

+

{data.phone.label}

-

+

{data.phone.value}

@@ -49,15 +49,15 @@ export default function SponsorContact({ data }: { data: SponsorContactData }) { {/* Email */}
-
-
- mail +
+
+ mail
-
-

+

+

{data.email.label}

-

+

{data.email.value}

@@ -67,7 +67,7 @@ export default function SponsorContact({ data }: { data: SponsorContactData }) {