feat: add translate
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { Mail, Users, MessageCircle, ChevronDown, Check, Heart, X } from 'lucide-react';
|
||||
import { Mail, Users, MessageCircle, ChevronDown, Check, Heart, X, Languages, HelpCircle } from 'lucide-react';
|
||||
import { useLanguage } from '../contexts/LanguageContext';
|
||||
|
||||
export default function Navbar() {
|
||||
const { language, setLanguage, t } = useLanguage();
|
||||
const [showContact, setShowContact] = useState(false);
|
||||
const [showReward, setShowReward] = useState(false);
|
||||
const [showLangMenu, setShowLangMenu] = useState(false);
|
||||
const [copied, setCopied] = useState(false);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
const langMenuRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const handleCopyQQ = async () => {
|
||||
await navigator.clipboard.writeText('1018282100');
|
||||
@@ -19,6 +23,9 @@ export default function Navbar() {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
||||
setShowContact(false);
|
||||
}
|
||||
if (langMenuRef.current && !langMenuRef.current.contains(event.target as Node)) {
|
||||
setShowLangMenu(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
@@ -37,8 +44,59 @@ export default function Navbar() {
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Right: Reward & Contact Buttons */}
|
||||
{/* Right: Actions */}
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Language Switcher */}
|
||||
<div className="relative" ref={langMenuRef}>
|
||||
<button
|
||||
onClick={() => setShowLangMenu(!showLangMenu)}
|
||||
className="flex items-center gap-2 px-3 py-2 hover:bg-gray-100 rounded-lg text-gray-700 text-sm font-medium transition-colors"
|
||||
title="Switch Language"
|
||||
>
|
||||
<Languages size={18} />
|
||||
<span className="hidden sm:inline">{language === 'en' ? 'English' : '简体中文'}</span>
|
||||
<ChevronDown size={14} className={`transition-transform duration-200 ${showLangMenu ? 'rotate-180' : ''}`} />
|
||||
</button>
|
||||
|
||||
{showLangMenu && (
|
||||
<div className="absolute right-0 top-full mt-2 w-32 bg-white rounded-xl shadow-lg border border-gray-200 py-1 z-50 animate-in fade-in slide-in-from-top-2 duration-200">
|
||||
<button
|
||||
onClick={() => {
|
||||
setLanguage('en');
|
||||
setShowLangMenu(false);
|
||||
}}
|
||||
className={`w-full flex items-center justify-between px-4 py-2 text-sm transition-colors hover:bg-gray-50 ${language === 'en' ? 'text-blue-600 font-medium' : 'text-gray-700'}`}
|
||||
>
|
||||
English
|
||||
{language === 'en' && <Check size={14} />}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
setLanguage('zh');
|
||||
setShowLangMenu(false);
|
||||
}}
|
||||
className={`w-full flex items-center justify-between px-4 py-2 text-sm transition-colors hover:bg-gray-50 ${language === 'zh' ? 'text-blue-600 font-medium' : 'text-gray-700'}`}
|
||||
>
|
||||
简体中文
|
||||
{language === 'zh' && <Check size={14} />}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* User Guide Button */}
|
||||
<button
|
||||
id="guide-button"
|
||||
className="flex items-center gap-2 px-3 py-2 hover:bg-gray-100 rounded-lg text-gray-700 text-sm font-medium transition-colors"
|
||||
onClick={() => {
|
||||
// This will be handled in App.tsx via a custom event or shared state
|
||||
window.dispatchEvent(new CustomEvent('start-user-guide'));
|
||||
}}
|
||||
>
|
||||
<HelpCircle size={18} />
|
||||
<span className="hidden sm:inline">{t.common.guide}</span>
|
||||
</button>
|
||||
|
||||
{/* Reward Button */}
|
||||
<div className="relative">
|
||||
<button
|
||||
@@ -46,7 +104,7 @@ export default function Navbar() {
|
||||
className="flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-rose-500 to-pink-500 hover:from-rose-600 hover:to-pink-600 rounded-lg text-white text-sm font-medium transition-all shadow-sm hover:shadow-md"
|
||||
>
|
||||
<Heart size={14} className="fill-white" />
|
||||
<span>赞赏</span>
|
||||
<span>{t.common.reward}</span>
|
||||
</button>
|
||||
|
||||
{/* Reward Modal */}
|
||||
@@ -60,7 +118,7 @@ export default function Navbar() {
|
||||
onClick={e => e.stopPropagation()}
|
||||
>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<span className="text-lg font-bold text-gray-900">微信赞赏码</span>
|
||||
<span className="text-lg font-bold text-gray-900">{t.navbar.rewardTitle}</span>
|
||||
<button
|
||||
onClick={() => setShowReward(false)}
|
||||
className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
@@ -71,12 +129,12 @@ export default function Navbar() {
|
||||
<div className="flex flex-col items-center">
|
||||
<img
|
||||
src="https://cdn.texpixel.com/public/rewardcode.png"
|
||||
alt="微信赞赏码"
|
||||
alt={t.navbar.rewardTitle}
|
||||
className="w-64 h-64 object-contain rounded-lg shadow-sm"
|
||||
/>
|
||||
<p className="text-sm text-gray-500 text-center mt-4">
|
||||
感谢您的支持与鼓励 ❤️<br />
|
||||
<span className="text-xs text-gray-400 mt-1 block">您的支持是我们持续更新的动力</span>
|
||||
{t.navbar.rewardThanks}<br />
|
||||
<span className="text-xs text-gray-400 mt-1 block">{t.navbar.rewardSubtitle}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -91,7 +149,7 @@ export default function Navbar() {
|
||||
className="flex items-center gap-2 px-4 py-2 bg-gray-100 hover:bg-gray-200 rounded-lg text-gray-700 text-sm font-medium transition-colors"
|
||||
>
|
||||
<MessageCircle size={14} />
|
||||
<span>Contact Us</span>
|
||||
<span>{t.common.contactUs}</span>
|
||||
<ChevronDown
|
||||
size={14}
|
||||
className={`transition-transform duration-200 ${showContact ? 'rotate-180' : ''}`}
|
||||
@@ -109,7 +167,7 @@ export default function Navbar() {
|
||||
<Mail size={16} className="text-blue-600" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs text-gray-500">Email</div>
|
||||
<div className="text-xs text-gray-500">{t.common.email}</div>
|
||||
<div className="text-sm font-medium text-gray-900">yogecoder@gmail.com</div>
|
||||
</div>
|
||||
</a>
|
||||
@@ -126,7 +184,7 @@ export default function Navbar() {
|
||||
</div>
|
||||
<div>
|
||||
<div className={`text-xs transition-colors ${copied ? 'text-green-600 font-medium' : 'text-gray-500'}`}>
|
||||
{copied ? 'Copied!' : 'QQ Group (Click to Copy)'}
|
||||
{copied ? t.common.copied : t.common.qqGroup}
|
||||
</div>
|
||||
<div className="text-sm font-medium text-gray-900">1018282100</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user