import { useEffect, useRef, useState } from 'react'; interface InlineEditInputProps { value: number; onSave: (value: number) => Promise; formatDisplay?: (value: number) => string; min?: number; step?: string; className?: string; disabled?: boolean; } type Status = 'idle' | 'editing' | 'saving' | 'success' | 'error'; export default function InlineEditInput({ value, onSave, formatDisplay = (v) => String(v), min, step, className = '', disabled = false, }: InlineEditInputProps) { const [status, setStatus] = useState('idle'); const [editValue, setEditValue] = useState(''); const inputRef = useRef(null); const savingRef = useRef(false); useEffect(() => { if (status === 'editing' && inputRef.current) { inputRef.current.focus(); inputRef.current.select(); } }, [status]); const startEditing = () => { if (disabled) return; setEditValue(String(value)); setStatus('editing'); }; const cancel = () => { setStatus('idle'); }; const save = async () => { if (savingRef.current) return; const parsed = Number(editValue); if (isNaN(parsed)) { setStatus('idle'); return; } if (parsed === value) { setStatus('idle'); return; } savingRef.current = true; setStatus('saving'); try { await onSave(parsed); setStatus('success'); setTimeout(() => setStatus('idle'), 1500); } catch { setStatus('error'); setTimeout(() => setStatus('idle'), 1500); } finally { savingRef.current = false; } }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { e.preventDefault(); save(); } else if (e.key === 'Escape') { cancel(); } }; if (status === 'editing' || status === 'saving') { return ( setEditValue(e.target.value)} onBlur={save} onKeyDown={handleKeyDown} min={min} step={step} disabled={status === 'saving'} className={`w-24 rounded border border-blue-300 bg-white px-2 py-0.5 text-sm text-gray-900 outline-none focus:ring-2 focus:ring-blue-500 ${className}`} /> ); } return ( {formatDisplay(value)} {status === 'success' && } {status === 'error' && } ); }