From 689c88fc3e69ce1b900acb6c4727cc616e14ed31 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Wed, 11 Mar 2026 20:56:19 +0100 Subject: [PATCH] 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 --- frontend/src/components/InlineEditCell.tsx | 60 ++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 frontend/src/components/InlineEditCell.tsx diff --git a/frontend/src/components/InlineEditCell.tsx b/frontend/src/components/InlineEditCell.tsx new file mode 100644 index 0000000..fbbdc93 --- /dev/null +++ b/frontend/src/components/InlineEditCell.tsx @@ -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 + 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) => { + if (e.key === 'Enter') { + handleBlur() + } + } + + return ( + + {editing ? ( + setInputValue(e.target.value)} + onBlur={handleBlur} + onKeyDown={handleKeyDown} + className="ml-auto w-28 text-right" + autoFocus + /> + ) : ( + + {formatCurrency(value, currency)} + + )} + + ) +}