settings framework and section metadata keyed (487 -> 425)
SettingsSection now carries titleKey/descriptionKey instead of title/description, and the sidebar and content pane resolve them. The section arrays are module-level consts holding JSX content, so they cannot call a hook — the data holds keys and the renderers translate. Sidebar search matches the RESOLVED words, so it works in the language on screen. Capital K in titleKey is load-bearing: docs-check-settings.ts greps key:\s*'…' for route segments, and a lowercase title_key would have fed it twenty bogus paths. Verified 0 bogus, 26 declared, 20 offered, 0 missing. Section titles now share one key with the Spotlight rows that name the same section, per 'one key per meaning'. Two casings had to converge, so Settings shows Spotlight's: 'Change Password' now reads 'Change password'. Settings sidebar search placeholder was 'Search...'; it is now 'Search settings…', which is what the skeleton catalog already said and what distinguishes it from the global Spotlight.
This commit is contained in:
@@ -10,6 +10,7 @@ import { GoogleOAuthConfig } from './GoogleOAuthConfig';
|
||||
// import { GoogleAccount } from './GoogleAccount'; // hidden — email uses IMAP app password now
|
||||
import { ApifyConfig } from './ApifyConfig';
|
||||
import { DavAppPasswords } from './DavAppPasswords';
|
||||
import { useTranslation } from '@/lib/i18n';
|
||||
|
||||
const BASE_PATH = '/settings/integrations';
|
||||
|
||||
@@ -17,15 +18,15 @@ const enterpriseSections: SettingsSection[] = [
|
||||
{
|
||||
key: 'google-oauth',
|
||||
icon: KeyRound,
|
||||
title: 'Google OAuth',
|
||||
description: 'Client ID and secret for Google APIs',
|
||||
titleKey: 'settings.sections.googleOauth.label',
|
||||
descriptionKey: 'settings.sections.googleOauth.description',
|
||||
content: <GoogleOAuthConfig />,
|
||||
},
|
||||
{
|
||||
key: 'apify',
|
||||
icon: Wrench,
|
||||
title: 'Apify',
|
||||
description: 'API token for web scraping actors',
|
||||
titleKey: 'settings.sections.apify.label',
|
||||
descriptionKey: 'settings.sections.apify.description',
|
||||
content: <ApifyConfig />,
|
||||
},
|
||||
];
|
||||
@@ -39,14 +40,14 @@ const personalSections: SettingsSection[] = [
|
||||
// key: 'google-account',
|
||||
// icon: UserCircle,
|
||||
// title: 'Google Account',
|
||||
// description: 'Connect your Google account',
|
||||
// descriptionKey: 'settings.sections.apify.description',
|
||||
// content: <GoogleAccount />,
|
||||
// },
|
||||
{
|
||||
key: 'dav-app-passwords',
|
||||
icon: CalendarDays,
|
||||
title: 'Calendar & Contacts sync',
|
||||
description: 'Per-device passwords for CalDAV/CardDAV clients',
|
||||
titleKey: 'settings.sections.davSync.label',
|
||||
descriptionKey: 'settings.sections.davSync.description',
|
||||
content: <DavAppPasswords />,
|
||||
},
|
||||
];
|
||||
@@ -60,6 +61,7 @@ const tabForSection = (section: string | undefined) =>
|
||||
personalSections.some((s) => s.key === section) ? 'personal' : 'enterprise';
|
||||
|
||||
const IntegrationsSidebar = () => {
|
||||
const { t } = useTranslation();
|
||||
const { section } = useParams<{ section?: string }>();
|
||||
const navigate = useNavigate();
|
||||
const tab = tabForSection(section);
|
||||
@@ -77,22 +79,28 @@ const IntegrationsSidebar = () => {
|
||||
<div className="p-3 pb-2">
|
||||
<div className="flex items-center gap-2.5 rounded-lg px-3 py-2 text-sm font-medium bg-duck-teal/15 text-duck-teal">
|
||||
<Puzzle className="h-4 w-4" />
|
||||
Integrations
|
||||
{t('settings.nav.integrations')}
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-3 pb-2">
|
||||
<Tabs value={tab} onValueChange={setTab}>
|
||||
<TabsList className="w-full">
|
||||
<TabsTrigger value="enterprise" className="flex-1 cursor-pointer">
|
||||
Enterprise
|
||||
{t('settings.integrations.enterprise')}
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="personal" className="flex-1 cursor-pointer">
|
||||
Personal
|
||||
{t('settings.integrations.personal')}
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
</div>
|
||||
<SettingsSidebar basePath={BASE_PATH} icon={Puzzle} label="Integrations" sections={sections} hideHeader />
|
||||
<SettingsSidebar
|
||||
basePath={BASE_PATH}
|
||||
icon={Puzzle}
|
||||
labelKey="settings.nav.integrations"
|
||||
sections={sections}
|
||||
hideHeader
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user