테스트 프로젝트 테이블 생성 및 오류들 수정
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { ComponentRendererProps } from "@/types/component";
|
||||
import { DateInputConfig } from "./types";
|
||||
import { filterDOMProps } from "@/lib/utils/domPropsFilter";
|
||||
import { AutoGenerationUtils } from "@/lib/utils/autoGeneration";
|
||||
import { AutoGenerationConfig } from "@/types/screen";
|
||||
|
||||
export interface DateInputComponentProps extends ComponentRendererProps {
|
||||
config?: DateInputConfig;
|
||||
value?: any; // 외부에서 전달받는 값
|
||||
autoGeneration?: AutoGenerationConfig;
|
||||
hidden?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,6 +32,8 @@ export const DateInputComponent: React.FC<DateInputComponentProps> = ({
|
||||
formData,
|
||||
onFormDataChange,
|
||||
value: externalValue, // 외부에서 전달받은 값
|
||||
autoGeneration,
|
||||
hidden,
|
||||
...props
|
||||
}) => {
|
||||
// 컴포넌트 설정
|
||||
@@ -36,14 +42,130 @@ export const DateInputComponent: React.FC<DateInputComponentProps> = ({
|
||||
...component.config,
|
||||
} as DateInputConfig;
|
||||
|
||||
// 🎯 자동생성 상태 관리
|
||||
const [autoGeneratedValue, setAutoGeneratedValue] = useState<string>("");
|
||||
|
||||
// 🚨 컴포넌트 마운트 확인용 로그
|
||||
console.log("🚨 DateInputComponent 마운트됨!", {
|
||||
componentId: component.id,
|
||||
isInteractive,
|
||||
isDesignMode,
|
||||
autoGeneration,
|
||||
componentAutoGeneration: component.autoGeneration,
|
||||
externalValue,
|
||||
formDataValue: formData?.[component.columnName || ""],
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
// 🧪 무조건 실행되는 테스트
|
||||
useEffect(() => {
|
||||
console.log("🧪 DateInputComponent 무조건 실행 테스트!");
|
||||
const testDate = "2025-01-19"; // 고정된 테스트 날짜
|
||||
setAutoGeneratedValue(testDate);
|
||||
console.log("🧪 autoGeneratedValue 설정 완료:", testDate);
|
||||
}, []); // 빈 의존성 배열로 한 번만 실행
|
||||
|
||||
// 자동생성 설정 (props 우선, 컴포넌트 설정 폴백)
|
||||
const finalAutoGeneration = autoGeneration || component.autoGeneration;
|
||||
const finalHidden = hidden !== undefined ? hidden : component.hidden;
|
||||
|
||||
// 🧪 테스트용 간단한 자동생성 로직
|
||||
useEffect(() => {
|
||||
console.log("🔍 DateInputComponent useEffect 실행:", {
|
||||
componentId: component.id,
|
||||
finalAutoGeneration,
|
||||
enabled: finalAutoGeneration?.enabled,
|
||||
type: finalAutoGeneration?.type,
|
||||
isInteractive,
|
||||
isDesignMode,
|
||||
hasOnFormDataChange: !!onFormDataChange,
|
||||
columnName: component.columnName,
|
||||
currentFormValue: formData?.[component.columnName || ""],
|
||||
});
|
||||
|
||||
// 🧪 테스트: 자동생성이 활성화되어 있으면 무조건 현재 날짜 설정
|
||||
if (finalAutoGeneration?.enabled) {
|
||||
const today = new Date().toISOString().split("T")[0]; // YYYY-MM-DD
|
||||
console.log("🧪 테스트용 날짜 생성:", today);
|
||||
|
||||
setAutoGeneratedValue(today);
|
||||
|
||||
// 인터랙티브 모드에서 폼 데이터에도 설정
|
||||
if (isInteractive && onFormDataChange && component.columnName) {
|
||||
console.log("📤 테스트용 폼 데이터 업데이트:", component.columnName, today);
|
||||
onFormDataChange(component.columnName, today);
|
||||
}
|
||||
}
|
||||
|
||||
// 원래 자동생성 로직 (주석 처리)
|
||||
/*
|
||||
if (finalAutoGeneration?.enabled && finalAutoGeneration.type !== "none") {
|
||||
const fieldName = component.columnName || component.id;
|
||||
const generatedValue = AutoGenerationUtils.generateValue(finalAutoGeneration, fieldName);
|
||||
|
||||
console.log("🎯 DateInputComponent 자동생성 시도:", {
|
||||
componentId: component.id,
|
||||
fieldName,
|
||||
type: finalAutoGeneration.type,
|
||||
options: finalAutoGeneration.options,
|
||||
generatedValue,
|
||||
isInteractive,
|
||||
isDesignMode,
|
||||
});
|
||||
|
||||
if (generatedValue) {
|
||||
console.log("✅ DateInputComponent 자동생성 성공:", generatedValue);
|
||||
setAutoGeneratedValue(generatedValue);
|
||||
|
||||
// 인터랙티브 모드에서 폼 데이터 업데이트
|
||||
if (isInteractive && onFormDataChange && component.columnName) {
|
||||
const currentValue = formData?.[component.columnName];
|
||||
if (!currentValue) {
|
||||
console.log("📤 DateInputComponent -> onFormDataChange 호출:", component.columnName, generatedValue);
|
||||
onFormDataChange(component.columnName, generatedValue);
|
||||
} else {
|
||||
console.log("⚠️ DateInputComponent 기존 값이 있어서 자동생성 스킵:", currentValue);
|
||||
}
|
||||
} else {
|
||||
console.log("⚠️ DateInputComponent 자동생성 조건 불만족:", {
|
||||
isInteractive,
|
||||
hasOnFormDataChange: !!onFormDataChange,
|
||||
hasColumnName: !!component.columnName,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log("❌ DateInputComponent 자동생성 실패: generatedValue가 null");
|
||||
}
|
||||
} else {
|
||||
console.log("⚠️ DateInputComponent 자동생성 비활성화:", {
|
||||
enabled: finalAutoGeneration?.enabled,
|
||||
type: finalAutoGeneration?.type,
|
||||
});
|
||||
}
|
||||
*/
|
||||
}, [
|
||||
finalAutoGeneration?.enabled,
|
||||
finalAutoGeneration?.type,
|
||||
finalAutoGeneration?.options,
|
||||
component.id,
|
||||
component.columnName,
|
||||
isInteractive,
|
||||
]);
|
||||
|
||||
// 날짜 값 계산 및 디버깅
|
||||
const fieldName = component.columnName || component.id;
|
||||
const rawValue =
|
||||
externalValue !== undefined
|
||||
? externalValue
|
||||
: isInteractive && formData && component.columnName
|
||||
? formData[component.columnName]
|
||||
: component.value;
|
||||
|
||||
// 값 우선순위: externalValue > formData > autoGeneratedValue > component.value
|
||||
let rawValue: any;
|
||||
if (externalValue !== undefined) {
|
||||
rawValue = externalValue;
|
||||
} else if (isInteractive && formData && component.columnName && formData[component.columnName]) {
|
||||
rawValue = formData[component.columnName];
|
||||
} else if (autoGeneratedValue) {
|
||||
rawValue = autoGeneratedValue;
|
||||
} else {
|
||||
rawValue = component.value;
|
||||
}
|
||||
|
||||
console.log("🔍 DateInputComponent 값 디버깅:", {
|
||||
componentId: component.id,
|
||||
@@ -196,10 +318,14 @@ export const DateInputComponent: React.FC<DateInputComponentProps> = ({
|
||||
<input
|
||||
type="date"
|
||||
value={formattedValue}
|
||||
placeholder={componentConfig.placeholder || ""}
|
||||
placeholder={
|
||||
finalAutoGeneration?.enabled
|
||||
? `자동생성: ${AutoGenerationUtils.getTypeDescription(finalAutoGeneration.type)}`
|
||||
: componentConfig.placeholder || ""
|
||||
}
|
||||
disabled={componentConfig.disabled || false}
|
||||
required={componentConfig.required || false}
|
||||
readOnly={componentConfig.readonly || false}
|
||||
readOnly={componentConfig.readonly || finalAutoGeneration?.enabled || false}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
|
||||
@@ -6,6 +6,8 @@ import { Label } from "@/components/ui/label";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { DateInputConfig } from "./types";
|
||||
import { AutoGenerationType, AutoGenerationConfig } from "@/types/screen";
|
||||
import { AutoGenerationUtils } from "@/lib/utils/autoGeneration";
|
||||
|
||||
export interface DateInputConfigPanelProps {
|
||||
config: DateInputConfig;
|
||||
@@ -16,21 +18,17 @@ export interface DateInputConfigPanelProps {
|
||||
* DateInput 설정 패널
|
||||
* 컴포넌트의 설정값들을 편집할 수 있는 UI 제공
|
||||
*/
|
||||
export const DateInputConfigPanel: React.FC<DateInputConfigPanelProps> = ({
|
||||
config,
|
||||
onChange,
|
||||
}) => {
|
||||
export const DateInputConfigPanel: React.FC<DateInputConfigPanelProps> = ({ config, onChange }) => {
|
||||
const handleChange = (key: keyof DateInputConfig, value: any) => {
|
||||
console.log("🔧 DateInputConfigPanel.handleChange:", { key, value });
|
||||
onChange({ [key]: value });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="text-sm font-medium">
|
||||
date-input 설정
|
||||
</div>
|
||||
<div className="text-sm font-medium">date-input 설정</div>
|
||||
|
||||
{/* date 관련 설정 */}
|
||||
{/* date 관련 설정 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="placeholder">플레이스홀더</Label>
|
||||
<Input
|
||||
@@ -67,6 +65,194 @@ export const DateInputConfigPanel: React.FC<DateInputConfigPanelProps> = ({
|
||||
onCheckedChange={(checked) => handleChange("readonly", checked)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 숨김 기능 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="hidden">숨김</Label>
|
||||
<Checkbox
|
||||
id="hidden"
|
||||
checked={config.hidden || false}
|
||||
onCheckedChange={(checked) => handleChange("hidden", checked)}
|
||||
/>
|
||||
<p className="text-xs text-gray-500">편집기에서는 연하게 보이지만 실제 화면에서는 숨겨집니다</p>
|
||||
</div>
|
||||
|
||||
{/* 자동생성 기능 */}
|
||||
<div className="space-y-3 border-t pt-3">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="autoGeneration">자동생성</Label>
|
||||
<Checkbox
|
||||
id="autoGeneration"
|
||||
checked={config.autoGeneration?.enabled || false}
|
||||
onCheckedChange={(checked) => {
|
||||
const newAutoGeneration: AutoGenerationConfig = {
|
||||
...config.autoGeneration,
|
||||
enabled: checked as boolean,
|
||||
type: config.autoGeneration?.type || "current_time",
|
||||
};
|
||||
handleChange("autoGeneration", newAutoGeneration);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{config.autoGeneration?.enabled && (
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="autoGenerationType">자동생성 타입</Label>
|
||||
<Select
|
||||
value={config.autoGeneration?.type || "current_time"}
|
||||
onValueChange={(value: AutoGenerationType) => {
|
||||
const newAutoGeneration: AutoGenerationConfig = {
|
||||
...config.autoGeneration,
|
||||
type: value,
|
||||
options: value === "current_time" ? { format: "date" } : {},
|
||||
};
|
||||
handleChange("autoGeneration", newAutoGeneration);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="current_time">현재 날짜/시간</SelectItem>
|
||||
<SelectItem value="uuid">UUID</SelectItem>
|
||||
<SelectItem value="current_user">현재 사용자</SelectItem>
|
||||
<SelectItem value="sequence">순차 번호</SelectItem>
|
||||
<SelectItem value="random_string">랜덤 문자열</SelectItem>
|
||||
<SelectItem value="random_number">랜덤 숫자</SelectItem>
|
||||
<SelectItem value="company_code">회사 코드</SelectItem>
|
||||
<SelectItem value="department">부서 코드</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-xs text-gray-500">
|
||||
{AutoGenerationUtils.getTypeDescription(config.autoGeneration?.type || "current_time")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{config.autoGeneration?.type === "current_time" && (
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="dateFormat">날짜 형식</Label>
|
||||
<Select
|
||||
value={config.autoGeneration?.options?.format || "date"}
|
||||
onValueChange={(value) => {
|
||||
const newAutoGeneration: AutoGenerationConfig = {
|
||||
...config.autoGeneration!,
|
||||
options: {
|
||||
...config.autoGeneration?.options,
|
||||
format: value,
|
||||
},
|
||||
};
|
||||
handleChange("autoGeneration", newAutoGeneration);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="date">날짜만 (YYYY-MM-DD)</SelectItem>
|
||||
<SelectItem value="datetime">날짜+시간 (YYYY-MM-DD HH:mm:ss)</SelectItem>
|
||||
<SelectItem value="time">시간만 (HH:mm:ss)</SelectItem>
|
||||
<SelectItem value="timestamp">타임스탬프</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(config.autoGeneration?.type === "sequence" ||
|
||||
config.autoGeneration?.type === "random_string" ||
|
||||
config.autoGeneration?.type === "random_number") && (
|
||||
<>
|
||||
{config.autoGeneration?.type === "sequence" && (
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="startValue">시작값</Label>
|
||||
<Input
|
||||
id="startValue"
|
||||
type="number"
|
||||
value={config.autoGeneration?.options?.startValue || 1}
|
||||
onChange={(e) => {
|
||||
const newAutoGeneration: AutoGenerationConfig = {
|
||||
...config.autoGeneration!,
|
||||
options: {
|
||||
...config.autoGeneration?.options,
|
||||
startValue: parseInt(e.target.value) || 1,
|
||||
},
|
||||
};
|
||||
handleChange("autoGeneration", newAutoGeneration);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(config.autoGeneration?.type === "random_string" ||
|
||||
config.autoGeneration?.type === "random_number") && (
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="length">길이</Label>
|
||||
<Input
|
||||
id="length"
|
||||
type="number"
|
||||
value={
|
||||
config.autoGeneration?.options?.length ||
|
||||
(config.autoGeneration?.type === "random_string" ? 8 : 6)
|
||||
}
|
||||
onChange={(e) => {
|
||||
const newAutoGeneration: AutoGenerationConfig = {
|
||||
...config.autoGeneration!,
|
||||
options: {
|
||||
...config.autoGeneration?.options,
|
||||
length: parseInt(e.target.value) || 8,
|
||||
},
|
||||
};
|
||||
handleChange("autoGeneration", newAutoGeneration);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="prefix">접두사</Label>
|
||||
<Input
|
||||
id="prefix"
|
||||
value={config.autoGeneration?.options?.prefix || ""}
|
||||
onChange={(e) => {
|
||||
const newAutoGeneration: AutoGenerationConfig = {
|
||||
...config.autoGeneration!,
|
||||
options: {
|
||||
...config.autoGeneration?.options,
|
||||
prefix: e.target.value,
|
||||
},
|
||||
};
|
||||
handleChange("autoGeneration", newAutoGeneration);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="suffix">접미사</Label>
|
||||
<Input
|
||||
id="suffix"
|
||||
value={config.autoGeneration?.options?.suffix || ""}
|
||||
onChange={(e) => {
|
||||
const newAutoGeneration: AutoGenerationConfig = {
|
||||
...config.autoGeneration!,
|
||||
options: {
|
||||
...config.autoGeneration?.options,
|
||||
suffix: e.target.value,
|
||||
},
|
||||
};
|
||||
handleChange("autoGeneration", newAutoGeneration);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="rounded bg-gray-50 p-2 text-xs">
|
||||
<strong>미리보기:</strong> {AutoGenerationUtils.generatePreviewValue(config.autoGeneration)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,17 +13,24 @@ export class DateInputRenderer extends AutoRegisteringComponentRenderer {
|
||||
static componentDefinition = DateInputDefinition;
|
||||
|
||||
render(): React.ReactElement {
|
||||
console.log("🎯 DateInputRenderer.render() 호출:", {
|
||||
componentId: this.props.component?.id,
|
||||
autoGeneration: this.props.autoGeneration,
|
||||
componentAutoGeneration: this.props.component?.autoGeneration,
|
||||
allProps: Object.keys(this.props),
|
||||
});
|
||||
|
||||
return <DateInputComponent {...this.props} renderer={this} />;
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트별 특화 메서드들
|
||||
*/
|
||||
|
||||
|
||||
// date 타입 특화 속성 처리
|
||||
protected getDateInputProps() {
|
||||
const baseProps = this.getWebTypeProps();
|
||||
|
||||
|
||||
// date 타입에 특화된 추가 속성들
|
||||
return {
|
||||
...baseProps,
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from "react";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import type { WebType } from "@/types/screen";
|
||||
import { DateInputWrapper } from "./DateInputComponent";
|
||||
import { DateInputComponent } from "./DateInputComponent";
|
||||
import { DateInputConfigPanel } from "./DateInputConfigPanel";
|
||||
import { DateInputConfig } from "./types";
|
||||
|
||||
@@ -19,7 +19,7 @@ export const DateInputDefinition = createComponentDefinition({
|
||||
description: "날짜 선택을 위한 날짜 선택기 컴포넌트",
|
||||
category: ComponentCategory.INPUT,
|
||||
webType: "date",
|
||||
component: DateInputWrapper,
|
||||
component: DateInputComponent,
|
||||
defaultConfig: {
|
||||
placeholder: "입력하세요",
|
||||
},
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
"use client";
|
||||
|
||||
import { ComponentConfig } from "@/types/component";
|
||||
import { AutoGenerationConfig } from "@/types/screen";
|
||||
|
||||
/**
|
||||
* DateInput 컴포넌트 설정 타입
|
||||
*/
|
||||
export interface DateInputConfig extends ComponentConfig {
|
||||
// date 관련 설정
|
||||
// date 관련 설정
|
||||
placeholder?: string;
|
||||
|
||||
|
||||
// 공통 설정
|
||||
disabled?: boolean;
|
||||
required?: boolean;
|
||||
readonly?: boolean;
|
||||
placeholder?: string;
|
||||
helperText?: string;
|
||||
|
||||
|
||||
// 자동생성 및 숨김 기능
|
||||
autoGeneration?: AutoGenerationConfig;
|
||||
hidden?: boolean;
|
||||
|
||||
// 스타일 관련
|
||||
variant?: "default" | "outlined" | "filled";
|
||||
size?: "sm" | "md" | "lg";
|
||||
|
||||
|
||||
// 이벤트 관련
|
||||
onChange?: (value: any) => void;
|
||||
onFocus?: () => void;
|
||||
@@ -37,7 +41,7 @@ export interface DateInputProps {
|
||||
config?: DateInputConfig;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
|
||||
|
||||
// 이벤트 핸들러
|
||||
onChange?: (value: any) => void;
|
||||
onFocus?: () => void;
|
||||
|
||||
Reference in New Issue
Block a user