All checks were successful
Staging Build / build (push) Successful in 2m46s
- Add is_required and allow_multiselect category toggles - Implement module-popover for product module assignment - Add cascade-protected deletion for categories and products - Add sidebar link with AdminNavLink active states
82 lines
1.9 KiB
TypeScript
82 lines
1.9 KiB
TypeScript
'use client'
|
|
|
|
import { useState, useEffect, useRef } from 'react'
|
|
|
|
interface InlineInputProps {
|
|
value: string
|
|
onSave: (val: string) => Promise<void>
|
|
className?: string
|
|
type?: 'text' | 'number'
|
|
}
|
|
|
|
export function InlineInput({ value, onSave, className, type = 'text' }: InlineInputProps) {
|
|
const [isEditing, setIsEditing] = useState(false)
|
|
const [currentValue, setCurrentValue] = useState(value)
|
|
const inputRef = useRef<HTMLInputElement>(null)
|
|
|
|
useEffect(() => {
|
|
setCurrentValue(value)
|
|
}, [value])
|
|
|
|
useEffect(() => {
|
|
if (isEditing && inputRef.current) {
|
|
inputRef.current.focus()
|
|
}
|
|
}, [isEditing])
|
|
|
|
const handleBlur = async () => {
|
|
setIsEditing(false)
|
|
const trimmed = currentValue.trim()
|
|
|
|
if (type === 'number') {
|
|
const parsed = parseFloat(trimmed)
|
|
if (isNaN(parsed) || trimmed === '') {
|
|
setCurrentValue(value)
|
|
return
|
|
}
|
|
const finalVal = parsed.toString()
|
|
if (finalVal !== value) {
|
|
await onSave(finalVal)
|
|
}
|
|
} else {
|
|
if (trimmed === '') {
|
|
setCurrentValue(value)
|
|
return
|
|
}
|
|
if (trimmed !== value) {
|
|
await onSave(trimmed)
|
|
}
|
|
}
|
|
}
|
|
|
|
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
if (e.key === 'Enter') {
|
|
handleBlur()
|
|
}
|
|
}
|
|
|
|
if (isEditing) {
|
|
return (
|
|
<input
|
|
ref={inputRef}
|
|
type={type}
|
|
step={type === 'number' ? '0.01' : undefined}
|
|
value={currentValue}
|
|
onChange={(e) => setCurrentValue(e.target.value)}
|
|
onBlur={handleBlur}
|
|
onKeyDown={handleKeyDown}
|
|
className={`bg-white/10 text-white border border-primary px-1 rounded outline-none w-full ${className}`}
|
|
/>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<span
|
|
onClick={() => setIsEditing(true)}
|
|
className={`cursor-pointer hover:bg-white/5 rounded px-1 transition ${className}`}
|
|
>
|
|
{value || <span className="italic text-slate-500">Klicken zum Bearbeiten</span>}
|
|
</span>
|
|
)
|
|
}
|