localization

This commit is contained in:
2026-02-17 21:36:12 +00:00
parent 3733e99ba8
commit 680f623b41
17 changed files with 341 additions and 71 deletions
@@ -1,51 +1,56 @@
import { useState, useEffect, useRef, useMemo } from 'react';
import { Search, User, Lock, Globe, ListChecks, Palette } from 'lucide-react';
import { Search, User, Lock, Globe, ListChecks } from 'lucide-react';
import { Input } from '@/components/ui/input';
import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@/components/ui/accordion';
import { Card } from '@/components/Card';
import { useTranslation } from '@/lib/i18n';
import { UserData } from './UserData';
import { ChangePassword } from './ChangePassword';
import { Languages } from './Languages';
import { TaskDefaults } from './TaskDefaults';
const sections = [
{
key: 'profile',
icon: User,
title: 'Profile',
description: 'Update your name and avatar.',
content: <UserData />,
},
{
key: 'change-password',
icon: Lock,
title: 'Change Password',
description: 'Update your account password.',
content: <ChangePassword />,
},
{
key: 'tasks',
icon: ListChecks,
title: 'Tasks',
description: 'Default model for file browser tasks.',
content: <TaskDefaults />,
},
{
key: 'languages',
icon: Globe,
title: 'Languages',
description: 'Set your spoken languages and translation preferences.',
content: <Languages />,
},
];
const allKeys = sections.map((s) => s.key);
export const ProfileSettings = () => {
const { t } = useTranslation();
const [search, setSearch] = useState('');
const [expanded, setExpanded] = useState<string[]>([]);
const sectionRefs = useRef<Record<string, HTMLDivElement | null>>({});
const sections = useMemo(
() => [
{
key: 'profile',
icon: User,
title: t('settings.profile.sections.profileTitle'),
description: t('settings.profile.sections.profileDescription'),
content: <UserData />,
},
{
key: 'change-password',
icon: Lock,
title: t('settings.profile.sections.changePasswordTitle'),
description: t('settings.profile.sections.changePasswordDescription'),
content: <ChangePassword />,
},
{
key: 'tasks',
icon: ListChecks,
title: t('settings.profile.sections.tasksTitle'),
description: t('settings.profile.sections.tasksDescription'),
content: <TaskDefaults />,
},
{
key: 'languages',
icon: Globe,
title: t('settings.profile.sections.languagesTitle'),
description: t('settings.profile.sections.languagesDescription'),
content: <Languages />,
},
],
[t],
);
const allKeys = useMemo(() => sections.map((s) => s.key), [sections]);
const matchingKeys = useMemo(() => {
if (!search) return allKeys;
const query = search.toLowerCase();
@@ -55,7 +60,7 @@ export const ProfileSettings = () => {
return (el?.textContent?.toLowerCase() ?? '').includes(query);
})
.map((s) => s.key);
}, [search]);
}, [search, allKeys, sections]);
useEffect(() => {
if (search) setExpanded(matchingKeys);
@@ -67,7 +72,7 @@ export const ProfileSettings = () => {
<div className="relative mb-6">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-duck-dark/40" />
<Input
placeholder="Search settings..."
placeholder={t('settings.profile.searchPlaceholder')}
value={search}
onChange={(ev) => setSearch(ev.target.value)}
className="pl-9"