包含 webapp(Next.js 用户端)、webapp-back(Go 后端)、 antdesign(管理后台)、landingpage(营销落地页)、 数据库 SQL 和配置文件。
281 lines
13 KiB
TypeScript
281 lines
13 KiB
TypeScript
'use client';
|
|
|
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
import { useTheme } from '@/contexts/ThemeContext';
|
|
import { BookOpen, ShieldCheck, GraduationCap, MessageCircle, Headphones, Users, Briefcase, Mail, Newspaper } from 'lucide-react';
|
|
|
|
interface ResourceMenuProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
language: 'zh' | 'en';
|
|
top?: number;
|
|
}
|
|
|
|
export default function ResourceMenu({ isOpen, onClose, language, top = 64 }: ResourceMenuProps) {
|
|
const { theme } = useTheme();
|
|
const isDark = theme === 'dark';
|
|
|
|
const content = {
|
|
zh: {
|
|
docLearning: '文档与学习',
|
|
docs: '文档',
|
|
docsDesc: '阅读技术文档、智能合约参考和集成指南。',
|
|
docsBadge: '已更新',
|
|
trustSecurity: '信任与安全',
|
|
trustSecurityDesc: '查看审计、合规认证和我们的安全实践。',
|
|
helpSupport: '帮助与支持',
|
|
learningCenter: '学习中心',
|
|
learningCenterDesc: '教程与视频指南。',
|
|
communityForum: '社区论坛',
|
|
communityForumDesc: '提问与交流。',
|
|
contactSupport: '联系支持',
|
|
contactSupportDesc: '从我们的团队获得帮助。',
|
|
company: '公司',
|
|
aboutTeam: '关于团队',
|
|
aboutTeamDesc: '认识AssetX背后的团队。',
|
|
careers: '招聘',
|
|
careersDesc: '加入我们不断成长的团队。',
|
|
contactUs: '联系我们',
|
|
contactUsDesc: '合作与媒体咨询。',
|
|
pressMedia: '新闻媒体',
|
|
pressMediaDesc: '最新消息与品牌资产。',
|
|
latestUpdate: '最新更新:',
|
|
updateInfo: 'December 2025',
|
|
privacyPolicy: '隐私政策',
|
|
termsOfService: '服务条款',
|
|
},
|
|
en: {
|
|
docLearning: 'Documentation & Learning',
|
|
docs: 'Docs',
|
|
docsDesc: 'Read technical docs, smart contract references, and integration guides.',
|
|
docsBadge: 'Updated',
|
|
trustSecurity: 'Trust & Security',
|
|
trustSecurityDesc: 'Review audits, compliance attestations, and our security practices.',
|
|
helpSupport: 'Help & Support',
|
|
learningCenter: 'Learning Center',
|
|
learningCenterDesc: 'Tutorials & video guides.',
|
|
communityForum: 'Community Forum',
|
|
communityForumDesc: 'Ask questions & connect.',
|
|
contactSupport: 'Contact Support',
|
|
contactSupportDesc: 'Get help from our team.',
|
|
company: 'Company',
|
|
aboutTeam: 'About Team',
|
|
aboutTeamDesc: 'Meet the people behind AssetX.',
|
|
careers: 'Careers',
|
|
careersDesc: 'Join our growing team.',
|
|
contactUs: 'Contact Us',
|
|
contactUsDesc: 'Partnerships & media inquiries.',
|
|
pressMedia: 'Press & Media',
|
|
pressMediaDesc: 'Latest news & brand assets.',
|
|
latestUpdate: 'Latest Update:',
|
|
updateInfo: 'December 2025',
|
|
privacyPolicy: 'Privacy Policy',
|
|
termsOfService: 'Terms of Service',
|
|
},
|
|
};
|
|
|
|
const t = content[language];
|
|
|
|
const helpItems = [
|
|
{ Icon: GraduationCap, title: t.learningCenter, desc: t.learningCenterDesc },
|
|
{ Icon: MessageCircle, title: t.communityForum, desc: t.communityForumDesc },
|
|
{ Icon: Headphones, title: t.contactSupport, desc: t.contactSupportDesc },
|
|
];
|
|
|
|
const companyItems = [
|
|
{ Icon: Users, title: t.aboutTeam, desc: t.aboutTeamDesc },
|
|
{ Icon: Briefcase, title: t.careers, desc: t.careersDesc },
|
|
{ Icon: Mail, title: t.contactUs, desc: t.contactUsDesc },
|
|
{ Icon: Newspaper, title: t.pressMedia, desc: t.pressMediaDesc },
|
|
];
|
|
|
|
return (
|
|
<AnimatePresence>
|
|
{isOpen && (
|
|
<>
|
|
{/* Transparent backdrop for click-outside */}
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
transition={{ duration: 0.2 }}
|
|
className="fixed inset-0 z-40"
|
|
onClick={onClose}
|
|
/>
|
|
|
|
{/* Menu — centered card */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: -8, x: '-50%' }}
|
|
animate={{ opacity: 1, y: 0, x: '-50%' }}
|
|
exit={{ opacity: 0, y: -8, x: '-50%' }}
|
|
transition={{ duration: 0.25, ease: 'easeOut' }}
|
|
className={`fixed left-1/2 z-50 rounded-2xl border transition-colors ${
|
|
isDark ? 'bg-[#18181b] border-[#27272a]' : 'bg-white border-[#E5E7EB]'
|
|
}`}
|
|
style={{ top: top, width: '960px', boxShadow: '0px 20px 50px rgba(0,0,0,0.10)' }}
|
|
>
|
|
<div>
|
|
<div style={{ padding: '32px' }}>
|
|
|
|
{/* Three-column layout */}
|
|
<div className="flex gap-12">
|
|
|
|
{/* Left — Documentation & Learning (large cards) */}
|
|
<div className="flex flex-col gap-6 flex-shrink-0" style={{ width: '345px' }}>
|
|
<span className={`text-xs font-bold uppercase tracking-[1.2px] font-domine ${isDark ? 'text-[#52525b]' : 'text-[#9CA3AF]'}`}>
|
|
{t.docLearning}
|
|
</span>
|
|
|
|
{/* Docs card */}
|
|
<div
|
|
className={`p-5 rounded-2xl cursor-pointer transition-opacity hover:opacity-75 ${
|
|
isDark
|
|
? 'bg-[#27272a] outline outline-1 outline-[#3f3f46]'
|
|
: 'bg-[#F9FAFB] outline outline-1 outline-[#E5E7EB]'
|
|
}`}
|
|
style={{ outlineOffset: '-1px' }}
|
|
>
|
|
<div className="flex items-start gap-4">
|
|
<div
|
|
className="w-12 h-12 rounded-full flex items-center justify-center flex-shrink-0"
|
|
style={{ background: isDark ? '#ffffff' : '#000000' }}
|
|
>
|
|
<BookOpen size={24} color={isDark ? '#000000' : '#ffffff'} />
|
|
</div>
|
|
<div className="flex flex-col gap-1 flex-1">
|
|
<div className="flex items-center gap-2">
|
|
<span className={`font-bold text-lg font-domine leading-7 ${isDark ? 'text-[#fafafa]' : 'text-[#111827]'}`}>
|
|
{t.docs}
|
|
</span>
|
|
<div className="px-2 py-0.5 rounded flex items-center" style={{ background: '#D1FAE5' }}>
|
|
<span className="text-[10px] font-bold uppercase font-domine leading-none" style={{ color: '#047857' }}>
|
|
{t.docsBadge}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<p className="text-sm font-domine text-[#6B7280] leading-relaxed">{t.docsDesc}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Trust & Security card */}
|
|
<div
|
|
className={`p-5 rounded-2xl cursor-pointer transition-opacity hover:opacity-75 ${
|
|
isDark
|
|
? 'bg-[#27272a] outline outline-1 outline-[#3f3f46]'
|
|
: 'bg-[#F9FAFB] outline outline-1 outline-[#E5E7EB]'
|
|
}`}
|
|
style={{ outlineOffset: '-1px' }}
|
|
>
|
|
<div className="flex items-start gap-4">
|
|
<div
|
|
className="w-12 h-12 rounded-full flex items-center justify-center flex-shrink-0"
|
|
style={{
|
|
background: isDark ? '#052e16' : '#ffffff',
|
|
outline: '2px solid #10B981',
|
|
outlineOffset: '-2px',
|
|
}}
|
|
>
|
|
<ShieldCheck size={24} color="#059669" />
|
|
</div>
|
|
<div className="flex flex-col gap-1 flex-1">
|
|
<span className={`font-bold text-lg font-domine leading-7 ${isDark ? 'text-[#fafafa]' : 'text-[#111827]'}`}>
|
|
{t.trustSecurity}
|
|
</span>
|
|
<p className="text-sm font-domine text-[#6B7280] leading-relaxed">{t.trustSecurityDesc}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Middle — Help & Support */}
|
|
<div className="flex flex-col gap-6 flex-shrink-0" style={{ width: '227px' }}>
|
|
<span className={`text-xs font-bold uppercase tracking-[1.2px] font-domine ${isDark ? 'text-[#52525b]' : 'text-[#9CA3AF]'}`}>
|
|
{t.helpSupport}
|
|
</span>
|
|
<div className="flex flex-col gap-6">
|
|
{helpItems.map(({ Icon, title, desc }) => (
|
|
<div
|
|
key={title}
|
|
className={`flex items-start gap-4 cursor-pointer rounded-lg p-2 -mx-2 transition-colors ${
|
|
isDark ? 'hover:bg-[#27272a]' : 'hover:bg-[#F9FAFB]'
|
|
}`}
|
|
>
|
|
<div
|
|
className={`w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0 ${
|
|
isDark ? 'bg-[#27272a] outline outline-1 outline-[#3f3f46]' : 'bg-[#F9FAFB] outline outline-1 outline-[#F3F4F6]'
|
|
}`}
|
|
style={{ outlineOffset: '-1px' }}
|
|
>
|
|
<Icon size={20} color={isDark ? '#d1d5db' : '#111827'} />
|
|
</div>
|
|
<div className="flex flex-col gap-0.5">
|
|
<span className={`text-sm font-bold font-domine leading-5 ${isDark ? 'text-[#fafafa]' : 'text-black'}`}>
|
|
{title}
|
|
</span>
|
|
<span className="text-xs font-domine text-[#6B7280] leading-4">{desc}</span>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Right — Company */}
|
|
<div className="flex flex-col gap-6 flex-1">
|
|
<span className={`text-xs font-bold uppercase tracking-[1.2px] font-domine ${isDark ? 'text-[#52525b]' : 'text-[#9CA3AF]'}`}>
|
|
{t.company}
|
|
</span>
|
|
<div className="flex flex-col gap-6">
|
|
{companyItems.map(({ Icon, title, desc }) => (
|
|
<div
|
|
key={title}
|
|
className={`flex items-start gap-4 cursor-pointer rounded-lg p-2 -mx-2 transition-colors ${
|
|
isDark ? 'hover:bg-[#27272a]' : 'hover:bg-[#F9FAFB]'
|
|
}`}
|
|
>
|
|
<div
|
|
className={`w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0 ${
|
|
isDark ? 'bg-[#27272a] outline outline-1 outline-[#3f3f46]' : 'bg-[#F9FAFB] outline outline-1 outline-[#F3F4F6]'
|
|
}`}
|
|
style={{ outlineOffset: '-1px' }}
|
|
>
|
|
<Icon size={20} color={isDark ? '#d1d5db' : '#111827'} />
|
|
</div>
|
|
<div className="flex flex-col gap-0.5">
|
|
<span className={`text-sm font-bold font-domine leading-5 ${isDark ? 'text-[#fafafa]' : 'text-black'}`}>
|
|
{title}
|
|
</span>
|
|
<span className="text-xs font-domine text-[#6B7280] leading-4">{desc}</span>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{/* Bottom bar */}
|
|
<div className={`mt-8 pt-6 border-t flex items-center justify-between ${isDark ? 'border-[#27272a]' : 'border-[#F3F4F6]'}`}>
|
|
<div className="text-xs font-domine">
|
|
<span className="text-[#9CA3AF]">{t.latestUpdate} </span>
|
|
<span className={`font-medium ${isDark ? 'text-[#fafafa]' : 'text-black'}`}>{t.updateInfo}</span>
|
|
</div>
|
|
<div className="flex gap-6">
|
|
<span className={`text-xs font-bold font-domine cursor-pointer transition-colors ${isDark ? 'text-[#6b7280] hover:text-[#fafafa]' : 'text-[#6B7280] hover:text-[#111827]'}`}>
|
|
{t.privacyPolicy}
|
|
</span>
|
|
<span className={`text-xs font-bold font-domine cursor-pointer transition-colors ${isDark ? 'text-[#6b7280] hover:text-[#fafafa]' : 'text-[#6B7280] hover:text-[#111827]'}`}>
|
|
{t.termsOfService}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
</>
|
|
)}
|
|
</AnimatePresence>
|
|
);
|
|
}
|