feat(01-02): implement InlineEditCell shared component

- Shared TableCell with display/edit mode toggle
- Calls onSave(number) on blur or Enter key
- Skips save when value unchanged or NaN
- Accepts className for amount coloring
This commit is contained in:
2026-03-11 20:56:19 +01:00
parent bb36aeb272
commit 689c88fc3e

View File

@@ -0,0 +1,60 @@
import { useState } from 'react'
import { TableCell } from '@/components/ui/table'
import { Input } from '@/components/ui/input'
import { formatCurrency } from '@/lib/format'
import { cn } from '@/lib/utils'
interface InlineEditCellProps {
value: number
currency: string
onSave: (value: number) => Promise<void>
className?: string
}
export function InlineEditCell({ value, currency, onSave, className }: InlineEditCellProps) {
const [editing, setEditing] = useState(false)
const [inputValue, setInputValue] = useState(String(value))
const handleClick = () => {
setInputValue(String(value))
setEditing(true)
}
const handleBlur = async () => {
const num = parseFloat(inputValue)
if (!isNaN(num) && num !== value) {
await onSave(num)
}
setEditing(false)
}
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleBlur()
}
}
return (
<TableCell className={cn('text-right', className)}>
{editing ? (
<Input
type="number"
step="0.01"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onBlur={handleBlur}
onKeyDown={handleKeyDown}
className="ml-auto w-28 text-right"
autoFocus
/>
) : (
<span
className="cursor-pointer rounded px-2 py-1 hover:bg-muted"
onClick={handleClick}
>
{formatCurrency(value, currency)}
</span>
)}
</TableCell>
)
}