-
-
+
+
{item.icon}
-
+
{item.title}
-
+ {item.benefits && item.benefits.length > 0 && (
+
+ {item.benefits.map((b) => (
+ -
+ {b}
+
+ ))}
+
+ )}
+
{item.status}
diff --git a/app/data/feedback.vi.json b/app/data/feedback.vi.json
index 2b04c7f..5f22b3e 100644
--- a/app/data/feedback.vi.json
+++ b/app/data/feedback.vi.json
@@ -1,10 +1,10 @@
{
- "title": "Phản Hồi Sự Kiện",
- "subtitle": "Ý kiến của bạn định hướng tương lai hạ tầng IPv6. Hãy giúp chúng tôi cải thiện trải nghiệm năm 2027.",
+ "title": "Khảo sát Sự Kiện",
+ "subtitle": "Giúp chúng tôi nâng tầm trải nghiệm 2027, thúc đẩy tương lai hạ tầng IPv6 bằng đánh giá của bạn.",
"sections": [
{
"id": "overall",
- "title": "1. TRẢI NGHIỆM TỔNG THỂ",
+ "title": "1. MỨC ĐỘ HÀI LÒNG TỔNG QUAN",
"subtitle": "Tổng quan về trải nghiệm hội nghị của bạn",
"questions": [
{
diff --git a/app/data/home.vi.json b/app/data/home.vi.json
index 1282531..9785a7d 100644
--- a/app/data/home.vi.json
+++ b/app/data/home.vi.json
@@ -2,8 +2,8 @@
"hero": {
"badgeIcon": "calendar_today",
"badgeText": "Tháng 6/2026 | TP. Hồ Chí Minh, Việt Nam",
- "title": "Hội Nghị IPv6 cho AI & Trung Tâm Dữ Liệu 2026",
- "subtitle": "Khai Phá Tiềm Năng Hạ Tầng Thế Hệ Mới. Cùng các nhà lãnh đạo toàn cầu định hình lại kết nối số ASEAN trong kỷ nguyên AI.",
+ "title": "IPv6 for AI & Data Centre Summit 2026",
+ "subtitle": "Khám phá tiềm năng Hạ tầng thế hệ mới. Chung sức định hình kỷ nguyên kết nối số tại ASEAN cùng doanh nghiệp hàng đầu quốc tế.",
"primaryCta": { "label": "Đăng Ký", "href": "/registration" },
"secondaryCta": { "label": "Xem Lịch Trình", "href": "#agenda" }
},
diff --git a/app/data/registration.vi.json b/app/data/registration.vi.json
index e74d737..80b60bc 100644
--- a/app/data/registration.vi.json
+++ b/app/data/registration.vi.json
@@ -1,6 +1,6 @@
{
"title": "Đăng Ký Tham Dự Hội Nghị",
- "subtitle": "Đảm bảo sự hiện diện của bạn ở tuyến đầu đổi mới IPv6 cho AI và Trung Tâm Dữ Liệu.",
+ "subtitle": "Nắm bắt cơ hội tiên phong thời kỳ đổi mới IPv6 cho AI và trung tâm dữ liệu.",
"sections": {
"personal": {
"title": "Thông Tin Cá Nhân",
@@ -9,13 +9,13 @@
"email": "Email Doanh Nghiệp"
},
"professional": {
- "title": "Thông Tin Nghề Nghiệp",
- "company": "Tên Công Ty",
- "jobTitle": "Chức Danh"
+ "title": "Thông Tin Doanh Nghiệp",
+ "company": "Tên Doanh Nghiệp",
+ "jobTitle": "Vị Trí"
},
"industry": {
- "title": "Ngành Nghề",
- "label": "Chọn Ngành Nghề",
+ "title": "Lĩnh Vực",
+ "label": "Chọn Lĩnh Vực",
"placeholder": "Vui lòng chọn...",
"options": [
{ "value": "government", "label": "Chính Phủ" },
@@ -27,8 +27,8 @@
},
"additional": {
"title": "Thông Tin Bổ Sung",
- "label": "Yêu cầu đặc biệt hoặc chế độ ăn kiêng",
- "placeholder": "Tùy chọn ăn chay, nhu cầu tiếp cận, v.v."
+ "label": "Yêu cầu đặc biệt hoặc chế độ dinh dưỡng",
+ "placeholder": "Chế độ ăn chay, hỗ trợ người khuyết tật, v.v"
}
},
"submit": {
diff --git a/app/data/sponsor.json b/app/data/sponsor.json
index fcc8dbd..451874d 100644
--- a/app/data/sponsor.json
+++ b/app/data/sponsor.json
@@ -71,24 +71,44 @@
]
},
"itemBased": {
- "eyebrow": "À LA CARTE",
+ "eyebrow": "ENGAGEMENT CATEGORIES",
"title": "Item-Based Sponsorship",
"description": "Targeted branding opportunities for specific summit pillars",
"items": [
- { "icon": "hotel", "title": "Hotel Accommodation", "status": "Limited Space" },
- { "icon": "meeting_room", "title": "Conference Hall", "status": "Sold Out" },
- { "icon": "groups", "title": "Networking Zone", "status": "Available" },
- { "icon": "newsmode", "title": "Media Partner", "status": "Apply Now" }
+ {
+ "icon": "location_city",
+ "title": "Venue Sponsor",
+ "status": "Register Now",
+ "benefits": ["Hotel venue", "Conference hall", "Networking area"]
+ },
+ {
+ "icon": "computer",
+ "title": "Tech Sponsor",
+ "status": "Register Now",
+ "benefits": ["AV equipment", "WiFi / Internet", "Tech support"]
+ },
+ {
+ "icon": "newspaper",
+ "title": "Media Sponsor",
+ "status": "Register Now",
+ "benefits": ["Press coverage", "Social media", "Media coverage"]
+ },
+ {
+ "icon": "card_giftcard",
+ "title": "Gift & F&B Sponsor",
+ "status": "Register Now",
+ "benefits": ["Gift set", "Coffee break", "Networking dinner"]
+ }
],
"highlights": [
{
"eyebrow": "STANDARD BENEFIT",
- "title": "Logo on backdrop & LED screens",
+ "title": "Logo on backdrop, LED",
"icon": "branding_watermark"
},
{
"eyebrow": "ACCESS PACK",
- "title": "02 VIP Delegate tickets included",
+ "title": "02 VIP Pass",
"icon": "confirmation_number"
}
]
diff --git a/app/data/sponsor.vi.json b/app/data/sponsor.vi.json
index 4579bcc..ceef38a 100644
--- a/app/data/sponsor.vi.json
+++ b/app/data/sponsor.vi.json
@@ -71,24 +71,44 @@
]
},
"itemBased": {
- "eyebrow": "À LA CARTE",
+ "eyebrow": "HẠNG MỤC ĐỒNG HÀNH",
"title": "Tài Trợ Theo Hạng Mục",
"description": "Cơ hội thương hiệu có mục tiêu cho các trụ cột cụ thể của hội nghị",
"items": [
- { "icon": "hotel", "title": "Chỗ Ở Khách Sạn", "status": "Còn Ít Chỗ" },
- { "icon": "meeting_room", "title": "Hội Trường Hội Nghị", "status": "Đã Hết" },
- { "icon": "groups", "title": "Khu Vực Kết Nối", "status": "Còn Trống" },
- { "icon": "newsmode", "title": "Đối Tác Truyền Thông", "status": "Đăng Ký Ngay" }
+ {
+ "icon": "location_city",
+ "title": "Tài Trợ Địa Điểm",
+ "status": "Đăng Ký Ngay",
+ "benefits": ["Khách sạn", "Hội trường", "Khu vực networking"]
+ },
+ {
+ "icon": "computer",
+ "title": "Tài Trợ Công Nghệ",
+ "status": "Đăng Ký Ngay",
+ "benefits": ["Thiết bị trình chiếu", "WiFi / Internet", "Hạ tầng kỹ thuật"]
+ },
+ {
+ "icon": "newspaper",
+ "title": "Tài Trợ Truyền Thông",
+ "status": "Đăng Ký Ngay",
+ "benefits": ["Báo chí", "Social media", "Media coverage"]
+ },
+ {
+ "icon": "card_giftcard",
+ "title": "Tài Trợ Quà Tặng / F&B",
+ "status": "Đăng Ký Ngay",
+ "benefits": ["Gift set", "Coffee break", "Networking dinner"]
+ }
],
"highlights": [
{
"eyebrow": "QUYỀN LỢI TIÊU CHUẨN",
- "title": "Logo trên phông & màn hình LED",
+ "title": "Logo nổi bật trên backdrop, màn LED",
"icon": "branding_watermark"
},
{
- "eyebrow": "GÓI TIẾP CẬN",
- "title": "02 vé VIP đại biểu được bao gồm",
+ "eyebrow": "QUYỀN LỢI THAM DỰ",
+ "title": "Đã bao gồm 02 vé VIP đại biểu",
"icon": "confirmation_number"
}
]
@@ -96,16 +116,16 @@
"contact": {
"id": "contact",
"title": "Hợp Tác Cùng Chúng Tôi",
- "description": "Nâng tầm thương hiệu của bạn trong hành lang công nghệ Ấn Độ - Thái Bình Dương. Hội nghị của chúng tôi mang đến khả năng tiếp cận vô song tới các nhà ra quyết định, nhà nghiên cứu và quan chức chính phủ đang thúc đẩy thế hệ hạ tầng trung tâm dữ liệu và phát triển AI.",
+ "description": "Nâng tầm thương hiệu doanh nghiệp trên khu vực công nghệ Ấn Độ - Thái Bình Dương. Hội thảo mang đến cơ hội hiếm có đến các tổ chức chính phủ, lãnh đạo chủ chốt, đơn vị nghiên cứu trực tiếp tham gia vào quá trình phát triển AI và Cơ sở hạ tầng dữ liệu số.",
"phone": {
"label": "ĐIỆN THOẠI",
"value": "+84 941 523 498"
},
"email": {
- "label": "EMAIL TRỰC TIẾP",
+ "label": "EMAIL TƯ VẤN",
"value": "events@techvanguard.vn"
},
- "cta": "Liên Hệ Để Tài Trợ",
+ "cta": "Kết nối nhà tài trợ",
"image": {
"src": "https://lh3.googleusercontent.com/aida-public/AB6AXuATSk4rhRYAo9_OfX0cJwIC7rUdUmzD9kO7cJM24ECjPHwglU_s0wjBn6gdK0d7tk4ExLvG9DUJQ1L-PbP5ucVH2THO05fev6bWgyvpkElf_94JXJNeWj0Mo4-5-l2ofY-kHE6kPLhitbRzarR7u41favHCt_V9WM0yYb7tcZZQM8eAN5jIVT5OVKSGvfpZNYe05dJm_h3pW0qkWhX1XrUtg_xhhjdvTi-Mei7zHDUkwwRrydg7BHmO17W6ScfALH5rMXojTHub7UDN",
"alt": "Cuộc họp kinh doanh chuyên nghiệp trong phòng hội thảo công nghệ cao"
diff --git a/app/globals.css b/app/globals.css
index 4bb5a1c..5929ff5 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1,5 +1,13 @@
@import "tailwindcss";
+@font-face {
+ font-family: "Nasalization";
+ src: url("/assets/webfonts/Nasalization Rg.otf") format("opentype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: swap;
+}
+
@theme {
/* IPV6 Summit design tokens */
--color-primary: #c5a059;
@@ -16,9 +24,9 @@
--color-on-surface-variant: #e0e0e0;
--color-outline: #c5a059;
- --font-body-base: "Inter", system-ui, sans-serif;
- --font-display-lg: "Space Grotesk", system-ui, sans-serif;
- --font-label-caps: "Geist", system-ui, sans-serif;
+ --font-body-base: "Nasalization", system-ui, sans-serif;
+ --font-display-lg: "Nasalization", system-ui, sans-serif;
+ --font-label-caps: "Nasalization", system-ui, sans-serif;
--font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
@@ -37,7 +45,7 @@ html {
body {
background-color: var(--color-background);
color: var(--color-on-surface-variant);
- font-family: var(--font-body-base);
+ font-family: "Nasalization", system-ui, sans-serif;
overflow-x: hidden;
}
@@ -98,3 +106,19 @@ textarea::placeholder {
box-shadow: 0 0 8px currentColor;
}
+
+/* Partners Carousel animations */
+@keyframes scroll-fwd {
+ 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); }
+}
+
+.animate-scroll:hover,
+.animate-scroll-reverse:hover {
+ animation-play-state: paused;
+}
diff --git a/middleware.ts b/middleware.ts
index bf2a4a3..7526bfa 100644
--- a/middleware.ts
+++ b/middleware.ts
@@ -1,41 +1,14 @@
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
-function unauthorized() {
- return new NextResponse("Authentication required", {
- status: 401,
- headers: {
- "WWW-Authenticate": 'Basic realm="IPv6 Admin"',
- },
- });
-}
-
export function middleware(request: NextRequest) {
- const user = process.env.ADMIN_BASIC_AUTH_USER;
- const pass = process.env.ADMIN_BASIC_AUTH_PASS;
+ const session = request.cookies.get("admin_session");
- if (!user || !pass) {
- return NextResponse.next();
- }
-
- const auth = request.headers.get("authorization");
- if (!auth?.startsWith("Basic ")) {
- return unauthorized();
- }
-
- let decoded: string;
- try {
- decoded = atob(auth.slice(6));
- } catch {
- return unauthorized();
- }
-
- const colon = decoded.indexOf(":");
- const u = colon >= 0 ? decoded.slice(0, colon) : "";
- const p = colon >= 0 ? decoded.slice(colon + 1) : "";
-
- if (u !== user || p !== pass) {
- return new NextResponse("Unauthorized", { status: 401 });
+ if (!session || session.value !== "true") {
+ // If not authenticated and trying to access admin, redirect to login
+ const url = request.nextUrl.clone();
+ url.pathname = "/login";
+ return NextResponse.redirect(url);
}
return NextResponse.next();
diff --git a/models/User.ts b/models/User.ts
new file mode 100644
index 0000000..7cbd795
--- /dev/null
+++ b/models/User.ts
@@ -0,0 +1,18 @@
+import mongoose, { Schema, Document } from "mongoose";
+
+export interface IUser extends Document {
+ email: string;
+ password: string;
+ createdAt: Date;
+ updatedAt: Date;
+}
+
+const UserSchema: Schema = new Schema(
+ {
+ email: { type: String, required: true, unique: true },
+ password: { type: String, required: true },
+ },
+ { timestamps: true }
+);
+
+export default mongoose.models.User || mongoose.model
("User", UserSchema);
diff --git a/public/assets/img/carousel/Alibaba-Logo.png b/public/assets/img/carousel/Alibaba-Logo.png
new file mode 100644
index 0000000..fa408a9
Binary files /dev/null and b/public/assets/img/carousel/Alibaba-Logo.png differ
diff --git a/public/assets/img/carousel/Equinix_logo.svg.png b/public/assets/img/carousel/Equinix_logo.svg.png
new file mode 100644
index 0000000..9b48212
Binary files /dev/null and b/public/assets/img/carousel/Equinix_logo.svg.png differ
diff --git a/public/assets/img/carousel/Huawei_Standard_logo.svg.png b/public/assets/img/carousel/Huawei_Standard_logo.svg.png
new file mode 100644
index 0000000..5b1ac2c
Binary files /dev/null and b/public/assets/img/carousel/Huawei_Standard_logo.svg.png differ
diff --git a/public/assets/img/carousel/Logonetflix.png b/public/assets/img/carousel/Logonetflix.png
new file mode 100644
index 0000000..67ada37
Binary files /dev/null and b/public/assets/img/carousel/Logonetflix.png differ
diff --git a/public/assets/img/carousel/Maxis-logo.png b/public/assets/img/carousel/Maxis-logo.png
new file mode 100644
index 0000000..d1b5296
Binary files /dev/null and b/public/assets/img/carousel/Maxis-logo.png differ
diff --git a/public/assets/img/carousel/Microsoft-Logo.png b/public/assets/img/carousel/Microsoft-Logo.png
new file mode 100644
index 0000000..37e5dbe
Binary files /dev/null and b/public/assets/img/carousel/Microsoft-Logo.png differ
diff --git a/public/assets/img/carousel/Nvidia_logo.svg.png b/public/assets/img/carousel/Nvidia_logo.svg.png
new file mode 100644
index 0000000..26a1c89
Binary files /dev/null and b/public/assets/img/carousel/Nvidia_logo.svg.png differ
diff --git a/public/assets/img/carousel/Singtel_logo.svg.png b/public/assets/img/carousel/Singtel_logo.svg.png
new file mode 100644
index 0000000..d7ad72c
Binary files /dev/null and b/public/assets/img/carousel/Singtel_logo.svg.png differ
diff --git a/public/assets/img/carousel/XL_Axiata-Logo.wine.png b/public/assets/img/carousel/XL_Axiata-Logo.wine.png
new file mode 100644
index 0000000..1162261
Binary files /dev/null and b/public/assets/img/carousel/XL_Axiata-Logo.wine.png differ
diff --git a/public/assets/img/carousel/airtrunk.png b/public/assets/img/carousel/airtrunk.png
new file mode 100644
index 0000000..25f256e
Binary files /dev/null and b/public/assets/img/carousel/airtrunk.png differ
diff --git a/public/assets/img/carousel/celcomdigi.png b/public/assets/img/carousel/celcomdigi.png
new file mode 100644
index 0000000..914d291
Binary files /dev/null and b/public/assets/img/carousel/celcomdigi.png differ
diff --git a/public/assets/img/carousel/grab.png b/public/assets/img/carousel/grab.png
new file mode 100644
index 0000000..241565e
Binary files /dev/null and b/public/assets/img/carousel/grab.png differ
diff --git a/public/assets/img/carousel/logo_transparent.png b/public/assets/img/carousel/logo_transparent.png
new file mode 100644
index 0000000..3f03689
Binary files /dev/null and b/public/assets/img/carousel/logo_transparent.png differ
diff --git a/public/assets/img/carousel/nida.png b/public/assets/img/carousel/nida.png
new file mode 100644
index 0000000..32272f9
Binary files /dev/null and b/public/assets/img/carousel/nida.png differ
diff --git a/public/assets/img/carousel/tencent.png b/public/assets/img/carousel/tencent.png
new file mode 100644
index 0000000..c20cf21
Binary files /dev/null and b/public/assets/img/carousel/tencent.png differ
diff --git a/public/assets/img/carousel/vnnic.png b/public/assets/img/carousel/vnnic.png
new file mode 100644
index 0000000..fc468d7
Binary files /dev/null and b/public/assets/img/carousel/vnnic.png differ
diff --git a/public/assets/webfonts/Nasalization Rg.otf b/public/assets/webfonts/Nasalization Rg.otf
new file mode 100644
index 0000000..a9333c7
Binary files /dev/null and b/public/assets/webfonts/Nasalization Rg.otf differ
diff --git a/scripts/seed-admin.ts b/scripts/seed-admin.ts
new file mode 100644
index 0000000..e08af41
--- /dev/null
+++ b/scripts/seed-admin.ts
@@ -0,0 +1,46 @@
+import mongoose from "mongoose";
+import User from "../models/User";
+import * as dotenv from "dotenv";
+import path from "path";
+import crypto from "crypto";
+
+dotenv.config({ path: path.join(__dirname, "../.env") });
+
+function hashPassword(password: string) {
+ return crypto.createHash("sha256").update(password).digest("hex");
+}
+
+async function seedAdmin() {
+ const MONGODB_URI = process.env.MONGODB_URI;
+
+ if (!MONGODB_URI) {
+ console.error("MONGODB_URI not found");
+ process.exit(1);
+ }
+
+ try {
+ await mongoose.connect(MONGODB_URI);
+ console.log("Connected to MongoDB");
+
+ const adminEmail = "adminipv6@mail.com".toLowerCase().trim();
+ const adminPassword = "adminipv6A@a";
+ const hashedPassword = hashPassword(adminPassword);
+
+ // Xóa sạch user cũ để tránh xung đột
+ await User.deleteMany({ email: adminEmail });
+
+ await User.create({
+ email: adminEmail,
+ password: hashedPassword,
+ });
+
+ console.log("SUCCESS: Admin account created/refreshed with hashed password.");
+ console.log(`Email: ${adminEmail}`);
+ } catch (error) {
+ console.error("Error:", error);
+ } finally {
+ await mongoose.disconnect();
+ }
+}
+
+seedAdmin();