테스트 프로젝트 테이블 생성 및 오류들 수정

This commit is contained in:
kjs
2025-09-19 12:19:34 +09:00
parent eb6fa71cf4
commit d1e1c7964b
28 changed files with 2221 additions and 94 deletions

View File

@@ -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%",

View File

@@ -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>
);
};

View File

@@ -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,

View File

@@ -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: "입력하세요",
},

View File

@@ -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;