diff --git a/client/src/components/Budget/BudgetPanel.tsx b/client/src/components/Budget/BudgetPanel.tsx index e1f117bc..f85f4079 100644 --- a/client/src/components/Budget/BudgetPanel.tsx +++ b/client/src/components/Budget/BudgetPanel.tsx @@ -75,9 +75,29 @@ function InlineEditCell({ value, onSave, type = 'text', style = {}, placeholder if (v !== value) onSave(v) } + const handlePaste = (e) => { + if (type !== 'number') return + e.preventDefault() + let text = e.clipboardData.getData('text').trim() + // Strip everything except digits, dots, commas, minus + text = text.replace(/[^\d.,-]/g, '') + // Remove all thousand separators (dots or commas before 3-digit groups), keep last separator as decimal + const lastComma = text.lastIndexOf(',') + const lastDot = text.lastIndexOf('.') + const decimalPos = Math.max(lastComma, lastDot) + if (decimalPos > -1) { + const intPart = text.substring(0, decimalPos).replace(/[.,]/g, '') + const decPart = text.substring(decimalPos + 1) + text = intPart + '.' + decPart + } else { + text = text.replace(/[.,]/g, '') + } + setEditValue(text) + } + if (editing) { return setEditValue(e.target.value)} onBlur={save} + onChange={e => setEditValue(e.target.value)} onBlur={save} onPaste={handlePaste} onKeyDown={e => { if (e.key === 'Enter') save(); if (e.key === 'Escape') { setEditValue(value ?? ''); setEditing(false) } }} style={{ width: '100%', border: '1px solid var(--accent)', borderRadius: 4, padding: '4px 6px', fontSize: 13, outline: 'none', background: 'var(--bg-input)', color: 'var(--text-primary)', fontFamily: 'inherit', ...style }} placeholder={placeholder} /> @@ -131,6 +151,7 @@ function AddItemRow({ onAdd, t }: AddItemRowProps) {