forked from UKSOURCE/ipv6
feat: memberships page
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import type { Metadata } from "next";
|
||||
import MembersPageClient from "@/app/components/members/MembersPageClient";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Our Members | IPv6 Enhanced 2026",
|
||||
description:
|
||||
"The collective force of leading global institutions driving IPv6 adoption across ASEAN's digital ecosystems.",
|
||||
};
|
||||
|
||||
export default function MembersPage() {
|
||||
return <MembersPageClient />;
|
||||
}
|
||||
@@ -18,7 +18,7 @@ type EventItem = {
|
||||
|
||||
export default function GalleryPageClient() {
|
||||
const { gallery, lang } = useTranslation();
|
||||
|
||||
|
||||
// Active Event Index (0: latest event, 7: oldest event)
|
||||
const [activeEventIndex, setActiveEventIndex] = useState(0);
|
||||
|
||||
@@ -128,21 +128,21 @@ export default function GalleryPageClient() {
|
||||
|
||||
{/* Gallery Section */}
|
||||
<section className="py-12 lg:py-20 px-[var(--spacing-gutter)] max-w-hd mx-auto">
|
||||
|
||||
|
||||
{/* Step Timeline Navigation */}
|
||||
<div className="mb-10 max-w-4xl mx-auto px-4">
|
||||
<div className="relative flex justify-between items-center">
|
||||
{/* Timeline track behind steps */}
|
||||
<div className="absolute left-0 right-0 h-[2px] bg-white/10 -z-10" />
|
||||
<div
|
||||
<div
|
||||
className="absolute left-0 h-[2px] bg-primary transition-all duration-500 -z-10"
|
||||
style={{ width: `${(activeEventIndex / (gallery.events.length - 1)) * 100}%` }}
|
||||
/>
|
||||
|
||||
|
||||
{gallery.events.map((event: EventItem, idx: number) => {
|
||||
const isActive = idx === activeEventIndex;
|
||||
const isPassed = idx < activeEventIndex;
|
||||
|
||||
|
||||
return (
|
||||
<button
|
||||
key={event.id}
|
||||
@@ -152,13 +152,13 @@ export default function GalleryPageClient() {
|
||||
title={event.title}
|
||||
>
|
||||
{/* Step circle */}
|
||||
<div
|
||||
<div
|
||||
className={[
|
||||
"w-8 h-8 rounded-full flex items-center justify-center font-[var(--font-label-caps)] text-xs font-bold transition-all duration-300 border-2 z-10",
|
||||
isActive
|
||||
? "bg-background border-primary text-primary status-led shadow-[0_0_12px_rgba(197,160,89,0.6)] scale-110"
|
||||
: isPassed
|
||||
? "bg-primary border-primary text-on-primary"
|
||||
isActive
|
||||
? "bg-background border-primary text-primary status-led shadow-[0_0_12px_rgba(197,160,89,0.6)] scale-110"
|
||||
: isPassed
|
||||
? "bg-primary border-primary text-on-primary"
|
||||
: "bg-surface-container-high border-white/10 text-on-surface-variant/40 hover:border-white/30 hover:text-on-surface"
|
||||
].join(" ")}
|
||||
>
|
||||
@@ -173,7 +173,7 @@ export default function GalleryPageClient() {
|
||||
{/* Active Event Grid Container */}
|
||||
{activeEvent && (
|
||||
<div className="glass-panel p-6 sm:p-10 lg:p-16 rounded-[2rem] lg:rounded-[3rem] border border-primary/20 hover:border-primary/30 shadow-2xl transition-all duration-300">
|
||||
|
||||
|
||||
{/* Top Navigation Control Header */}
|
||||
<div className="flex justify-between items-center mb-10 border-b border-white/5 pb-6">
|
||||
<button
|
||||
@@ -187,8 +187,8 @@ export default function GalleryPageClient() {
|
||||
</button>
|
||||
|
||||
<span className="font-[var(--font-label-caps)] text-xs sm:text-sm text-primary tracking-widest bg-primary/5 border border-primary/20 px-4 py-2 rounded-xl">
|
||||
{lang === "vi"
|
||||
? `SỰ KIỆN ${activeEventIndex + 1} / ${gallery.events.length}`
|
||||
{lang === "vi"
|
||||
? `SỰ KIỆN ${activeEventIndex + 1} / ${gallery.events.length}`
|
||||
: `EVENT ${activeEventIndex + 1} OF ${gallery.events.length}`
|
||||
}
|
||||
</span>
|
||||
@@ -209,13 +209,13 @@ export default function GalleryPageClient() {
|
||||
<h2 className="text-2xl sm:text-3xl lg:text-4xl font-[var(--font-display-lg)] text-primary mb-4 leading-tight">
|
||||
{activeEvent.title}
|
||||
</h2>
|
||||
|
||||
|
||||
<div className="flex flex-wrap items-center gap-4 text-xs uppercase tracking-wider text-on-surface-variant/50 font-[var(--font-label-caps)] mb-6">
|
||||
<div className="flex items-center gap-1.5 bg-surface-container-high px-3.5 py-2 rounded-xl border border-white/5">
|
||||
<span className="material-symbols-outlined text-base text-primary">calendar_today</span>
|
||||
<span>{activeEvent.date}</span>
|
||||
</div>
|
||||
|
||||
|
||||
{activeEvent.googleDriveUrl && activeEvent.googleDriveUrl.trim() !== "" && (
|
||||
<a
|
||||
href={activeEvent.googleDriveUrl}
|
||||
@@ -235,8 +235,8 @@ export default function GalleryPageClient() {
|
||||
<div className="flex flex-col items-center justify-center py-20 px-6 border border-white/5 bg-white/[0.01] rounded-2xl">
|
||||
<span className="material-symbols-outlined text-5xl text-primary/45 mb-4">image</span>
|
||||
<p className="text-on-surface-variant/60 font-sans text-sm sm:text-base text-center max-w-md">
|
||||
{lang === "vi"
|
||||
? "Hình ảnh nổi bật cho sự kiện này hiện đang được cập nhật."
|
||||
{lang === "vi"
|
||||
? "Hình ảnh nổi bật cho sự kiện này hiện đang được cập nhật."
|
||||
: "Highlight images for this event are currently being updated."
|
||||
}
|
||||
</p>
|
||||
@@ -244,7 +244,7 @@ export default function GalleryPageClient() {
|
||||
) : (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
|
||||
{activeEvent.images.map((imgUrl, i) => (
|
||||
<div
|
||||
<div
|
||||
key={i}
|
||||
className={[
|
||||
getMosaicClasses(i, activeEvent.images.length),
|
||||
@@ -253,9 +253,9 @@ export default function GalleryPageClient() {
|
||||
onClick={() => openLightbox(i)}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={getImgSrc(imgUrl)}
|
||||
alt={`${activeEvent.title} Highlight ${i + 1}`}
|
||||
<img
|
||||
src={getImgSrc(imgUrl)}
|
||||
alt={`${activeEvent.title} Highlight ${i + 1}`}
|
||||
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-105"
|
||||
loading="lazy"
|
||||
/>
|
||||
@@ -278,13 +278,13 @@ export default function GalleryPageClient() {
|
||||
|
||||
{/* Lightbox Overlay */}
|
||||
{lightboxImageIndex !== null && activeEvent && activeImage && (
|
||||
<div
|
||||
<div
|
||||
className="fixed inset-0 z-[100] flex flex-col justify-center items-center bg-black/95 backdrop-blur-md transition-opacity duration-300"
|
||||
onClick={closeLightbox}
|
||||
>
|
||||
{/* Close button */}
|
||||
<button
|
||||
type="button"
|
||||
<button
|
||||
type="button"
|
||||
className="absolute top-6 right-6 text-white/70 hover:text-white transition-colors p-2 z-[110] focus:outline-none"
|
||||
onClick={closeLightbox}
|
||||
aria-label="Close Lightbox"
|
||||
@@ -293,12 +293,12 @@ export default function GalleryPageClient() {
|
||||
</button>
|
||||
|
||||
{/* Lightbox content container */}
|
||||
<div
|
||||
<div
|
||||
className="relative flex items-center justify-between w-full max-w-6xl px-4 md:px-12 h-[60vh] sm:h-[70vh] md:h-[80vh]"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{/* Prev arrow */}
|
||||
<button
|
||||
<button
|
||||
type="button"
|
||||
className="w-12 h-12 md:w-16 md:h-16 rounded-full bg-white/5 hover:bg-white/10 border border-white/10 text-white flex items-center justify-center transition-colors mr-2 active:scale-95 focus:outline-none"
|
||||
onClick={() => setLightboxImageIndex((prev) => (prev! - 1 + activeEvent.images.length) % activeEvent.images.length)}
|
||||
@@ -310,15 +310,15 @@ export default function GalleryPageClient() {
|
||||
{/* Active Image */}
|
||||
<div className="flex-1 flex items-center justify-center h-full relative overflow-hidden select-none px-4">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={getImgSrc(activeImage)}
|
||||
<img
|
||||
src={getImgSrc(activeImage)}
|
||||
alt={`${activeEvent.title} Full Highlight`}
|
||||
className="max-w-full max-h-full object-contain rounded-lg border border-white/5 shadow-2xl transition-all duration-300 animate-in fade-in zoom-in-95 duration-200"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Next arrow */}
|
||||
<button
|
||||
<button
|
||||
type="button"
|
||||
className="w-12 h-12 md:w-16 md:h-16 rounded-full bg-white/5 hover:bg-white/10 border border-white/10 text-white flex items-center justify-center transition-colors ml-2 active:scale-95 focus:outline-none"
|
||||
onClick={() => setLightboxImageIndex((prev) => (prev! + 1) % activeEvent.images.length)}
|
||||
@@ -329,7 +329,7 @@ export default function GalleryPageClient() {
|
||||
</div>
|
||||
|
||||
{/* Info bar below image */}
|
||||
<div
|
||||
<div
|
||||
className="text-center mt-6 px-6 max-w-2xl select-none"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
@@ -337,7 +337,7 @@ export default function GalleryPageClient() {
|
||||
{activeEvent.title}
|
||||
</h3>
|
||||
<p className="text-on-surface-variant/60 text-xs sm:text-sm uppercase tracking-wider font-[var(--font-label-caps)]">
|
||||
{lang === "vi"
|
||||
{lang === "vi"
|
||||
? `Hình ảnh ${lightboxImageIndex + 1} trên ${activeEvent.images.length}`
|
||||
: `Image ${lightboxImageIndex + 1} of ${activeEvent.images.length}`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { useTranslation } from "@/app/hooks/useTranslation";
|
||||
import ReadyToJoin from "@/app/components/gallery/ReadyToJoin";
|
||||
|
||||
const BASE = process.env.NEXT_PUBLIC_BASE_PATH || "";
|
||||
|
||||
type MemberItem = {
|
||||
name: string;
|
||||
logo: string;
|
||||
subtitle: string;
|
||||
};
|
||||
|
||||
type Category = {
|
||||
title: string;
|
||||
items: MemberItem[];
|
||||
};
|
||||
|
||||
type IndividualMember = {
|
||||
name: string;
|
||||
title: string;
|
||||
};
|
||||
|
||||
/* Stateful Logo Card component to dynamically adjust padding & scaling based on image aspect ratio */
|
||||
const LogoCard = ({ item }: { item: MemberItem }) => {
|
||||
const [isSquareOrTall, setIsSquareOrTall] = useState(false);
|
||||
const imgRef = useRef<HTMLImageElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const img = imgRef.current;
|
||||
if (!img) return;
|
||||
|
||||
// Reset aspect ratio state when logo path changes
|
||||
setIsSquareOrTall(false);
|
||||
|
||||
const handleLoad = () => {
|
||||
const { naturalWidth, naturalHeight } = img;
|
||||
if (naturalHeight && naturalWidth) {
|
||||
// If height-to-width ratio is close to square or taller (>= 0.75)
|
||||
setIsSquareOrTall(naturalHeight / naturalWidth >= 0.75);
|
||||
}
|
||||
};
|
||||
|
||||
if (img.complete) {
|
||||
handleLoad();
|
||||
} else {
|
||||
img.addEventListener("load", handleLoad);
|
||||
return () => img.removeEventListener("load", handleLoad);
|
||||
}
|
||||
}, [item.logo]);
|
||||
|
||||
const hasLogo = item.logo && item.logo.trim() !== "";
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center group w-full">
|
||||
{/* Card containing the logo image or fallback placeholder */}
|
||||
<div
|
||||
className={`w-full h-28 flex items-center justify-center bg-white/95 rounded-2xl border border-white/5 group-hover:scale-[1.03] transition-all duration-300 shadow-md ${
|
||||
hasLogo && isSquareOrTall ? "p-2.5" : "p-4.5"
|
||||
}`}
|
||||
>
|
||||
{hasLogo ? (
|
||||
/* Logo Container with background fill for high contrast */
|
||||
<div className="flex items-center justify-center w-full h-full">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
ref={imgRef}
|
||||
src={`${BASE}${item.logo}`}
|
||||
alt={item.name}
|
||||
className={`w-auto h-auto object-contain filter group-hover:scale-105 transition-all duration-300 ${
|
||||
isSquareOrTall
|
||||
? "max-h-[82%] max-w-[82%]"
|
||||
: "max-h-[55%] max-w-[85%]"
|
||||
}`}
|
||||
loading="lazy"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
/* Fallback avatar badge */
|
||||
<div className="w-12 h-12 rounded-full bg-primary/10 border border-primary/20 flex items-center justify-center">
|
||||
<span className="font-[var(--font-display-lg)] text-sm text-primary font-bold">
|
||||
{item.name.slice(0, 2).toUpperCase()}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Text details (outside on the dark background, larger text) */}
|
||||
<div className="mt-3.5 flex flex-col items-center text-center w-full">
|
||||
<span className="font-[var(--font-display-lg)] text-sm lg:text-base text-on-surface group-hover:text-primary transition-colors duration-300 tracking-wider uppercase leading-tight px-1">
|
||||
{item.name}
|
||||
</span>
|
||||
<span className="text-[10px] lg:text-[11px] text-on-surface-variant/50 leading-tight mt-1.5 max-w-full px-2 truncate block uppercase tracking-widest font-[var(--font-body-base)] select-none">
|
||||
{item.subtitle}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function MembersPageClient() {
|
||||
const { members } = useTranslation();
|
||||
|
||||
const categories = members.organizationalMembers.categories;
|
||||
|
||||
return (
|
||||
<main className="pt-16 lg:pt-20 min-h-screen bg-background text-on-surface">
|
||||
{/* Hero Header Section */}
|
||||
<section className="hero-glow py-20 lg:py-32 px-[var(--spacing-gutter)] text-center border-b border-white/5">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<span className="font-[var(--font-label-caps)] text-xs lg:text-sm text-primary block mb-4 lg:mb-6 tracking-[0.25em] uppercase animate-pulse">
|
||||
{members.hero.eyebrow}
|
||||
</span>
|
||||
<h1 className="font-[var(--font-display-lg)] text-on-surface text-[clamp(2.5rem,6vw+1rem,5.5rem)] leading-none tracking-tight">
|
||||
{members.hero.title}
|
||||
</h1>
|
||||
<p className="font-[var(--font-body-base)] text-on-surface-variant text-base lg:text-[20px] max-w-3xl mx-auto opacity-70 leading-relaxed mt-6">
|
||||
{members.hero.description}
|
||||
</p>
|
||||
|
||||
{/* Jump Anchors Navigation Menu */}
|
||||
<div className="flex flex-wrap justify-center gap-4 sm:gap-6 mt-10">
|
||||
<a
|
||||
href="#org-members"
|
||||
className="inline-flex items-center gap-2.5 px-6 py-3 rounded-full border border-primary/25 bg-primary/5 text-primary text-xs lg:text-sm font-bold uppercase tracking-widest hover:bg-primary/10 hover:border-primary/50 transition-all duration-300"
|
||||
>
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-primary" />
|
||||
{members.organizationalMembers.title}
|
||||
</a>
|
||||
<a
|
||||
href="#contrib-members"
|
||||
className="inline-flex items-center gap-2.5 px-6 py-3 rounded-full border border-primary/25 bg-primary/5 text-primary text-xs lg:text-sm font-bold uppercase tracking-widest hover:bg-primary/10 hover:border-primary/50 transition-all duration-300"
|
||||
>
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-primary" />
|
||||
{members.contributingMembers.title}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Organizational Members Section */}
|
||||
<section className="py-16 lg:py-24 px-[var(--spacing-gutter)] max-w-hd mx-auto" id="org-members">
|
||||
<div className="mb-12 lg:mb-20 text-center max-w-3xl mx-auto">
|
||||
<h2 className="font-[var(--font-display-lg)] text-on-surface uppercase tracking-tight text-[clamp(1.75rem,3vw+1rem,3.5rem)] mb-4">
|
||||
{members.organizationalMembers.title}
|
||||
</h2>
|
||||
<p className="text-on-surface-variant/60 text-base lg:text-lg">
|
||||
{members.organizationalMembers.description}
|
||||
</p>
|
||||
<div className="h-[2px] w-24 bg-primary/50 mx-auto rounded-full mt-6" />
|
||||
</div>
|
||||
|
||||
{/* Subcategories */}
|
||||
<div className="space-y-20 lg:space-y-28">
|
||||
{Object.entries(categories).map(([key, cat]) => {
|
||||
const category = cat as Category;
|
||||
return (
|
||||
<div key={key} className="space-y-8 lg:space-y-12">
|
||||
{/* Subcategory title */}
|
||||
<h3 className="font-[var(--font-display-lg)] text-base lg:text-lg text-primary uppercase tracking-widest border-l-4 border-primary pl-4 leading-none">
|
||||
{category.title}
|
||||
</h3>
|
||||
{/* Logos Grid */}
|
||||
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-x-6 gap-y-12">
|
||||
{category.items.map((item) => (
|
||||
<LogoCard key={item.name} item={item} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contributing Members Section */}
|
||||
<section className="py-16 lg:py-24 px-[var(--spacing-gutter)] max-w-hd mx-auto border-t border-white/5 bg-white/[0.01]" id="contrib-members">
|
||||
<div className="mb-12 lg:mb-20 text-center max-w-3xl mx-auto">
|
||||
<h2 className="font-[var(--font-display-lg)] text-on-surface uppercase tracking-tight text-[clamp(1.75rem,3vw+1rem,3.5rem)] mb-4">
|
||||
{members.contributingMembers.title}
|
||||
</h2>
|
||||
<p className="text-on-surface-variant/60 text-base lg:text-lg">
|
||||
{members.contributingMembers.description}
|
||||
</p>
|
||||
<div className="h-[2px] w-24 bg-primary/50 mx-auto rounded-full mt-6" />
|
||||
</div>
|
||||
|
||||
{/* Individual Contributors Grid */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 max-w-6xl mx-auto">
|
||||
{members.contributingMembers.items.map((item: IndividualMember) => (
|
||||
<div
|
||||
key={item.name}
|
||||
className="glass-panel p-5 rounded-2xl flex items-center gap-4 hover:border-primary/50 hover:scale-[1.02] transition-all duration-300 shadow-md group"
|
||||
>
|
||||
<div className="w-12 h-12 rounded-full bg-primary/10 border border-primary/20 flex items-center justify-center shrink-0 group-hover:bg-primary/20 transition-colors duration-300">
|
||||
<span className="material-symbols-outlined text-primary text-2xl" aria-hidden="true">
|
||||
person
|
||||
</span>
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<h4 className="font-[var(--font-display-lg)] text-sm lg:text-base text-on-surface leading-tight truncate mb-1 group-hover:text-primary transition-colors duration-300">
|
||||
{item.name}
|
||||
</h4>
|
||||
<p className="text-xs text-on-surface-variant/70 leading-normal truncate">
|
||||
{item.title}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Ready To Join CTA Section (Reusing Visual Gallery CTA design) */}
|
||||
<ReadyToJoin data={members.join} />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"hero": {
|
||||
"eyebrow": "OUR COUNCIL",
|
||||
"title": "Our Members",
|
||||
"description": "The collective force of leading global institutions driving IPv6 adoption across ASEAN's digital ecosystems. These are the members of the APAC Council."
|
||||
},
|
||||
"organizationalMembers": {
|
||||
"title": "Organizational Members",
|
||||
"description": "Leading institutions and authorities committed to deploying next-generation internet infrastructure.",
|
||||
"categories": {
|
||||
"government": {
|
||||
"title": "Government & Forums",
|
||||
"items": [
|
||||
{ "name": "APNIC", "logo": "/assets/img/gov & forums/APNIC.png", "subtitle": "Asia-Pacific Network Information Centre" },
|
||||
{ "name": "VNNIC", "logo": "/assets/img/gov & forums/VNNIC.png", "subtitle": "Vietnam Internet Network Information Center" },
|
||||
{ "name": "IPv6 Forum", "logo": "/assets/img/gov & forums/IPv6 Forum.png", "subtitle": "Global IPv6 Forum" },
|
||||
{ "name": "APAN", "logo": "/assets/img/gov & forums/APAN.png", "subtitle": "Asia Pacific Advanced Network" },
|
||||
{ "name": "Bharat IPv6 Forum", "logo": "/assets/img/gov & forums/Bharat IPv6 Forum.jpg", "subtitle": "India IPv6 Forum" },
|
||||
{ "name": "IDNIC", "logo": "/assets/img/gov & forums/IDNIC.png", "subtitle": "Indonesian Network Information Center" },
|
||||
{ "name": "ISOC Kazakhstan", "logo": "/assets/img/gov & forums/ISOC Kazakhstan.png", "subtitle": "Internet Society Kazakhstan Chapter" },
|
||||
{ "name": "ITU-APT", "logo": "/assets/img/gov & forums/ITU-APT.jpg", "subtitle": "ITU-APT Foundation of India" },
|
||||
{ "name": "LANIC", "logo": "/assets/img/gov & forums/LANIC.jpg", "subtitle": "Laos National Internet Centre" },
|
||||
{ "name": "Malawi Revenue Authority", "logo": "/assets/img/gov & forums/Malawi Revenue Authority.jpg", "subtitle": "Malawi Revenue Authority" },
|
||||
{ "name": "NAv6", "logo": "/assets/img/gov & forums/NAv6.jpg", "subtitle": "National Advanced IPv6 Centre" },
|
||||
{ "name": "NIDA", "logo": "/assets/img/gov & forums/NIDA.png", "subtitle": "National Institute of Development Administration" },
|
||||
{ "name": "NIXI", "logo": "/assets/img/gov & forums/NIXI.png", "subtitle": "National Internet Exchange of India" },
|
||||
{ "name": "TRC Sri Lanka", "logo": "/assets/img/gov & forums/TRC Sri Lanka.png", "subtitle": "Telecommunications Regulatory Commission of Sri Lanka" },
|
||||
{ "name": "World Broadband Association", "logo": "/assets/img/gov & forums/World Broadband Association.png", "subtitle": "World Broadband Association" },
|
||||
{ "name": "APJII", "logo": "/assets/img/gov & forums/APJII.png", "subtitle": "Indonesia Internet Service Provider Association" }
|
||||
]
|
||||
},
|
||||
"universities": {
|
||||
"title": "Universities",
|
||||
"items": [
|
||||
{ "name": "APU Malaysia", "logo": "/assets/img/universities/APU Malaysia.png", "subtitle": "Asia Pacific University of Technology & Innovation" },
|
||||
{ "name": "COMSATS University", "logo": "/assets/img/universities/COMSATS Uni.jpg", "subtitle": "COMSATS University Islamabad" },
|
||||
{ "name": "Dr. MGR University", "logo": "/assets/img/universities/Dr. MGR University.png", "subtitle": "Dr. M.G.R. Educational and Research Institute" },
|
||||
{ "name": "IEC", "logo": "/assets/img/universities/IEC.png", "subtitle": "International Education Centre" },
|
||||
{ "name": "ITS", "logo": "/assets/img/universities/ITS.webp", "subtitle": "Sepuluh Nopember Institute of Technology" },
|
||||
{ "name": "Keio University", "logo": "/assets/img/universities/Keio University.png", "subtitle": "Keio University" },
|
||||
{ "name": "MSEC", "logo": "/assets/img/universities/MSEC.jpg", "subtitle": "Meenakshi Sundararajan Engineering College" },
|
||||
{ "name": "MUST", "logo": "/assets/img/universities/MUST.jpg", "subtitle": "Malaysia University of Science and Technology" },
|
||||
{ "name": "SIMS", "logo": "/assets/img/universities/SIMS.jpg", "subtitle": "Saigon Institute for Management Studies" },
|
||||
{ "name": "SUST", "logo": "/assets/img/universities/SUST.jpg", "subtitle": "Shahjalal University of Science and Technology" },
|
||||
{ "name": "UNSW", "logo": "/assets/img/universities/UNSW.jpg", "subtitle": "University of New South Wales" }
|
||||
]
|
||||
},
|
||||
"privateSector": {
|
||||
"title": "Organizations",
|
||||
"items": [
|
||||
{ "name": "Agile Consultancy", "logo": "/assets/img/organizations/Agile Consultancy.jpg", "subtitle": "Agile Consultancy Pvt. Ltd." },
|
||||
{ "name": "BII Group", "logo": "/assets/img/organizations/BII Group.png", "subtitle": "BII Group Holdings" },
|
||||
{ "name": "Bhutan Telecom", "logo": "/assets/img/organizations/Bhutan Telecom Ltd., Bhutan.png", "subtitle": "Bhutan Telecom" },
|
||||
{ "name": "CERT Tonga", "logo": "/assets/img/organizations/CERT Tonga.jpg", "subtitle": "Computer Emergency Response Team Tonga" },
|
||||
{ "name": "CNLabs", "logo": "/assets/img/organizations/CNLabs.jpg", "subtitle": "CNLabs (IPv6 Ready Logo Lab)" },
|
||||
{ "name": "Digital Bridge Institute", "logo": "/assets/img/organizations/Digital Bridge Institute.png", "subtitle": "Digital Bridge Institute Nigeria" },
|
||||
{ "name": "Edgepoint", "logo": "/assets/img/organizations/Edgepoint.png", "subtitle": "Edgepoint Infrastructure" },
|
||||
{ "name": "Hassan Solutions", "logo": "/assets/img/organizations/Hassan Solutions.png", "subtitle": "Hassan Solutions Pakistan" },
|
||||
{ "name": "Huawei", "logo": "/assets/img/organizations/Huawei.png", "subtitle": "Huawei Technologies Co., Ltd." },
|
||||
{ "name": "IPv6 Forum Malaysia", "logo": "/assets/img/organizations/IPv6 Forum Malaysia.png", "subtitle": "IPv6 Forum Malaysia Chapter" },
|
||||
{ "name": "InfinIT ComTech", "logo": "/assets/img/organizations/InfinIT ComTech.jpg", "subtitle": "InfinIT ComTech Vietnam" },
|
||||
{ "name": "MPT", "logo": "/assets/img/organizations/MPT.svg", "subtitle": "Myanma Posts and Telecommunications" },
|
||||
{ "name": "Nokia", "logo": "/assets/img/organizations/NOKIA.jpg", "subtitle": "Nokia Corporation" },
|
||||
{ "name": "RICHAT Partners", "logo": "/assets/img/organizations/RICHAT Partners.jpg", "subtitle": "RICHAT Partners Vietnam" },
|
||||
{ "name": "SAIM Enterprises", "logo": "/assets/img/organizations/SAIM Enterprises.jpg", "subtitle": "SAIM Enterprises India" },
|
||||
{ "name": "Smart Industry Malaysia", "logo": "/assets/img/organizations/Smart Industry Malaysia.jpg", "subtitle": "Smart Industry Malaysia" },
|
||||
{ "name": "Subisu Nepal", "logo": "/assets/img/organizations/Subisu Nepal.png", "subtitle": "Subisu Cablenet Nepal" },
|
||||
{ "name": "Tonga", "logo": "/assets/img/organizations/Tonga.png", "subtitle": "Tonga Communications Corporation" },
|
||||
{ "name": "Wexa Consulting", "logo": "/assets/img/organizations/Wexa Consulting.png", "subtitle": "Wexa Consulting Malaysia" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"contributingMembers": {
|
||||
"title": "Contributing Members",
|
||||
"description": "Distinguished individuals who have contributed to the success of the Council's initiatives.",
|
||||
"items": [
|
||||
{ "name": "Prof Emeritus Dr. Sureswaran Ramadass", "title": "Chairman, APAC IPv6 Council" },
|
||||
{ "name": "Dr Muhammad Asyraf Mohammad Naim", "title": "Director for Training & Consultancy, IPv6 Forum Malaysia" },
|
||||
{ "name": "Ms. Vallikkannu Nagappan", "title": "Chief Secretary, APAC IPv6 Council" },
|
||||
{ "name": "Mr. Hong Thang", "title": "Executive, VNNIC" },
|
||||
{ "name": "Mr. Nguyen Truong Giang", "title": "Executive, VNNIC" },
|
||||
{ "name": "Mr. Bayu Hanantasena", "title": "Strategic Advisor to CEO, Indosat" },
|
||||
{ "name": "Saysomvang Souvannavong", "title": "Deputy Director, Laos National Internet Centre" },
|
||||
{ "name": "Dr. Will Liu", "title": "Head of Europe Datacom Standard & Industry Development, Huawei" },
|
||||
{ "name": "Dr. Gopinath Rao", "title": "Chair of AI Standards Task Force, MTFSB" },
|
||||
{ "name": "Dr. Navaneethan C Arjuman", "title": "Global Coordinator, IPv6 Forum Logo Programme" },
|
||||
{ "name": "Prof. Ts. Dr. Salman Yussof", "title": "Technical Specialist, APAC IPv6 Council" },
|
||||
{ "name": "Mr. Zulfadli Hasan", "title": "Network Engineer, IPv6 Forum Malaysia" },
|
||||
{ "name": "Dr. Suresh Liew", "title": "Research Coordinator, APAC IPv6 Council" },
|
||||
{ "name": "Mr. Mohamad Shukur", "title": "Operations Manager, IPv6 Forum Malaysia" },
|
||||
{ "name": "Assoc. Prof. Dr. Angela Amphawan", "title": "Academic Advisor, APAC IPv6 Council" },
|
||||
{ "name": "Mr. Azizi A. Hadi", "title": "Industry Specialist, Indosat" },
|
||||
{ "name": "Prof. Dr. Abdul Rahman", "title": "Advisor, APAC IPv6 Council" }
|
||||
]
|
||||
},
|
||||
"join": {
|
||||
"title": "Ready to Attend the Summit?",
|
||||
"description": "Register today to secure your ticket and join regional leaders in shaping the future of AI & next-generation data centers in ASEAN.",
|
||||
"registerBtn": "Register Now",
|
||||
"viewMembersBtn": "View Event Agenda"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"hero": {
|
||||
"eyebrow": "HỘI ĐỒNG CỦA CHÚNG TÔI",
|
||||
"title": "Thành Viên",
|
||||
"description": "Sức mạnh tập thể của các tổ chức toàn cầu hàng đầu thúc đẩy áp dụng IPv6 trên toàn hệ sinh thái số của ASEAN. Đây là các thành viên của Hội đồng APAC."
|
||||
},
|
||||
"organizationalMembers": {
|
||||
"title": "Thành Viên Tổ Chức",
|
||||
"description": "Các tổ chức và cơ quan quản lý cam kết triển khai hạ tầng Internet thế hệ mới.",
|
||||
"categories": {
|
||||
"government": {
|
||||
"title": "Chính Phủ & Cơ Quan Quản Lý",
|
||||
"items": [
|
||||
{ "name": "APNIC", "logo": "/assets/img/gov & forums/APNIC.png", "subtitle": "Asia-Pacific Network Information Centre" },
|
||||
{ "name": "VNNIC", "logo": "/assets/img/gov & forums/VNNIC.png", "subtitle": "Vietnam Internet Network Information Center" },
|
||||
{ "name": "IPv6 Forum", "logo": "/assets/img/gov & forums/IPv6 Forum.png", "subtitle": "Global IPv6 Forum" },
|
||||
{ "name": "APAN", "logo": "/assets/img/gov & forums/APAN.png", "subtitle": "Asia Pacific Advanced Network" },
|
||||
{ "name": "Bharat IPv6 Forum", "logo": "/assets/img/gov & forums/Bharat IPv6 Forum.jpg", "subtitle": "India IPv6 Forum" },
|
||||
{ "name": "IDNIC", "logo": "/assets/img/gov & forums/IDNIC.png", "subtitle": "Indonesian Network Information Center" },
|
||||
{ "name": "ISOC Kazakhstan", "logo": "/assets/img/gov & forums/ISOC Kazakhstan.png", "subtitle": "Internet Society Kazakhstan Chapter" },
|
||||
{ "name": "ITU-APT", "logo": "/assets/img/gov & forums/ITU-APT.jpg", "subtitle": "ITU-APT Foundation of India" },
|
||||
{ "name": "LANIC", "logo": "/assets/img/gov & forums/LANIC.jpg", "subtitle": "Laos National Internet Centre" },
|
||||
{ "name": "Malawi Revenue Authority", "logo": "/assets/img/gov & forums/Malawi Revenue Authority.jpg", "subtitle": "Malawi Revenue Authority" },
|
||||
{ "name": "NAv6", "logo": "/assets/img/gov & forums/NAv6.jpg", "subtitle": "National Advanced IPv6 Centre" },
|
||||
{ "name": "NIDA", "logo": "/assets/img/gov & forums/NIDA.png", "subtitle": "National Institute of Development Administration" },
|
||||
{ "name": "NIXI", "logo": "/assets/img/gov & forums/NIXI.png", "subtitle": "National Internet Exchange of India" },
|
||||
{ "name": "TRC Sri Lanka", "logo": "/assets/img/gov & forums/TRC Sri Lanka.png", "subtitle": "Telecommunications Regulatory Commission of Sri Lanka" },
|
||||
{ "name": "World Broadband Association", "logo": "/assets/img/gov & forums/World Broadband Association.png", "subtitle": "World Broadband Association" },
|
||||
{ "name": "APJII", "logo": "/assets/img/gov & forums/APJII.png", "subtitle": "Indonesia Internet Service Provider Association" }
|
||||
]
|
||||
},
|
||||
"universities": {
|
||||
"title": "Trường Đại Học & Nghiên Cứu",
|
||||
"items": [
|
||||
{ "name": "APU Malaysia", "logo": "/assets/img/universities/APU Malaysia.png", "subtitle": "Asia Pacific University of Technology & Innovation" },
|
||||
{ "name": "COMSATS University", "logo": "/assets/img/universities/COMSATS Uni.jpg", "subtitle": "COMSATS University Islamabad" },
|
||||
{ "name": "Dr. MGR University", "logo": "/assets/img/universities/Dr. MGR University.png", "subtitle": "Dr. M.G.R. Educational and Research Institute" },
|
||||
{ "name": "IEC", "logo": "/assets/img/universities/IEC.png", "subtitle": "International Education Centre" },
|
||||
{ "name": "ITS", "logo": "/assets/img/universities/ITS.webp", "subtitle": "Sepuluh Nopember Institute of Technology" },
|
||||
{ "name": "Keio University", "logo": "/assets/img/universities/Keio University.png", "subtitle": "Keio University" },
|
||||
{ "name": "MSEC", "logo": "/assets/img/universities/MSEC.jpg", "subtitle": "Meenakshi Sundararajan Engineering College" },
|
||||
{ "name": "MUST", "logo": "/assets/img/universities/MUST.jpg", "subtitle": "Malaysia University of Science and Technology" },
|
||||
{ "name": "SIMS", "logo": "/assets/img/universities/SIMS.jpg", "subtitle": "Saigon Institute for Management Studies" },
|
||||
{ "name": "SUST", "logo": "/assets/img/universities/SUST.jpg", "subtitle": "Shahjalal University of Science and Technology" },
|
||||
{ "name": "UNSW", "logo": "/assets/img/universities/UNSW.jpg", "subtitle": "University of New South Wales" }
|
||||
]
|
||||
},
|
||||
"privateSector": {
|
||||
"title": "Doanh Nghiệp Tư Nhân",
|
||||
"items": [
|
||||
{ "name": "Agile Consultancy", "logo": "/assets/img/organizations/Agile Consultancy.jpg", "subtitle": "Agile Consultancy Pvt. Ltd." },
|
||||
{ "name": "BII Group", "logo": "/assets/img/organizations/BII Group.png", "subtitle": "BII Group Holdings" },
|
||||
{ "name": "Bhutan Telecom", "logo": "/assets/img/organizations/Bhutan Telecom Ltd., Bhutan.png", "subtitle": "Bhutan Telecom" },
|
||||
{ "name": "CERT Tonga", "logo": "/assets/img/organizations/CERT Tonga.jpg", "subtitle": "Computer Emergency Response Team Tonga" },
|
||||
{ "name": "CNLabs", "logo": "/assets/img/organizations/CNLabs.jpg", "subtitle": "CNLabs (IPv6 Ready Logo Lab)" },
|
||||
{ "name": "Digital Bridge Institute", "logo": "/assets/img/organizations/Digital Bridge Institute.png", "subtitle": "Digital Bridge Institute Nigeria" },
|
||||
{ "name": "Edgepoint", "logo": "/assets/img/organizations/Edgepoint.png", "subtitle": "Edgepoint Infrastructure" },
|
||||
{ "name": "Hassan Solutions", "logo": "/assets/img/organizations/Hassan Solutions.png", "subtitle": "Hassan Solutions Pakistan" },
|
||||
{ "name": "Huawei", "logo": "/assets/img/organizations/Huawei.png", "subtitle": "Huawei Technologies Co., Ltd." },
|
||||
{ "name": "IPv6 Forum Malaysia", "logo": "/assets/img/organizations/IPv6 Forum Malaysia.png", "subtitle": "IPv6 Forum Malaysia Chapter" },
|
||||
{ "name": "InfinIT ComTech", "logo": "/assets/img/organizations/InfinIT ComTech.jpg", "subtitle": "InfinIT ComTech Vietnam" },
|
||||
{ "name": "MPT", "logo": "/assets/img/organizations/MPT.svg", "subtitle": "Myanma Posts and Telecommunications" },
|
||||
{ "name": "Nokia", "logo": "/assets/img/organizations/NOKIA.jpg", "subtitle": "Nokia Corporation" },
|
||||
{ "name": "RICHAT Partners", "logo": "/assets/img/organizations/RICHAT Partners.jpg", "subtitle": "RICHAT Partners Vietnam" },
|
||||
{ "name": "SAIM Enterprises", "logo": "/assets/img/organizations/SAIM Enterprises.jpg", "subtitle": "SAIM Enterprises India" },
|
||||
{ "name": "Smart Industry Malaysia", "logo": "/assets/img/organizations/Smart Industry Malaysia.jpg", "subtitle": "Smart Industry Malaysia" },
|
||||
{ "name": "Subisu Nepal", "logo": "/assets/img/organizations/Subisu Nepal.png", "subtitle": "Subisu Cablenet Nepal" },
|
||||
{ "name": "Tonga", "logo": "/assets/img/organizations/Tonga.png", "subtitle": "Tonga Communications Corporation" },
|
||||
{ "name": "Wexa Consulting", "logo": "/assets/img/organizations/Wexa Consulting.png", "subtitle": "Wexa Consulting Malaysia" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"contributingMembers": {
|
||||
"title": "Thành Viên Đóng Góp",
|
||||
"description": "Những cá nhân xuất sắc đã đóng góp vào sự thành công của các sáng kiến từ Hội đồng.",
|
||||
"items": [
|
||||
{ "name": "Prof Emeritus Dr. Sureswaran Ramadass", "title": "Chairman, APAC IPv6 Council" },
|
||||
{ "name": "Dr Muhammad Asyraf Mohammad Naim", "title": "Director for Training & Consultancy, IPv6 Forum Malaysia" },
|
||||
{ "name": "Ms. Vallikkannu Nagappan", "title": "Chief Secretary, APAC IPv6 Council" },
|
||||
{ "name": "Mr. Hong Thang", "title": "Executive, VNNIC" },
|
||||
{ "name": "Mr. Nguyen Truong Giang", "title": "Executive, VNNIC" },
|
||||
{ "name": "Mr. Bayu Hanantasena", "title": "Strategic Advisor to CEO, Indosat" },
|
||||
{ "name": "Saysomvang Souvannavong", "title": "Deputy Director, Laos National Internet Centre" },
|
||||
{ "name": "Dr. Will Liu", "title": "Head of Europe Datacom Standard & Industry Development, Huawei" },
|
||||
{ "name": "Dr. Gopinath Rao", "title": "Chair of AI Standards Task Force, MTFSB" },
|
||||
{ "name": "Dr. Navaneethan C Arjuman", "title": "Global Coordinator, IPv6 Forum Logo Programme" },
|
||||
{ "name": "Prof. Ts. Dr. Salman Yussof", "title": "Technical Specialist, APAC IPv6 Council" },
|
||||
{ "name": "Mr. Zulfadli Hasan", "title": "Network Engineer, IPv6 Forum Malaysia" },
|
||||
{ "name": "Dr. Suresh Liew", "title": "Research Coordinator, APAC IPv6 Council" },
|
||||
{ "name": "Mr. Mohamad Shukur", "title": "Operations Manager, IPv6 Forum Malaysia" },
|
||||
{ "name": "Assoc. Prof. Dr. Angela Amphawan", "title": "Academic Advisor, APAC IPv6 Council" },
|
||||
{ "name": "Mr. Azizi A. Hadi", "title": "Industry Specialist, Indosat" },
|
||||
{ "name": "Prof. Dr. Abdul Rahman", "title": "Advisor, APAC IPv6 Council" }
|
||||
]
|
||||
},
|
||||
"join": {
|
||||
"title": "Sẵn Sàng Tham Gia Hội Nghị?",
|
||||
"description": "Đăng ký ngay hôm nay để giữ chỗ và cùng các nhà lãnh đạo khu vực định hình tương lai của AI & trung tâm dữ liệu thế hệ mới tại ASEAN.",
|
||||
"registerBtn": "Đăng Ký Ngay",
|
||||
"viewMembersBtn": "Xem Lịch Trình Sự Kiện"
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
"nav": [
|
||||
{ "label": "Home", "href": "/" },
|
||||
{ "label": "Gallery", "href": "/gallery" },
|
||||
{ "label": "Members", "href": "/members" },
|
||||
{ "label": "Registration", "href": "/registration" },
|
||||
{ "label": "Feedback", "href": "/feedback" },
|
||||
{ "label": "Sponsor", "href": "/sponsor" }
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"nav": [
|
||||
{ "label": "Trang Chủ", "href": "/" },
|
||||
{ "label": "Thư Viện Ảnh", "href": "/gallery" },
|
||||
{ "label": "Thành Viên", "href": "/members" },
|
||||
{ "label": "Đăng Ký", "href": "/registration" },
|
||||
{ "label": "Phản Hồi", "href": "/feedback" },
|
||||
{ "label": "Nhà Tài Trợ", "href": "/sponsor" }
|
||||
|
||||
+21
-6
@@ -43,7 +43,12 @@ body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: "Nasalization", system-ui, sans-serif;
|
||||
}
|
||||
|
||||
@@ -107,16 +112,26 @@ textarea::placeholder {
|
||||
|
||||
/* Partners Carousel animations */
|
||||
@keyframes scroll-fwd {
|
||||
0% { transform: translateX(0); }
|
||||
100% { transform: translateX(calc(-1 * var(--set-width) - 20px)); }
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(calc(-1 * var(--set-width) - 20px));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scroll-reverse {
|
||||
0% { transform: translateX(calc(-1 * var(--set-width) - 20px)); }
|
||||
100% { transform: translateX(0); }
|
||||
0% {
|
||||
transform: translateX(calc(-1 * var(--set-width) - 20px));
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-scroll:hover,
|
||||
.animate-scroll-reverse:hover {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@ import adminEn from "@/app/data/admin.json";
|
||||
import adminVi from "@/app/data/admin.vi.json";
|
||||
import galleryEn from "@/app/data/gallery.json";
|
||||
import galleryVi from "@/app/data/gallery.vi.json";
|
||||
import membersEn from "@/app/data/members.json";
|
||||
import membersVi from "@/app/data/members.vi.json";
|
||||
|
||||
export function useTranslation() {
|
||||
const { lang } = useLanguage();
|
||||
@@ -28,5 +30,6 @@ export function useTranslation() {
|
||||
sponsor: isVi ? sponsorVi : sponsorEn,
|
||||
admin: isVi ? adminVi : adminEn,
|
||||
gallery: isVi ? galleryVi : galleryEn,
|
||||
members: isVi ? membersVi : membersEn,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user