Compare commits

...

3 Commits

Author SHA1 Message Date
cf880f573f quick question, answer
All checks were successful
Build and Release / release (push) Successful in 33s
2026-05-09 16:22:22 +07:00
3ec9c51085 update about us
All checks were successful
Build and Release / release (push) Successful in 35s
2026-05-09 16:01:01 +07:00
f5fa38ec5a about-us
All checks were successful
Build and Release / release (push) Successful in 34s
2026-05-09 15:19:40 +07:00
9 changed files with 435 additions and 28 deletions

BIN
public/images/map.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,300 @@
"use client";
import React from "react";
import Image from "next/image";
import Link from "next/link";
export default function LandingPage() {
const features = [
{
title: "Bản đồ dòng thời gian",
desc: "Giao diện bản đồ tự động thay đổi biên giới, địa danh và sự kiện tương ứng với mốc thời gian được lựa chọn.",
icon: "🗺️",
},
{
title: "Tương tác thực tế",
desc: "Hiển thị chi tiết bối cảnh, nhân vật và số liệu khi người dùng thao tác vào các điểm neo sự kiện trên bản đồ.",
icon: "📍",
},
{
title: "Trợ lý ảo & Công cụ học",
desc: "Tích hợp AI giải đáp thắc mắc lịch sử, kết hợp hệ thống giao bài tập và làm Quiz trực tuyến cho học đường.",
icon: "🤖",
},
];
const team = [
{
name: "Trần Anh Đức",
role: "Project Manager",
desc: "Đẹp trai cao m8",
avatar: "/images/teamdev/tad.jpeg",
},
{
name: "Đỗ Duy Khánh",
role: "Backend Developer",
desc: "Kì nhân dị sỹ",
avatar: "/images/teamdev/ddk2.jpeg",
},
{
name: "Ngô Cung Đức Anh",
role: "Frontend Developer",
desc: "Cũng đẹp trai nhưng cao m7 thôi",
avatar: "/images/teamdev/ncda.jpeg",
},
];
return (
// Sử dụng tông màu Vàng cổ (Parchment) và Xanh rêu (Dark Slate Green)
<div className="relative min-h-screen w-full text-[#2D3A3A] font-sans selection:bg-[#A88B4C] selection:text-white overflow-x-hidden">
{/* --- BACKGROUND IMAGE --- */}
<div className="fixed inset-0 -z-20 pointer-events-none">
<Image
src="/images/map.jpeg"
alt="World Map Background"
fill
className="object-cover object-center opacity-40"
priority
/>
</div>
{/* Lớp overlay mờ để làm dịu background */}
<div className="fixed inset-0 bg-gradient-to-b from-[#FDFBF7]/80 via-[#FDFBF7]/70 to-[#FDFBF7]/90 -z-10 pointer-events-none"></div>
{/* --- HEADER NAVBAR --- */}
<header className="fixed top-0 w-full px-6 py-4 flex justify-between items-center backdrop-blur-sm bg-[#FDFBF7]/70 z-50 border-b border-[#A88B4C]/20">
<div className="text-xl font-bold tracking-widest text-[#2D3A3A] uppercase">
<span className="text-[#A88B4C]">Geo</span>History
</div>
<nav className="flex gap-4 items-center">
<Link
href="/auth/signin"
className="text-sm font-semibold text-[#2D3A3A] hover:text-[#A88B4C] transition-colors"
>
Đăng nhập
</Link>
<Link
href="/user"
className="text-sm font-semibold px-4 py-2 bg-[#2D3A3A] text-[#FDFBF7] rounded-lg hover:bg-[#1a2323] transition-colors"
>
Vào Hệ thống
</Link>
</nav>
</header>
<main className="max-w-6xl mx-auto px-6 pt-32 pb-24 flex flex-col gap-32 w-full relative">
{/* --- PHẦN 1: GIỚI THIỆU TỔNG QUAN --- */}
<section className="min-h-[70vh] flex flex-col justify-center relative">
<h1 className="text-5xl md:text-7xl font-black leading-tight tracking-tight mb-6">
Bách khoa toàn thư <br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-[#A88B4C] to-[#806835]">
Bản đ số Lịch sử
</span>
</h1>
<div className="max-w-3xl space-y-6 text-lg md:text-xl text-[#4A5555] leading-relaxed">
<p>
Hệ thống thông tin đa (GIS) tiên phong trong việc trực quan
hóa dữ liệu lịch sử. Nền tảng của chúng tôi cho phép hiển thị đng
các thông tin như biên giới quốc gia, diễn biến trận chiến sự
kiện theo đúng tiến trình thời gian.
</p>
<p>
Đây không gian tập trung tri thức đưc tinh lọc, nơi các chuyên
gia, nhà sử học giáo viên đóng góp dữ liệu tọa đ, vector, đưc
hệ thống kiểm duyệt chặt chẽ trước khi xuất bản.
</p>
</div>
<div className="mt-10 flex gap-4">
<Link
href="#mission"
className="px-8 py-4 bg-[#A88B4C] text-white font-bold rounded-xl shadow-lg shadow-[#A88B4C]/20 hover:bg-[#8e743c]"
>
Khám phá sứ mệnh
</Link>
</div>
</section>
{/* --- PHẦN 2: SỨ MỆNH & CHỨC NĂNG --- */}
<section id="mission" className="scroll-mt-24 relative">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-16 items-center">
{/* Sứ mệnh */}
<div>
<div className="inline-block px-3 py-1 bg-[#A88B4C]/10 text-[#A88B4C] font-bold text-sm tracking-widest uppercase rounded-full mb-4 border border-[#A88B4C]/20">
Sứ mệnh của chúng tôi
</div>
<h2 className="text-3xl md:text-4xl font-bold mb-6">
Đnh hình lại cách học Lịch sử
</h2>
<div className="space-y-6 text-[#4A5555]">
<div>
<h3 className="text-xl font-bold text-[#2D3A3A] mb-2 flex items-center gap-2">
<span className="w-8 h-8 rounded-full bg-[#A88B4C]/20 flex items-center justify-center text-[#A88B4C]">
1
</span>
Giải quyết rào cản giáo dục
</h3>
<p>
Khắc phục sự nhàm chán khó tiếp cận của phương pháp học
lịch sử truyền thống bằng cách biến dữ liệu chữ viết thành
hình nh không gian, thời gian trực quan.
</p>
</div>
<div className="w-full h-px bg-[#A88B4C]/20"></div>
<div>
<h3 className="text-xl font-bold text-[#2D3A3A] mb-2 flex items-center gap-2">
<span className="w-8 h-8 rounded-full bg-[#A88B4C]/20 flex items-center justify-center text-[#A88B4C]">
2
</span>
Tập trung hóa tri thức
</h3>
<p>
Xây dựng một kho dữ liệu lịch sử thống nhất, chuẩn xác, phục
vụ đa dạng đi tượng từ chính phủ, chuyên gia nghiên cứu đến
học sinh, sinh viên cộng đng.
</p>
</div>
</div>
</div>
{/* Chức năng */}
<div>
<div className="inline-block px-3 py-1 bg-[#2D3A3A]/10 text-[#2D3A3A] font-bold text-sm tracking-widest uppercase rounded-full mb-4 border border-[#2D3A3A]/20">
Tính năng cốt lõi
</div>
<h2 className="text-3xl md:text-4xl font-bold mb-6">
Công nghệ hội tụ
</h2>
<div className="flex flex-col gap-4">
{features.map((feat, idx) => (
<div
key={idx}
className="flex gap-4 items-start p-5 hover:bg-[#A88B4C]/10 rounded-2xl group"
>
<div className="text-3xl bg-transparent w-14 h-14 rounded-xl flex items-center justify-center shrink-0">
{feat.icon}
</div>
<div>
<h4 className="font-bold text-[#2D3A3A] text-lg mb-1">
{feat.title}
</h4>
<p className="text-sm text-[#4A5555] leading-relaxed">
{feat.desc}
</p>
</div>
</div>
))}
</div>
</div>
</div>
</section>
{/* --- PHẦN 3: ĐỘI NGŨ PHÁT TRIỂN --- */}
<section className="relative">
<div className="text-center max-w-2xl mx-auto mb-12">
<div className="inline-block px-3 py-1 bg-[#A88B4C]/10 text-[#A88B4C] font-bold text-sm tracking-widest uppercase rounded-full mb-4 border border-[#A88B4C]/20">
Về chúng tôi
</div>
<h2 className="text-3xl md:text-4xl font-bold mb-4">
Đi ngũ phát triển
</h2>
<p className="text-[#4A5555]">
Những con người đam lịch sử công nghệ chung tay xây dựng cỗ
máy thời gian kỹ thuật số.
</p>
</div>
<div className="flex mx-auto justify-center gap-12 flex-wrap">
{team.map((member, i) => (
<div key={i} className="p-6 text-center min-w-[264px]">
<div className="w-24 aspect-square mx-auto bg-gradient-to-tr from-[#A88B4C]/20 to-[#2D3A3A]/20 rounded-full mb-4 flex items-center justify-center overflow-hidden">
<Image
src={member.avatar}
alt={member.name}
width={96}
height={96}
className="w-full h-full object-cover object-center rounded-full"
/>
</div>
<h3 className="font-bold text-lg text-[#2D3A3A]">
{member.name}
</h3>
<p className="text-xs font-bold text-[#A88B4C] uppercase tracking-wider my-2">
{member.role}
</p>
<p className="text-sm text-[#4A5555]">{member.desc}</p>
</div>
))}
</div>
</section>
</main>
{/* --- PHẦN 4: GÓP Ý & LIÊN HỆ --- */}
<section className="relative mt-8 mb-16 w-full">
<div className="flex flex-col lg:flex-row justify-between gap-10 border rounded-2xl p-8 bg-[#FDFBF7]/80 backdrop-blur-sm border-[#A88B4C]/20">
{/* Box Text */}
<div className="lg:w-1/4 text-center lg:text-left flex flex-col justify-center">
<h2 className="text-2xl font-bold text-gray-900 mb-3">
Góp ý cho chúng tôi!
</h2>
<p className="text-sm text-gray-500 leading-relaxed">
Đăng nhận tin tức mới nhất hoặc đ lại ý kiến đóng góp giúp hệ
thống hoàn thiện hơn.
</p>
</div>
{/* Box Form Nhập Liệu (Dòng trên - Dòng dưới) */}
<div className="flex-1 w-full max-w-3xl flex flex-col gap-4">
<input
type="email"
placeholder="Email của bạn..."
className="w-full px-5 py-3.5 text-gray-700 bg-gray-50 border border-gray-200 rounded-xl focus:outline-none focus:bg-white focus:border-[#FFDE00] focus:ring-4 focus:ring-[#FFDE00]/20 transition-all text-sm placeholder:text-gray-400"
/>
<textarea
placeholder="Nội dung góp ý của bạn..."
rows={3}
className="w-full px-5 py-3.5 text-gray-700 bg-gray-50 border border-gray-200 rounded-xl focus:outline-none focus:bg-white focus:border-[#FFDE00] focus:ring-4 focus:ring-[#FFDE00]/20 transition-all text-sm placeholder:text-gray-400 resize-none"
></textarea>
<div className="flex justify-end">
<button className="bg-[#FFDE00] hover:bg-[#F0D100] text-black font-bold uppercase tracking-wide px-8 py-3.5 rounded-xl transition-colors text-sm shadow-sm">
Gửi Góp Ý
</button>
</div>
</div>
{/* Box Socials */}
<div className="lg:w-auto flex flex-col items-center lg:items-start pl-0 lg:pl-8 border-t lg:border-t-0 lg:border-l border-gray-100 pt-8 lg:pt-0 justify-center">
<h3 className="text-lg font-bold text-gray-900 mb-5">Follow us</h3>
<div className="flex gap-4">
<a
href="https://www.youtube.com/@BlackCatStudio-mw2sq"
target="_blank"
rel="noopener noreferrer"
className="w-12 h-12 rounded-full bg-[#FF0000] flex items-center justify-center text-white hover:opacity-90 hover:-translate-y-1 transition-all shadow-lg group"
>
<svg className="w-6 h-6 fill-current" viewBox="0 0 24 24">
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" />
</svg>
</a>
</div>
</div>
</div>
</section>
{/* FOOTER */}
<footer className="border-t border-[#A88B4C]/20 bg-[#2D3A3A] text-white py-12 text-center w-full mt-auto rounded-2xl">
<div className="max-w-6xl mx-auto px-6 flex flex-col items-center">
<div className="text-2xl font-bold tracking-widest uppercase mb-4">
<span className="text-[#A88B4C]">Geo</span>History
</div>
<p className="text-gray-400 text-sm mb-4 max-w-md">
Bách khoa toàn thư bản đ số lịch sử. Kết nối quá khứ, thấu hiểu
hiện tại, kiến tạo tương lai.
</p>
<div className="text-xs text-gray-500">
&copy; {new Date().getFullYear()} GeoHistory Project. All rights
reserved.
</div>
</div>
</footer>
</div>
);
}

View File

@@ -0,0 +1,82 @@
'use client';
import { useState } from 'react';
const faqData = [
{
id: 1,
question: "1. Phần mềm này tương thích với những hệ điều hành nào?",
answer: "Hệ thống tương thích hoàn toàn với Windows 10/11, macOS 12 trở lên. Đối với môi trường máy chủ, chúng tôi hỗ trợ các bản phân phối Linux phổ biến như Ubuntu và Debian."
},
{
id: 2,
question: "2. Sự khác biệt giữa phiên bản Miễn phí và Trả phí là gì?",
answer: "Phiên bản trả phí cung cấp băng thông không giới hạn, hỗ trợ kỹ thuật ưu tiên 24/7, và quyền truy cập sớm vào các tính năng nâng cao. Bản miễn phí sẽ giới hạn một số tính năng xuất dữ liệu."
},
{
id: 3,
question: "3. Hệ thống hỗ trợ những phương thức kết nối nào?",
answer: "Chúng tôi hỗ trợ kết nối qua REST API, WebSocket cho dữ liệu thời gian thực và cung cấp sẵn SDK cho các ngôn ngữ phổ biến như TypeScript, Go."
},
{
id: 4,
question: "4. Làm thế nào để tôi có thể tích hợp vào dự án Next.js hiện tại?",
answer: "Bạn chỉ cần cài đặt package qua npm/yarn, thêm API Key vào file .env và gọi component Provider ở file layout.tsx gốc. Tài liệu chi tiết có sẵn trong mục Developer Docs."
},
{
id: 5,
question: "5. Dữ liệu của tôi được bảo mật như thế nào?",
answer: "Toàn bộ dữ liệu được mã hóa đầu cuối (End-to-End Encryption). Chúng tôi tuân thủ nghiêm ngặt các tiêu chuẩn bảo mật quốc tế và thường xuyên rà soát hệ thống để phòng chống các lỗ hổng bảo mật."
}
];
export default function Page() {
// Lưu index của câu hỏi đang được mở. Mặc định mở câu đầu tiên (index 0).
const [openIndex, setOpenIndex] = useState<number | null>(0);
const toggleFAQ = (index: number) => {
// Nếu click lại vào câu đang mở thì đóng nó, ngược lại thì mở câu mới
setOpenIndex(openIndex === index ? null : index);
};
return (
<div className="min-h-screen bg-white text-slate-900 py-16 px-4 sm:px-8">
<div className="max-w-4xl mx-auto">
<h1 className="text-4xl font-bold mb-10">FAQs</h1>
<div className="border-t border-slate-200">
{faqData.map((faq, index) => {
const isOpen = openIndex === index;
return (
<div key={faq.id} className="border-b border-slate-200">
<button
onClick={() => toggleFAQ(index)}
className="w-full py-6 flex justify-between items-center text-left focus:outline-none group"
>
<span className="text-lg font-bold group-hover:text-indigo-600 transition-colors">
{faq.question}
</span>
<span className="text-3xl font-light ml-4 text-indigo-600 shrink-0 leading-none">
{isOpen ? '' : '+'}
</span>
</button>
{/* Phần nội dung có hiệu ứng trượt */}
<div
className={`overflow-hidden transition-all duration-300 ease-in-out ${
isOpen ? 'max-h-96 opacity-100 pb-6' : 'max-h-0 opacity-0'
}`}
>
<p className="text-slate-600 text-base leading-relaxed pr-8">
{faq.answer}
</p>
</div>
</div>
);
})}
</div>
</div>
</div>
);
}

View File

@@ -8,7 +8,7 @@ import { fullDataUser } from "@/interface/admin";
import { UserMetaCardProps } from "@/interface/user"; import { UserMetaCardProps } from "@/interface/user";
import { apiGetCurrentUser, apiLogout } from "@/service/auth"; import { apiGetCurrentUser, apiLogout } from "@/service/auth";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { ListIcon } from "@/icons"; import { ListIcon, ShootingStarIcon } from "@/icons";
export default function UserDropdown() { export default function UserDropdown() {
const router = useRouter(); const router = useRouter();
@@ -152,6 +152,19 @@ export default function UserDropdown() {
</span> </span>
Nhà Sử Học Nhà Sử Học
</DropdownItem> </DropdownItem>
</li>
<li>
<DropdownItem
onItemClick={closeDropdown}
tag="a"
href="/user/role-upgrade"
className="flex items-center gap-3 px-3 py-2 font-medium text-gray-700 rounded-lg group text-theme-sm hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-white/5 dark:hover:text-gray-300"
>
<span className="menu-item-icon">
<ShootingStarIcon />
</span>
Về chúng tôi
</DropdownItem>
</li> </li>
{/* <li> {/* <li>
<DropdownItem <DropdownItem

View File

@@ -88,7 +88,7 @@ export default function ChatbotWidget({
}; };
return ( return (
<div className="fixed bottom-6 right-6 z-50"> <div className="fixed bottom-8 right-8 z-50">
{!isOpen && ( {!isOpen && (
<button <button
onClick={() => setIsOpen(true)} onClick={() => setIsOpen(true)}

View File

@@ -15,6 +15,7 @@ import {
PageIcon, PageIcon,
PieChartIcon, PieChartIcon,
PlugInIcon, PlugInIcon,
ShootingStarIcon,
TableIcon, TableIcon,
UserCircleIcon, UserCircleIcon,
} from "../icons/index"; } from "../icons/index";
@@ -53,36 +54,47 @@ const ALL_NAV_ITEMS: NavItem[] = [
name: "Tài Khoản", name: "Tài Khoản",
path: "/user/account", path: "/user/account",
}, },
]; ];
const OTHERS_ITEMS: NavItem[] = [ const OTHERS_ITEMS: NavItem[] = [
// {
// icon: <PieChartIcon />,
// name: "Charts",
// subItems: [
// { name: "Line Chart", path: "/line-chart", pro: false },
// { name: "Bar Chart", path: "/bar-chart", pro: false },
// ],
// },
// {
// icon: <BoxCubeIcon />,
// name: "UI Elements",
// subItems: [
// { name: "Alerts", path: "/alerts", pro: false },
// { name: "Avatar", path: "/avatars", pro: false },
// { name: "Badge", path: "/badge", pro: false },
// { name: "Buttons", path: "/buttons", pro: false },
// { name: "Images", path: "/images", pro: false },
// { name: "Videos", path: "/videos", pro: false },
// ],
// },
// {
// icon: <PlugInIcon />,
// name: "Authentication",
// subItems: [
// { name: "Sign In", path: "/signin", pro: false },
// { name: "Sign Up", path: "/signup", pro: false },
// ],
// },
{ {
icon: <PieChartIcon />, icon: <ShootingStarIcon />,
name: "Charts", name: "Về Chúng Tôi",
subItems: [ path: "/user/about-us",
{ name: "Line Chart", path: "/line-chart", pro: false },
{ name: "Bar Chart", path: "/bar-chart", pro: false },
],
}, },
{ {
icon: <BoxCubeIcon />, icon: <ShootingStarIcon />,
name: "UI Elements", name: "Hỗ trợ",
subItems: [ path: "/user/quick-qa",
{ name: "Alerts", path: "/alerts", pro: false },
{ name: "Avatar", path: "/avatars", pro: false },
{ name: "Badge", path: "/badge", pro: false },
{ name: "Buttons", path: "/buttons", pro: false },
{ name: "Images", path: "/images", pro: false },
{ name: "Videos", path: "/videos", pro: false },
],
},
{
icon: <PlugInIcon />,
name: "Authentication",
subItems: [
{ name: "Sign In", path: "/signin", pro: false },
{ name: "Sign Up", path: "/signup", pro: false },
],
}, },
]; ];
@@ -280,12 +292,12 @@ const AppSidebar: React.FC = () => {
</h2> </h2>
{renderMenuItems(ALL_NAV_ITEMS, "main")} {renderMenuItems(ALL_NAV_ITEMS, "main")}
</div> </div>
{/* <div> <div>
<h2 className={`mb-4 text-xs uppercase flex leading-[20px] text-gray-400 ${!isExpanded && !isHovered ? "lg:justify-center" : "justify-start"}`}> <h2 className={`mb-4 text-xs uppercase flex leading-[20px] text-gray-400 ${!isExpanded && !isHovered ? "lg:justify-center" : "justify-start"}`}>
{isExpanded || isHovered || isMobileOpen ? "Others" : <HorizontaLDots />} {isExpanded || isHovered || isMobileOpen ? "Others" : <HorizontaLDots />}
</h2> </h2>
{renderMenuItems(OTHERS_ITEMS, "others")} {renderMenuItems(OTHERS_ITEMS, "others")}
</div> */} </div>
</div> </div>
</nav> </nav>
</div> </div>