'use client' import React, {ChangeEvent, useCallback, useContext, useEffect, useMemo} from 'react'; import {Baseline, CaseSensitive, Eye, Indent, Palette, Type} from 'lucide-react'; import {useTranslations} from '@/lib/i18n'; import SelectBox from "@/components/form/SelectBox"; import Button from "@/components/ui/Button"; import {AlertContext, AlertContextProps} from "@/context/AlertContext"; interface UserEditorSettingsProps { settings: EditorDisplaySettings; onSettingsChange: (settings: EditorDisplaySettings) => void; } export interface EditorDisplaySettings { zoomLevel: number; indent: number; lineHeight: number; theme: 'clair' | 'sombre' | 'sépia'; fontFamily: 'lora' | 'serif' | 'sans-serif' | 'monospace'; maxWidth: number; focusMode: boolean; } const zoomLabels = ['Très petit', 'Petit', 'Normal', 'Grand', 'Très grand'] as const; const fontSizes = [14, 16, 18, 20, 22] as const; const themes = ['clair', 'sombre', 'sépia'] as const; function isValidFontFamily(value: string): value is EditorDisplaySettings['fontFamily'] { return value === 'lora' || value === 'serif' || value === 'sans-serif' || value === 'monospace'; } const defaultSettings: EditorDisplaySettings = { zoomLevel: 3, indent: 30, lineHeight: 1.5, theme: 'sombre', fontFamily: 'lora', maxWidth: 768, focusMode: false }; export default function UserEditorSettings({settings, onSettingsChange}: UserEditorSettingsProps): React.JSX.Element { const t = useTranslations(); const {errorMessage}: AlertContextProps = useContext(AlertContext); const handleSettingChange = useCallback(( key: K, value: EditorDisplaySettings[K] ): void => { onSettingsChange({...settings, [key]: value}); }, [settings, onSettingsChange]); const resetToDefaults = useCallback((): void => { onSettingsChange(defaultSettings); }, [onSettingsChange]); const zoomOptions = useMemo((): { value: string; label: string }[] => zoomLabels.map((label: typeof zoomLabels[number], index: number): { value: string; label: string } => ({ value: (index + 1).toString(), label: `${t(`userEditorSettings.zoom.${label}`)} (${fontSizes[index]}px)` })) , [t]); const themeButtons = useMemo((): { key: typeof themes[number]; isActive: boolean; className: string }[] => themes.map((theme: typeof themes[number]): { key: typeof themes[number]; isActive: boolean; className: string } => ({ key: theme, isActive: settings.theme === theme, className: `p-2.5 rounded-xl border capitalize transition-colors duration-150 font-medium ${ settings.theme === theme ? 'bg-secondary text-primary border-primary' : 'bg-secondary border-secondary text-muted hover:text-text-primary' }` })) , [settings.theme]); useEffect((): void => { try { const savedSettings: string | null = localStorage.getItem('userEditorSettings'); if (savedSettings) { const parsed: Partial = JSON.parse(savedSettings); if (parsed && typeof parsed === 'object') { onSettingsChange({...defaultSettings, ...parsed}); } } } catch (e: unknown) { onSettingsChange(defaultSettings); } }, [onSettingsChange]); useEffect((): () => void => { const timeoutId: ReturnType = setTimeout((): void => { try { localStorage.setItem('userEditorSettings', JSON.stringify(settings)); } catch (e: unknown) { if (e instanceof Error) { errorMessage(t('userEditorSettings.saveError')); } else { errorMessage(t('userEditorSettings.unknownError')); } } }, 100); return (): void => clearTimeout(timeoutId); }, [settings]); return (

{t("userEditorSettings.displayPreferences")}

): void => { handleSettingChange('zoomLevel', Number(e.target.value)) }} data={zoomOptions} />
): void => handleSettingChange('indent', Number(e.target.value))} className="w-full accent-primary" />
{t("userEditorSettings.indentNone")} {settings.indent}px {t("userEditorSettings.indentMax")}
): void => handleSettingChange('lineHeight', Number(e.target.value))} data={[ {value: "1.2", label: t("userEditorSettings.lineHeightCompact")}, {value: "1.5", label: t("userEditorSettings.lineHeightNormal")}, {value: "1.75", label: t("userEditorSettings.lineHeightSpaced")}, {value: "2", label: t("userEditorSettings.lineHeightDouble")} ]} />
): void => { const fontValue: string = e.target.value; if (isValidFontFamily(fontValue)) { handleSettingChange('fontFamily', fontValue); } }} data={[ {value: "lora", label: t("userEditorSettings.fontLora")}, {value: "serif", label: t("userEditorSettings.fontSerif")}, {value: "sans-serif", label: t("userEditorSettings.fontSansSerif")}, {value: "monospace", label: t("userEditorSettings.fontMonospace")} ]} />
): void => handleSettingChange('maxWidth', Number(e.target.value))} className="w-full accent-primary" />
{t("userEditorSettings.maxWidthNarrow")} {settings.maxWidth}px {t("userEditorSettings.maxWidthWide")}
{themeButtons.map((themeBtn: { key: typeof themes[number]; isActive: boolean; className: string }) => ( ))}
); }