feat: Refactor EditModal for improved INSERT/UPDATE handling

- Introduced a new state flag `isCreateModeFlag` to determine the mode (INSERT or UPDATE) directly from the event, enhancing clarity in the modal's behavior.
- Updated the logic for initializing `originalData` and determining the mode, ensuring that the modal correctly identifies whether to create or update based on the provided data.
- Refactored the update logic to send the entire `formData` without relying on `originalData`, streamlining the update process.
- Enhanced logging for better debugging and understanding of the modal's state during operations.
This commit is contained in:
DDD1542
2026-02-12 16:20:26 +09:00
parent 4294e6206b
commit df04afa5de
11 changed files with 180 additions and 97 deletions

View File

@@ -82,8 +82,9 @@ const TextInput = forwardRef<
disabled?: boolean;
className?: string;
columnName?: string;
inputStyle?: React.CSSProperties;
}
>(({ value, onChange, format = "none", placeholder, readonly, disabled, className, columnName }, ref) => {
>(({ value, onChange, format = "none", placeholder, readonly, disabled, className, columnName, inputStyle }, ref) => {
// 검증 상태
const [hasBlurred, setHasBlurred] = useState(false);
const [validationError, setValidationError] = useState<string>("");
@@ -210,6 +211,7 @@ const TextInput = forwardRef<
hasError && "border-destructive focus-visible:ring-destructive",
className,
)}
style={inputStyle}
/>
{hasError && (
<p className="text-destructive mt-1 text-[11px]">{validationError}</p>
@@ -234,8 +236,9 @@ const NumberInput = forwardRef<
readonly?: boolean;
disabled?: boolean;
className?: string;
inputStyle?: React.CSSProperties;
}
>(({ value, onChange, min, max, step = 1, placeholder, readonly, disabled, className }, ref) => {
>(({ value, onChange, min, max, step = 1, placeholder, readonly, disabled, className, inputStyle }, ref) => {
const handleChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const val = e.target.value;
@@ -268,6 +271,7 @@ const NumberInput = forwardRef<
readOnly={readonly}
disabled={disabled}
className={cn("h-full w-full", className)}
style={inputStyle}
/>
);
});
@@ -285,8 +289,9 @@ const PasswordInput = forwardRef<
readonly?: boolean;
disabled?: boolean;
className?: string;
inputStyle?: React.CSSProperties;
}
>(({ value, onChange, placeholder, readonly, disabled, className }, ref) => {
>(({ value, onChange, placeholder, readonly, disabled, className, inputStyle }, ref) => {
const [showPassword, setShowPassword] = useState(false);
return (
@@ -300,6 +305,7 @@ const PasswordInput = forwardRef<
readOnly={readonly}
disabled={disabled}
className={cn("h-full w-full pr-10", className)}
style={inputStyle}
/>
<button
type="button"
@@ -393,8 +399,9 @@ const TextareaInput = forwardRef<
readonly?: boolean;
disabled?: boolean;
className?: string;
inputStyle?: React.CSSProperties;
}
>(({ value = "", onChange, placeholder, rows = 3, readonly, disabled, className }, ref) => {
>(({ value = "", onChange, placeholder, rows = 3, readonly, disabled, className, inputStyle }, ref) => {
return (
<textarea
ref={ref}
@@ -408,6 +415,7 @@ const TextareaInput = forwardRef<
"border-input placeholder:text-muted-foreground focus-visible:ring-ring flex h-full w-full rounded-md border bg-transparent px-3 py-2 text-sm shadow-sm focus-visible:ring-1 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
style={inputStyle}
/>
);
});
@@ -767,6 +775,7 @@ export const V2Input = forwardRef<HTMLDivElement, V2InputProps>((props, ref) =>
readonly={readonly || (autoGeneration.enabled && hasGeneratedRef.current)}
disabled={disabled}
columnName={columnName}
inputStyle={inputTextStyle}
/>
);
@@ -784,6 +793,7 @@ export const V2Input = forwardRef<HTMLDivElement, V2InputProps>((props, ref) =>
placeholder={config.placeholder}
readonly={readonly}
disabled={disabled}
inputStyle={inputTextStyle}
/>
);
@@ -798,6 +808,7 @@ export const V2Input = forwardRef<HTMLDivElement, V2InputProps>((props, ref) =>
placeholder={config.placeholder}
readonly={readonly}
disabled={disabled}
inputStyle={inputTextStyle}
/>
);
@@ -840,6 +851,7 @@ export const V2Input = forwardRef<HTMLDivElement, V2InputProps>((props, ref) =>
rows={config.rows}
readonly={readonly}
disabled={disabled}
inputStyle={inputTextStyle}
/>
);
@@ -859,6 +871,7 @@ export const V2Input = forwardRef<HTMLDivElement, V2InputProps>((props, ref) =>
placeholder={isGeneratingNumbering ? "생성 중..." : "자동 생성됩니다"}
readonly={true}
disabled={disabled || isGeneratingNumbering}
inputStyle={inputTextStyle}
/>
);
}
@@ -905,6 +918,7 @@ export const V2Input = forwardRef<HTMLDivElement, V2InputProps>((props, ref) =>
placeholder="입력"
className="h-full min-w-[60px] flex-1 bg-transparent px-2 text-sm focus-visible:outline-none"
disabled={disabled || isGeneratingNumbering}
style={inputTextStyle}
/>
{/* 고정 접미어 */}
{templateSuffix && (
@@ -929,6 +943,7 @@ export const V2Input = forwardRef<HTMLDivElement, V2InputProps>((props, ref) =>
readonly={readonly}
disabled={disabled}
columnName={columnName}
inputStyle={inputTextStyle}
/>
);
}
@@ -954,13 +969,15 @@ export const V2Input = forwardRef<HTMLDivElement, V2InputProps>((props, ref) =>
const hasCustomBackground = !!style?.backgroundColor;
const hasCustomRadius = !!style?.borderRadius;
// 텍스트 스타일 오버라이드 (CSS 상속으로 내부 input에 전달)
// 텍스트 스타일 오버라이드 (내부 input/textarea에 직접 전달)
const customTextStyle: React.CSSProperties = {};
if (style?.color) customTextStyle.color = style.color;
if (style?.fontSize) customTextStyle.fontSize = style.fontSize;
if (style?.fontWeight) customTextStyle.fontWeight = style.fontWeight;
if (style?.textAlign) customTextStyle.textAlign = style.textAlign as React.CSSProperties["textAlign"];
const hasCustomText = Object.keys(customTextStyle).length > 0;
// 내부 input에 직접 적용할 텍스트 스타일 (fontSize, color, fontWeight, textAlign)
const inputTextStyle: React.CSSProperties | undefined = hasCustomText ? customTextStyle : undefined;
return (
<div