Compare commits

..

6 Commits

Author SHA1 Message Date
kjs e42932d76c Merge pull request 'jskim-node' (#422) from jskim-node into main
Reviewed-on: http://39.117.244.52:3000/kjs/ERP-node/pulls/422
2026-03-19 09:47:45 +09:00
kjs 2690a3fe66 Merge branch 'main' into jskim-node 2026-03-19 09:47:40 +09:00
kjs 1064397be2 fix: update required field handling in V2Repeater and RepeaterTable components
- Modified the logic in the V2Repeater component to determine required fields based on the isNullable property, enhancing validation accuracy.
- Updated the RepeaterTable component to visually indicate required fields with an asterisk, improving user awareness during data entry.

These changes aim to enhance data validation and user experience by ensuring that required fields are clearly marked and accurately validated.
2026-03-19 09:47:15 +09:00
kjs 43a394df31 feat: add required field validation in V2Repeater component
- Implemented validation logic to ensure required fields are filled before saving data in the V2Repeater component.
- Added error messages to notify users of missing required fields, enhancing user experience and data integrity.
- Updated column configuration to include isRequired property for better handling of required fields.

These changes aim to improve data validation and user feedback during data entry processes.
2026-03-18 18:34:00 +09:00
kjs e5aa44e0d4 Merge branch 'jskim-node' of http://39.117.244.52:3000/kjs/ERP-node into jskim-node 2026-03-18 17:59:28 +09:00
kjs 5fa905f9ab refactor: simplify FileUploadComponent logic and remove unnecessary condition
- Removed the check for record mode in the FileUploadComponent, streamlining the file loading process.
- Updated the dependency array in the useEffect hook to exclude isRecordMode, ensuring cleaner and more efficient component behavior.

These changes aim to enhance the clarity and maintainability of the FileUploadComponent, improving overall functionality.
2026-03-18 17:59:27 +09:00
4 changed files with 27 additions and 7 deletions

4
.gitignore vendored
View File

@ -194,4 +194,6 @@ mcp-task-queue/
# 파이프라인 회고록 (자동 생성)
docs/retrospectives/
mes-architecture-guide.md
mes-architecture-guide.md
# MES Reference Documents
docs/mes-reference/

View File

@ -367,6 +367,20 @@ export const V2Repeater: React.FC<V2RepeaterProps> = ({
});
try {
// 🆕 필수값 검증
const requiredColumns = repeaterColumnsRef.current.filter(col => col.required);
for (let i = 0; i < currentData.length; i++) {
const row = currentData[i];
for (const col of requiredColumns) {
const val = row[col.field];
if (val === undefined || val === null || val === "") {
toast.error(`${i + 1}번째 행의 '${col.label}'은(는) 필수 입력 항목입니다.`);
window.dispatchEvent(new CustomEvent("repeaterSaveComplete"));
return;
}
}
}
let validColumns: Set<string> = new Set();
try {
const columnsResponse = await apiClient.get(`/table-management/tables/${tableName}/columns`);
@ -706,6 +720,7 @@ export const V2Repeater: React.FC<V2RepeaterProps> = ({
displayName: col.displayName || col.display_name || col.label || name,
detailSettings: col.detailSettings || col.detail_settings,
categoryRef: typeInfo?.categoryRef || null,
isRequired: col.isNullable === 'NO' || col.is_nullable === 'NO' || col.isRequired || col.is_required || col.notNull || col.not_null === true || col.not_null === 'Y' || col.not_null === 'y',
};
});
setCurrentTableColumnInfo(columnMap);
@ -808,10 +823,12 @@ export const V2Repeater: React.FC<V2RepeaterProps> = ({
loadSourceColumnLabels();
}, [resolvedSourceTable, isModalMode]);
const repeaterColumnsRef = useRef<RepeaterColumnConfig[]>([]);
// V2ColumnConfig → RepeaterColumnConfig 변환
// 🆕 모든 컬럼을 columns 배열의 순서대로 처리 (isSourceDisplay 플래그로 구분)
const repeaterColumns: RepeaterColumnConfig[] = useMemo(() => {
return config.columns
const cols = config.columns
.filter((col: V2ColumnConfig) => col.visible !== false)
.map((col: V2ColumnConfig): RepeaterColumnConfig => {
const colInfo = currentTableColumnInfo[col.key];
@ -858,12 +875,15 @@ export const V2Repeater: React.FC<V2RepeaterProps> = ({
type,
editable: col.editable !== false,
width: col.width === "auto" ? undefined : col.width,
required: false,
required: colInfo?.isRequired || false,
categoryRef, // 🆕 카테고리 참조 ID 전달
hidden: col.hidden, // 🆕 히든 처리
autoFill: col.autoFill, // 🆕 자동 입력 설정
};
});
repeaterColumnsRef.current = cols;
return cols;
}, [config.columns, sourceColumnLabels, currentTableColumnInfo, resolvedSourceTable, config.dataSource?.tableName]);
// 리피터 컬럼 설정에서 카테고리 타입 컬럼 자동 감지

View File

@ -792,6 +792,7 @@ export function RepeaterTable({
{/* 컬럼명 - 선택된 옵션라벨 형식으로 표시 */}
<span>
{activeOption?.headerLabel || `${col.label} - ${activeOption?.label || ""}`}
{col.required && <span className="text-destructive ml-1">*</span>}
</span>
<ChevronDown className="h-3 w-3 opacity-60" />
</button>

View File

@ -207,9 +207,6 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
return;
}
// 등록 모드(새 레코드)일 때는 이전 파일을 로드하지 않음
if (!isRecordMode) return;
const rawValue = String(imageObjidFromFormData);
// 콤마 구분 다중 objid 또는 단일 objid 모두 처리
const objids = rawValue.split(',').map(s => s.trim()).filter(s => /^\d+$/.test(s));
@ -265,7 +262,7 @@ const FileUploadComponent: React.FC<FileUploadComponentProps> = ({
console.error("🖼️ [FileUploadComponent] 파일 정보 조회 오류:", error);
}
})();
}, [imageObjidFromFormData, columnName, component.id, isRecordMode]);
}, [imageObjidFromFormData, columnName, component.id]);
// 🎯 화면설계 모드에서 실제 화면으로의 실시간 동기화 이벤트 리스너
// 🆕 columnName도 체크하여 같은 화면의 다른 파일 업로드 컴포넌트와 구분