fix: Dialog 모달 내부 input 필드 텍스트 입력 불가 문제 해결
- ResizableDialog 콘텐츠 영역에 pointer-events 및 z-index 설정 추가 - TextInputComponent를 제어 컴포넌트에서 비제어 컴포넌트로 변경 (value → defaultValue) - ItemSelectionModal 및 TextInputComponent 디버그 로그 제거 수정 파일: - frontend/components/ui/resizable-dialog.tsx - frontend/lib/registry/components/text-input/TextInputComponent.tsx - frontend/lib/registry/components/modal-repeater-table/ItemSelectionModal.tsx
This commit is contained in:
parent
9c8ec879d9
commit
0bedd8bc0b
|
|
@ -11,7 +11,6 @@ import {
|
|||
} from "@/components/ui/dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
|
|
@ -19,7 +18,6 @@ import {
|
|||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { OrderCustomerSearch } from "./OrderCustomerSearch";
|
||||
import { OrderItemRepeaterTable } from "./OrderItemRepeaterTable";
|
||||
import { toast } from "sonner";
|
||||
|
|
@ -260,14 +258,15 @@ export function OrderRegistrationModal({
|
|||
<Label htmlFor="contactPerson" className="text-xs sm:text-sm">
|
||||
담당자
|
||||
</Label>
|
||||
<Input
|
||||
<input
|
||||
type="text"
|
||||
id="contactPerson"
|
||||
placeholder="담당자"
|
||||
value={formData.contactPerson}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, contactPerson: e.target.value })
|
||||
}
|
||||
className="h-8 text-xs sm:h-10 sm:text-sm"
|
||||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -276,14 +275,15 @@ export function OrderRegistrationModal({
|
|||
<Label htmlFor="deliveryDestination" className="text-xs sm:text-sm">
|
||||
납품처
|
||||
</Label>
|
||||
<Input
|
||||
<input
|
||||
type="text"
|
||||
id="deliveryDestination"
|
||||
placeholder="납품처"
|
||||
value={formData.deliveryDestination}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, deliveryDestination: e.target.value })
|
||||
}
|
||||
className="h-8 text-xs sm:h-10 sm:text-sm"
|
||||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -292,14 +292,15 @@ export function OrderRegistrationModal({
|
|||
<Label htmlFor="deliveryAddress" className="text-xs sm:text-sm">
|
||||
납품장소
|
||||
</Label>
|
||||
<Input
|
||||
<input
|
||||
type="text"
|
||||
id="deliveryAddress"
|
||||
placeholder="납품장소"
|
||||
value={formData.deliveryAddress}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, deliveryAddress: e.target.value })
|
||||
}
|
||||
className="h-8 text-xs sm:h-10 sm:text-sm"
|
||||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -310,9 +311,10 @@ export function OrderRegistrationModal({
|
|||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs sm:text-sm">견대 번호 *</Label>
|
||||
<Input
|
||||
<input
|
||||
type="text"
|
||||
placeholder="견대 번호를 입력하세요"
|
||||
className="h-8 text-xs sm:h-10 sm:text-sm"
|
||||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -322,9 +324,10 @@ export function OrderRegistrationModal({
|
|||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs sm:text-sm">단가 방식 설정</Label>
|
||||
<Input
|
||||
<input
|
||||
type="text"
|
||||
placeholder="단가 정보 입력"
|
||||
className="h-8 text-xs sm:h-10 sm:text-sm"
|
||||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -436,14 +439,15 @@ export function OrderRegistrationModal({
|
|||
<Label htmlFor="portOfLoading" className="text-xs sm:text-sm">
|
||||
선적항
|
||||
</Label>
|
||||
<Input
|
||||
<input
|
||||
type="text"
|
||||
id="portOfLoading"
|
||||
placeholder="선적항"
|
||||
value={formData.portOfLoading}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, portOfLoading: e.target.value })
|
||||
}
|
||||
className="h-8 text-xs sm:h-10 sm:text-sm"
|
||||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -452,14 +456,15 @@ export function OrderRegistrationModal({
|
|||
<Label htmlFor="portOfDischarge" className="text-xs sm:text-sm">
|
||||
도착항
|
||||
</Label>
|
||||
<Input
|
||||
<input
|
||||
type="text"
|
||||
id="portOfDischarge"
|
||||
placeholder="도착항"
|
||||
value={formData.portOfDischarge}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, portOfDischarge: e.target.value })
|
||||
}
|
||||
className="h-8 text-xs sm:h-10 sm:text-sm"
|
||||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -468,14 +473,15 @@ export function OrderRegistrationModal({
|
|||
<Label htmlFor="hsCode" className="text-xs sm:text-sm">
|
||||
HS Code
|
||||
</Label>
|
||||
<Input
|
||||
<input
|
||||
type="text"
|
||||
id="hsCode"
|
||||
placeholder="HS Code"
|
||||
value={formData.hsCode}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, hsCode: e.target.value })
|
||||
}
|
||||
className="h-8 text-xs sm:h-10 sm:text-sm"
|
||||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -487,14 +493,14 @@ export function OrderRegistrationModal({
|
|||
<Label htmlFor="memo" className="text-xs sm:text-sm">
|
||||
메모
|
||||
</Label>
|
||||
<Textarea
|
||||
<textarea
|
||||
id="memo"
|
||||
placeholder="메모를 입력하세요"
|
||||
value={formData.memo}
|
||||
onChange={(e) =>
|
||||
setFormData({ ...formData, memo: e.target.value })
|
||||
}
|
||||
className="text-xs sm:text-sm"
|
||||
className="border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[80px] w-full rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
|
||||
rows={3}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -377,8 +377,8 @@ const ResizableDialogContent = React.forwardRef<
|
|||
>
|
||||
<div
|
||||
ref={contentRef}
|
||||
className="h-full w-full"
|
||||
style={{ display: 'block', overflow: 'hidden' }}
|
||||
className="h-full w-full relative"
|
||||
style={{ display: 'block', overflow: 'hidden', pointerEvents: 'auto', zIndex: 1 }}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
|
|
@ -387,41 +387,49 @@ const ResizableDialogContent = React.forwardRef<
|
|||
{/* 오른쪽 */}
|
||||
<div
|
||||
className="absolute right-0 top-0 h-full w-2 cursor-ew-resize hover:bg-primary/20 transition-colors"
|
||||
style={{ pointerEvents: 'auto', zIndex: 10 }}
|
||||
onMouseDown={startResize("e")}
|
||||
/>
|
||||
{/* 아래 */}
|
||||
<div
|
||||
className="absolute bottom-0 left-0 w-full h-2 cursor-ns-resize hover:bg-primary/20 transition-colors"
|
||||
style={{ pointerEvents: 'auto', zIndex: 10 }}
|
||||
onMouseDown={startResize("s")}
|
||||
/>
|
||||
{/* 오른쪽 아래 */}
|
||||
<div
|
||||
className="absolute right-0 bottom-0 w-4 h-4 cursor-nwse-resize hover:bg-primary/30 transition-colors"
|
||||
style={{ pointerEvents: 'auto', zIndex: 10 }}
|
||||
onMouseDown={startResize("se")}
|
||||
/>
|
||||
{/* 왼쪽 */}
|
||||
<div
|
||||
className="absolute left-0 top-0 h-full w-2 cursor-ew-resize hover:bg-primary/20 transition-colors"
|
||||
style={{ pointerEvents: 'auto', zIndex: 10 }}
|
||||
onMouseDown={startResize("w")}
|
||||
/>
|
||||
{/* 위 */}
|
||||
<div
|
||||
className="absolute top-0 left-0 w-full h-2 cursor-ns-resize hover:bg-primary/20 transition-colors"
|
||||
style={{ pointerEvents: 'auto', zIndex: 10 }}
|
||||
onMouseDown={startResize("n")}
|
||||
/>
|
||||
{/* 왼쪽 아래 */}
|
||||
<div
|
||||
className="absolute left-0 bottom-0 w-4 h-4 cursor-nesw-resize hover:bg-primary/30 transition-colors"
|
||||
style={{ pointerEvents: 'auto', zIndex: 10 }}
|
||||
onMouseDown={startResize("sw")}
|
||||
/>
|
||||
{/* 오른쪽 위 */}
|
||||
<div
|
||||
className="absolute right-0 top-0 w-4 h-4 cursor-nesw-resize hover:bg-primary/30 transition-colors"
|
||||
style={{ pointerEvents: 'auto', zIndex: 10 }}
|
||||
onMouseDown={startResize("ne")}
|
||||
/>
|
||||
{/* 왼쪽 위 */}
|
||||
<div
|
||||
className="absolute left-0 top-0 w-4 h-4 cursor-nwse-resize hover:bg-primary/30 transition-colors"
|
||||
style={{ pointerEvents: 'auto', zIndex: 10 }}
|
||||
onMouseDown={startResize("nw")}
|
||||
/>
|
||||
|
||||
|
|
|
|||
|
|
@ -148,7 +148,6 @@ export function ItemSelectionModal({
|
|||
|
||||
// uniqueField 값이 undefined인 경우 객체 참조로 비교
|
||||
if (itemValue === undefined || itemValue === null) {
|
||||
console.warn(`⚠️ uniqueField "${uniqueField}"의 값이 undefined입니다. 객체 참조로 비교합니다.`);
|
||||
return selectedItems.includes(item);
|
||||
}
|
||||
|
||||
|
|
@ -287,14 +286,6 @@ export function ItemSelectionModal({
|
|||
const itemKey = (uniqueFieldValue !== undefined && uniqueFieldValue !== null)
|
||||
? uniqueFieldValue
|
||||
: `item-${index}`;
|
||||
|
||||
console.log("🔍 행 렌더링:", {
|
||||
index,
|
||||
itemKey,
|
||||
selected,
|
||||
uniqueFieldValue,
|
||||
selectedCount: selectedItems.length
|
||||
});
|
||||
|
||||
return (
|
||||
<tr
|
||||
|
|
|
|||
|
|
@ -686,7 +686,7 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
|
|||
|
||||
<input
|
||||
type={inputType}
|
||||
value={(() => {
|
||||
defaultValue={(() => {
|
||||
let displayValue = "";
|
||||
|
||||
if (isInteractive && formData && component.columnName) {
|
||||
|
|
@ -745,13 +745,6 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
|
|||
// isInteractive 모드에서는 formData 업데이트
|
||||
if (isInteractive && onFormDataChange && component.columnName) {
|
||||
onFormDataChange(component.columnName, newValue);
|
||||
} else {
|
||||
console.log("❌ TextInputComponent onFormDataChange 조건 미충족:", {
|
||||
isInteractive,
|
||||
hasOnFormDataChange: !!onFormDataChange,
|
||||
hasColumnName: !!component.columnName,
|
||||
columnName: component.columnName,
|
||||
});
|
||||
}
|
||||
|
||||
// props.onChange는 DynamicComponentRenderer의 handleChange
|
||||
|
|
|
|||
Loading…
Reference in New Issue