'use client';
import * as React from 'react';
import Link from 'next/link';
import { Check, Loader2, Monitor, Moon, Sun } from 'lucide-react';
import { useTheme } from 'next-themes';
import { toast } from 'sonner';
import { Button } from '@/components/ui/button';
import { useCustomTheme } from '@/lib/theme';
import { cn } from '@/lib/utils';
import { LanguageSwitcher } from '@/components/common/language-switcher';
import { useTranslations } from 'next-intl';
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/components/ui/breadcrumb';
function ThemeModeSection() {
const { theme, setTheme } = useTheme();
const t = useTranslations('settings.appearance');
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => {
setMounted(true);
}, []);
const modes = [
{ id: 'light', name: t('modeLight'), icon: Sun },
{ id: 'dark', name: t('modeDark'), icon: Moon },
{ id: 'system', name: t('modeSystem'), icon: Monitor },
];
if (!mounted) {
return (
{t('themeMode')}
{t('themeModeDesc')}
{modes.map((mode) => {
const Icon = mode.icon;
return (
);
})}
);
}
return (
{t('themeMode')}
{t('themeModeDesc')}
{modes.map((mode) => {
const Icon = mode.icon;
const isActive = theme === mode.id;
return (
);
})}
);
}
function InterfaceAppearanceSection() {
const {
themes,
currentThemeId,
setTheme: setCustomTheme,
isLoading,
} = useCustomTheme();
const { theme: mode } = useTheme();
const t = useTranslations('settings.appearance');
const [mounted, setMounted] = React.useState(false);
const [switching, setSwitching] = React.useState(null);
React.useEffect(() => {
setMounted(true);
}, []);
const handleSetTheme = (themeId: string) => {
if (switching === themeId) return;
setSwitching(themeId);
try {
setCustomTheme(themeId);
const themeName = themes.find((t) => t.id === themeId)?.name || themeId;
toast.success(t('switched', { name: themeName }));
} catch {
toast.error(t('switchFailed'));
} finally {
setSwitching(null);
}
};
const isDark =
mounted &&
(mode === 'dark' ||
(mode === 'system' &&
typeof window !== 'undefined' &&
window.matchMedia('(prefers-color-scheme: dark)').matches));
return (
{t('interface')}
{t('interfaceDesc')}
{isLoading ? (
) : (
{themes.map((theme) => {
const isActive =
currentThemeId === theme.id ||
(!currentThemeId && theme.id === 'default.css');
const isSwitching = switching === theme.id;
const colors = isDark ? theme.colors.dark : theme.colors.light;
return (
handleSetTheme(theme.id)}
className={cn(
'group relative cursor-pointer rounded-xl border transition-all overflow-hidden',
isActive
? 'border-primary ring-2 ring-primary/20'
: 'border-border hover:border-border/50 hover:shadow-md',
)}
>
{isActive && !isSwitching && (
)}
);
})}
)}
);
}
export function AppearanceMain() {
const t = useTranslations('settings');
const ta = useTranslations('settings.appearance');
return (
{t('title')}
{ta('breadcrumb')}
{ta('language')}
{ta('languageDesc')}
{ta('comingSoon')}
{ta('comingSoonBody')}
);
}