feat: Tích hợp bộ chuyển đổi chủ đề và ngôn ngữ vào thanh điều hướng, cập nhật hook i18n, và đặt chủ đề tối làm mặc định.

This commit is contained in:
Ho Ngoc Hai
2026-01-04 22:42:58 +07:00
parent d2da32124c
commit b00b5eaaa1
4 changed files with 21 additions and 14 deletions

View File

@@ -78,7 +78,9 @@ export function NavigationHeader({ className }: { className?: string }) {
</nav>
{/* EN: CTA Button / VI: Button CTA */}
<div className="hidden md:flex items-center">
<div className="hidden md:flex items-center gap-3">
<ThemeToggle />
<LanguageSwitcher />
<Button
variant="ghost"
size="sm"
@@ -134,6 +136,12 @@ export function NavigationHeader({ className }: { className?: string }) {
>
Try Grok
</Button>
{/* EN: Theme and Language Controls / VI: Controls theme và ngôn ngữ */}
<div className="flex items-center gap-3 pt-4 border-t border-white/5">
<ThemeToggle />
<LanguageSwitcher />
</div>
</div>
)}
</div>

View File

@@ -5,7 +5,7 @@ import { useRouter } from 'next/navigation';
import { useAuthStore } from '../../../stores/auth-store';
import { Role } from '@goodgo/types';
import { Card } from '../components/ui/card';
import { Button } from '../ui/button';
import { Button } from '../components/ui/button';
/**
* EN: Auth Guard Props
@@ -121,7 +121,7 @@ export function AuthGuard({
<Button onClick={() => router.back()}>
Go Back
</Button>
<Button variant="outline" onClick={() => router.push('/dashboard')}>
<Button variant="ghost" onClick={() => router.push('/dashboard')}>
Dashboard
</Button>
</div>

View File

@@ -37,7 +37,7 @@ export type LanguageCode = typeof languages[number]['code'];
* ```
*/
export function LanguageSwitcher() {
const { locale: currentLocale, setLocale } = useTranslation();
const { locale: currentLocale, setLocale } = useI18n();
const currentLanguage = languages.find(lang => lang.code === currentLocale) || languages[0];
@@ -104,7 +104,7 @@ export function LanguageSwitcher() {
* ```
*/
export function LanguageSwitcherCompact() {
const { locale: currentLocale, setLocale } = useTranslation();
const { locale: currentLocale, setLocale } = useI18n();
const currentLanguage = languages.find(lang => lang.code === currentLocale) || languages[0];
const toggleLanguage = () => {

View File

@@ -58,17 +58,17 @@ const applyTheme = (theme: 'light' | 'dark') => {
* @param children - Child components / Components con
*/
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setThemeState] = useState<ThemeMode>('system');
const [theme, setThemeState] = useState<ThemeMode>('dark');
const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>(() => {
if (typeof window === 'undefined') return 'dark';
// EN: Load from localStorage or default to system
// VI: Load từ localStorage hoặc mặc định là system
// EN: Load from localStorage or default to dark
// VI: Load từ localStorage hoặc mặc định là dark
const stored = localStorage.getItem('theme') as ThemeMode | null;
if (stored && (stored === 'light' || stored === 'dark' || stored === 'system')) {
return stored === 'system' ? getSystemTheme() : stored;
}
return getSystemTheme();
return 'dark';
});
// EN: Initialize theme from localStorage
@@ -83,11 +83,10 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
setResolvedTheme(resolved);
applyTheme(resolved);
} else {
// EN: Default to system preference
// VI: Mặc định theo preference hệ thống
const systemTheme = getSystemTheme();
setResolvedTheme(systemTheme);
applyTheme(systemTheme);
// EN: Default to dark theme
// VI: Mặc định là dark theme
setResolvedTheme('dark');
applyTheme('dark');
}
}, []);