import { useEffect, useMemo, useRef, useState } from 'react' import { useLocation, useSearchParams } from 'react-router-dom' const DESIGNER_QUERY_KEY = 'design' interface UseDesignerStateOptions { currentLanguage?: string supportedLanguages?: string[] } function serializeValue(value: T | null | undefined) { if (value === undefined) { return '__undefined__' } if (value === null) { return '__null__' } try { return JSON.stringify(value) } catch { return '__unserializable__' } } function normalizeLanguageKey(language?: string) { if (!language) { return 'tr' } return language.toLowerCase().split('-')[0] } function cloneValue(value: T): T { try { return JSON.parse(JSON.stringify(value)) as T } catch { return value } } export function useDesignerState( pageKey: string, initialContent: T | null, options?: UseDesignerStateOptions, ) { const location = useLocation() const [searchParams] = useSearchParams() const isDesignMode = searchParams.get(DESIGNER_QUERY_KEY) === '1' || location.pathname.endsWith('/designer') const currentLanguage = normalizeLanguageKey(options?.currentLanguage) const supportedLanguages = useMemo(() => { const base = (options?.supportedLanguages ?? [currentLanguage]).map((language) => normalizeLanguageKey(language), ) if (!base.includes(currentLanguage)) { return [currentLanguage, ...base] } return Array.from(new Set(base)) }, [currentLanguage, options?.supportedLanguages]) const [selectedLanguage, setSelectedLanguage] = useState(currentLanguage) const [byLanguage, setByLanguage] = useState>({}) const [selectedBlockId, setSelectedBlockId] = useState(null) const seededDefaultsRef = useRef>({}) const selectedLanguagePrefix = normalizeLanguageKey(selectedLanguage) const content = byLanguage[selectedLanguage] ?? byLanguage[selectedLanguagePrefix] ?? byLanguage[currentLanguage] ?? initialContent ?? null useEffect(() => { setSelectedLanguage(normalizeLanguageKey(currentLanguage)) }, [currentLanguage]) useEffect(() => { if (!initialContent) { return } const nextSerializedInitial = serializeValue(initialContent) setByLanguage((prev) => { const currentValue = prev[currentLanguage] const currentSerialized = serializeValue(currentValue) const previousSeed = seededDefaultsRef.current[currentLanguage] if (currentValue !== undefined && previousSeed !== undefined && currentSerialized !== previousSeed) { return prev } if (currentSerialized === nextSerializedInitial) { seededDefaultsRef.current[currentLanguage] = nextSerializedInitial return prev } seededDefaultsRef.current[currentLanguage] = nextSerializedInitial return { ...prev, [currentLanguage]: cloneValue(initialContent), } }) if (!isDesignMode && selectedBlockId !== null) { setSelectedBlockId(null) } }, [currentLanguage, initialContent, isDesignMode, selectedBlockId]) useEffect(() => { if (!isDesignMode || !initialContent) { return } const normalizedSelectedLanguage = normalizeLanguageKey(selectedLanguage) const hasSelectedLanguageContent = byLanguage[normalizedSelectedLanguage] !== undefined || byLanguage[selectedLanguage] !== undefined if (hasSelectedLanguageContent) { return } // If selected language has no saved value, initialize it from the current translated defaults. seededDefaultsRef.current[normalizedSelectedLanguage] = serializeValue(initialContent) setByLanguage((prev) => ({ ...prev, [normalizedSelectedLanguage]: cloneValue(initialContent), })) }, [byLanguage, initialContent, isDesignMode, selectedLanguage]) const setContent = (updater: (current: T | null) => T | null) => { setByLanguage((prev) => { const current = prev[selectedLanguage] ?? prev[normalizeLanguageKey(selectedLanguage)] ?? prev[currentLanguage] ?? initialContent ?? null const next = updater(current) if (!next) { return prev } return { ...prev, [normalizeLanguageKey(selectedLanguage)]: cloneValue(next), } }) } const resetContent = () => { if (!initialContent) { return } const normalizedSelectedLanguage = normalizeLanguageKey(selectedLanguage) seededDefaultsRef.current[normalizedSelectedLanguage] = serializeValue(initialContent) setByLanguage((prev) => ({ ...prev, [normalizedSelectedLanguage]: cloneValue(initialContent), })) } return { content, isDesignMode, selectedBlockId, selectedLanguage, supportedLanguages, setContent, setSelectedBlockId, setSelectedLanguage, resetContent, } }