галочка сохранения инпутов
This commit is contained in:
@@ -1,13 +1,44 @@
|
||||
import { Input } from '@/component/ui/input'
|
||||
import { ElementDefinition } from '@/entitiy/element/model/interface'
|
||||
import { CellsBadge } from '@/entitiy/element/ui/cellsBadge'
|
||||
import { ExtraSettingsBadge } from '@/entitiy/element/ui/extraSettingsBadge'
|
||||
import { Type } from 'lucide-react'
|
||||
import { Save, SaveOff, Type } from 'lucide-react'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
interface TextConfig {
|
||||
placeholder?: string
|
||||
required?: boolean
|
||||
targetCells: any[]
|
||||
name?: string
|
||||
id?: string // Добавляем id для совместимости с TemplateElement
|
||||
}
|
||||
|
||||
// Утилиты для работы с localStorage
|
||||
const getLocalStorageKey = (type: string, id: string) => `${type}_${id}`
|
||||
|
||||
const saveToLocalStorage = (key: string, value: string) => {
|
||||
try {
|
||||
localStorage.setItem(key, value)
|
||||
} catch (error) {
|
||||
console.warn('Failed to save to localStorage:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const getFromLocalStorage = (key: string): string => {
|
||||
try {
|
||||
return localStorage.getItem(key) || ''
|
||||
} catch (error) {
|
||||
console.warn('Failed to get from localStorage:', error)
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
const removeFromLocalStorage = (key: string) => {
|
||||
try {
|
||||
localStorage.removeItem(key)
|
||||
} catch (error) {
|
||||
console.warn('Failed to remove from localStorage:', error)
|
||||
}
|
||||
}
|
||||
|
||||
export const textDefinition: ElementDefinition<TextConfig, string> = {
|
||||
@@ -21,6 +52,14 @@ export const textDefinition: ElementDefinition<TextConfig, string> = {
|
||||
targetCells: [],
|
||||
name: '',
|
||||
},
|
||||
getInitialValue: config => {
|
||||
// Используем id из config (который приходит из TemplateElement)
|
||||
if (config.id) {
|
||||
const key = getLocalStorageKey('text', config.id)
|
||||
return getFromLocalStorage(key)
|
||||
}
|
||||
return ''
|
||||
},
|
||||
mapToCells: config => config.targetCells || [],
|
||||
mapToCellValues: (config, value) => {
|
||||
const cells = config.targetCells || []
|
||||
@@ -38,20 +77,114 @@ export const textDefinition: ElementDefinition<TextConfig, string> = {
|
||||
<Input placeholder={config.placeholder} className="w-full" />
|
||||
</div>
|
||||
),
|
||||
Render: ({ config, value, onChange }) => (
|
||||
<div className="space-y-1">
|
||||
{config.name && (
|
||||
<label className="text-sm font-medium text-gray-900">
|
||||
{config.name}
|
||||
{config.required && <span className="ml-1 text-red-500">*</span>}
|
||||
</label>
|
||||
)}
|
||||
<Input
|
||||
placeholder={config.placeholder}
|
||||
value={value || ''}
|
||||
onChange={e => onChange?.(e.target.value)}
|
||||
required={config.required}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
Render: ({ config, value, onChange }) => {
|
||||
const [localStorageEnabled, setLocalStorageEnabled] = useState(false)
|
||||
const [currentValue, setCurrentValue] = useState(value || '')
|
||||
|
||||
// Инициализация состояния localStorage из сохраненных данных
|
||||
useEffect(() => {
|
||||
if (config.id) {
|
||||
const key = getLocalStorageKey('text', config.id)
|
||||
const savedValue = getFromLocalStorage(key)
|
||||
|
||||
// Если есть сохраненное значение, включаем localStorage и загружаем его
|
||||
if (savedValue) {
|
||||
setLocalStorageEnabled(true)
|
||||
if (savedValue !== currentValue) {
|
||||
setCurrentValue(savedValue)
|
||||
onChange?.(savedValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [config.id])
|
||||
|
||||
// Синхронизация внешнего значения
|
||||
useEffect(() => {
|
||||
if (value !== currentValue) {
|
||||
setCurrentValue(value || '')
|
||||
}
|
||||
}, [value])
|
||||
|
||||
const handleValueChange = (newValue: string) => {
|
||||
setCurrentValue(newValue)
|
||||
onChange?.(newValue)
|
||||
|
||||
// Сохранение в localStorage если включено
|
||||
if (localStorageEnabled && config.id) {
|
||||
const key = getLocalStorageKey('text', config.id)
|
||||
saveToLocalStorage(key, newValue)
|
||||
}
|
||||
}
|
||||
|
||||
const handleLocalStorageToggle = () => {
|
||||
const newEnabled = !localStorageEnabled
|
||||
setLocalStorageEnabled(newEnabled)
|
||||
|
||||
if (config.id) {
|
||||
const key = getLocalStorageKey('text', config.id)
|
||||
|
||||
if (newEnabled) {
|
||||
// Включаем localStorage - сохраняем текущее значение
|
||||
saveToLocalStorage(key, currentValue)
|
||||
} else {
|
||||
// Выключаем localStorage - удаляем сохраненное значение
|
||||
removeFromLocalStorage(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative space-y-1">
|
||||
{/* Бейджи в правом верхнем углу */}
|
||||
<div className="absolute right-0 top-0 z-10 flex items-center gap-1">
|
||||
{/* Галочка сохранения */}
|
||||
{config.id && (
|
||||
<div className="group/save">
|
||||
<button
|
||||
onClick={handleLocalStorageToggle}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
{localStorageEnabled ? (
|
||||
<Save className="h-3 w-3 text-green-600 opacity-80 transition-opacity hover:opacity-100" />
|
||||
) : (
|
||||
<SaveOff className="h-3 w-3 cursor-help text-gray-500 opacity-60 transition-opacity hover:opacity-100" />
|
||||
)}
|
||||
</button>
|
||||
<div className="pointer-events-none absolute right-0 top-full z-50 mt-2 whitespace-nowrap rounded bg-gray-900 p-2 text-xs text-white opacity-0 shadow-lg transition-opacity group-hover/save:opacity-100">
|
||||
<div className="font-medium">
|
||||
{localStorageEnabled
|
||||
? 'Автосохранение включено'
|
||||
: 'Автосохранение выключено'}
|
||||
</div>
|
||||
<div className="text-gray-300">
|
||||
{localStorageEnabled
|
||||
? 'Значение сохраняется в браузере'
|
||||
: 'Нажмите, чтобы включить автосохранение'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Бейдж ячеек */}
|
||||
<CellsBadge targetCells={config.targetCells} className="" />
|
||||
</div>
|
||||
|
||||
{/* Лейбл поля */}
|
||||
{config.name && (
|
||||
<label className="text-sm font-medium text-gray-900">
|
||||
{config.name}
|
||||
{config.required && <span className="ml-1 text-red-500">*</span>}
|
||||
</label>
|
||||
)}
|
||||
|
||||
{/* Поле ввода */}
|
||||
<Input
|
||||
placeholder={config.placeholder}
|
||||
value={currentValue}
|
||||
onChange={e => handleValueChange(e.target.value)}
|
||||
required={config.required}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user