quick question, answer
All checks were successful
Build and Release / release (push) Successful in 33s
All checks were successful
Build and Release / release (push) Successful in 33s
This commit is contained in:
82
src/app/user/quick-qa/page.tsx
Normal file
82
src/app/user/quick-qa/page.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -54,41 +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[] = [
|
||||||
|
// {
|
||||||
|
// 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: <ShootingStarIcon />,
|
icon: <ShootingStarIcon />,
|
||||||
name: "Về Chúng Tôi",
|
name: "Về Chúng Tôi",
|
||||||
path: "/user/about-us",
|
path: "/user/about-us",
|
||||||
},
|
},
|
||||||
];
|
|
||||||
|
|
||||||
const OTHERS_ITEMS: NavItem[] = [
|
|
||||||
{
|
{
|
||||||
icon: <PieChartIcon />,
|
icon: <ShootingStarIcon />,
|
||||||
name: "Charts",
|
name: "Hỗ trợ",
|
||||||
subItems: [
|
path: "/user/quick-qa",
|
||||||
{ 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 },
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -286,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>
|
||||||
|
|||||||
Reference in New Issue
Block a user