Refactor Admin and Settings UI to Ethereal Precision aesthetic and improve note import/export functionality
Some checks failed
Deploy to Production / Build and Deploy (push) Failing after 1m4s

This commit is contained in:
Antigravity
2026-05-03 12:51:25 +00:00
parent 635e516616
commit b611ec874d
27 changed files with 1151 additions and 1081 deletions

View File

@@ -1,11 +1,11 @@
'use client'
import { useState } from 'react'
import { SettingsSection, SettingToggle, SettingSelect } from '@/components/settings'
import { useLanguage } from '@/lib/i18n'
import { updateAISettings } from '@/app/actions/ai-settings'
import { toast } from 'sonner'
import { useRouter } from 'next/navigation'
import { Globe, Bell } from 'lucide-react'
interface GeneralSettingsClientProps {
initialSettings: {
@@ -25,7 +25,6 @@ export function GeneralSettingsClient({ initialSettings }: GeneralSettingsClient
const handleLanguageChange = async (value: string) => {
setLanguage(value)
await updateAISettings({ preferredLanguage: value as any })
if (value === 'auto') {
localStorage.removeItem('user-language')
toast.success(t('settings.languageAuto') || 'Language set to Auto')
@@ -34,7 +33,6 @@ export function GeneralSettingsClient({ initialSettings }: GeneralSettingsClient
setContextLanguage(value as any)
toast.success(t('profile.languageUpdateSuccess') || 'Language updated')
}
setTimeout(() => router.refresh(), 300)
}
@@ -51,63 +49,102 @@ export function GeneralSettingsClient({ initialSettings }: GeneralSettingsClient
}
return (
<div className="space-y-6">
<div className="space-y-8">
{/* Page title */}
<div>
<h1 className="text-3xl font-bold mb-2">{t('generalSettings.title')}</h1>
<p className="text-gray-600 dark:text-gray-400">
{t('generalSettings.description')}
</p>
<h1 className="text-2xl font-bold tracking-tight text-foreground">{t('generalSettings.title')}</h1>
<p className="text-muted-foreground mt-1">{t('generalSettings.description')}</p>
</div>
<SettingsSection
title={t('settings.language')}
icon={<span className="text-2xl">🌍</span>}
description={t('profile.languagePreferencesDescription')}
>
<SettingSelect
label={t('settings.language')}
description={t('settings.selectLanguage')}
value={language}
options={[
{ value: 'auto', label: t('profile.autoDetect') },
{ value: 'en', label: 'English' },
{ value: 'fr', label: 'Français' },
{ value: 'es', label: 'Español' },
{ value: 'de', label: 'Deutsch' },
{ value: 'fa', label: 'فارسی' },
{ value: 'it', label: 'Italiano' },
{ value: 'pt', label: 'Português' },
{ value: 'ru', label: 'Русский' },
{ value: 'zh', label: '中文' },
{ value: 'ja', label: '日本語' },
{ value: 'ko', label: '한국어' },
{ value: 'ar', label: 'العربية' },
{ value: 'hi', label: 'हिन्दी' },
{ value: 'nl', label: 'Nederlands' },
{ value: 'pl', label: 'Polski' },
]}
onChange={handleLanguageChange}
/>
</SettingsSection>
{/* 2-column card grid */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Language card */}
<div className="bg-card rounded-lg border border-border p-6 shadow-sm flex flex-col gap-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary shrink-0">
<Globe className="h-5 w-5" />
</div>
<div>
<h3 className="font-semibold text-foreground">{t('settings.language')}</h3>
<p className="text-sm text-muted-foreground">{t('settings.selectLanguage')}</p>
</div>
</div>
<div className="relative mt-2">
<select
value={language}
onChange={(e) => handleLanguageChange(e.target.value)}
className="w-full h-11 px-4 bg-muted border border-border rounded-lg text-foreground text-sm focus:ring-2 focus:ring-primary/20 focus:border-primary outline-none appearance-none cursor-pointer transition-colors"
>
<option value="auto">{t('profile.autoDetect')}</option>
<option value="en">English</option>
<option value="fr">Français</option>
<option value="es">Español</option>
<option value="de">Deutsch</option>
<option value="fa">فارسی</option>
<option value="it">Italiano</option>
<option value="pt">Português</option>
<option value="ru">Русский</option>
<option value="zh"></option>
<option value="ja"></option>
<option value="ko"></option>
<option value="ar">العربية</option>
<option value="hi">ि</option>
<option value="nl">Nederlands</option>
<option value="pl">Polski</option>
</select>
<div className="absolute right-4 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground">
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" /></svg>
</div>
</div>
</div>
<SettingsSection
title={t('settings.notifications')}
icon={<span className="text-2xl">🔔</span>}
description={t('settings.notificationsDesc')}
>
<SettingToggle
label={t('settings.emailNotifications')}
description={t('settings.emailNotificationsDesc')}
checked={emailNotifications}
onChange={handleEmailNotificationsChange}
/>
<SettingToggle
label={t('settings.desktopNotifications')}
description={t('settings.desktopNotificationsDesc')}
checked={desktopNotifications}
onChange={handleDesktopNotificationsChange}
/>
</SettingsSection>
{/* Notifications card */}
<div className="bg-card rounded-lg border border-border p-6 shadow-sm flex flex-col gap-4">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary shrink-0">
<Bell className="h-5 w-5" />
</div>
<div>
<h3 className="font-semibold text-foreground">{t('settings.notifications')}</h3>
<p className="text-sm text-muted-foreground">{t('settings.notificationsDesc')}</p>
</div>
</div>
<div className="mt-2 space-y-5">
{/* Email toggle */}
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-foreground">{t('settings.emailNotifications')}</p>
<p className="text-xs text-muted-foreground">{t('settings.emailNotificationsDesc')}</p>
</div>
<button
type="button"
role="switch"
aria-checked={emailNotifications}
onClick={() => handleEmailNotificationsChange(!emailNotifications)}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-primary/30 ${emailNotifications ? 'bg-primary' : 'bg-muted-foreground/30'}`}
>
<span className={`inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${emailNotifications ? 'translate-x-6' : 'translate-x-1'}`} />
</button>
</div>
{/* Desktop toggle */}
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-foreground">{t('settings.desktopNotifications')}</p>
<p className="text-xs text-muted-foreground">{t('settings.desktopNotificationsDesc')}</p>
</div>
<button
type="button"
role="switch"
aria-checked={desktopNotifications}
onClick={() => handleDesktopNotificationsChange(!desktopNotifications)}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-primary/30 ${desktopNotifications ? 'bg-primary' : 'bg-muted-foreground/30'}`}
>
<span className={`inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${desktopNotifications ? 'translate-x-6' : 'translate-x-1'}`} />
</button>
</div>
</div>
</div>
</div>
</div>
)
}