summaryrefslogtreecommitdiff
path: root/components/form-data/spreadJS-dialog.tsx
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-10-03 13:55:08 +0900
committerjoonhoekim <26rote@gmail.com>2025-10-03 13:55:08 +0900
commitfca5e37d43543ed1e6e680a779d340b1cc4427cd (patch)
tree5835c5c06dd76cbaf6c411b38ffe38c17ec7fc8a /components/form-data/spreadJS-dialog.tsx
parent8945be5ea89365f8a686a0e65b5a7d5b61c2ca20 (diff)
(김준회) spreadjs dialog client error 처리
Diffstat (limited to 'components/form-data/spreadJS-dialog.tsx')
-rw-r--r--components/form-data/spreadJS-dialog.tsx99
1 files changed, 65 insertions, 34 deletions
diff --git a/components/form-data/spreadJS-dialog.tsx b/components/form-data/spreadJS-dialog.tsx
index 375c097c..272d99be 100644
--- a/components/form-data/spreadJS-dialog.tsx
+++ b/components/form-data/spreadJS-dialog.tsx
@@ -189,6 +189,11 @@ export function TemplateViewDialog({
}, [columnsJSON]);
const isValidTemplate = React.useCallback((template: TemplateItem): boolean => {
+ // 🔍 TMPL_ID 필수 검증 추가
+ if (!template || !template.TMPL_ID || typeof template.TMPL_ID !== 'string') {
+ console.warn('⚠️ Invalid template: missing or invalid TMPL_ID', template);
+ return false;
+ }
return determineTemplateType(template) !== null;
}, [determineTemplateType]);
@@ -270,29 +275,43 @@ export function TemplateViewDialog({
if (validTemplates.length > 0 && !selectedTemplateId) {
const firstTemplate = validTemplates[0];
- const templateTypeToSet = determineTemplateType(firstTemplate);
- setSelectedTemplateId(firstTemplate.TMPL_ID);
- setTemplateType(templateTypeToSet);
+ // 🔍 TMPL_ID 검증 (isValidTemplate로 필터링했으므로 존재해야 하지만 안전장치)
+ if (firstTemplate?.TMPL_ID) {
+ const templateTypeToSet = determineTemplateType(firstTemplate);
+ setSelectedTemplateId(firstTemplate.TMPL_ID);
+ setTemplateType(templateTypeToSet);
+ } else {
+ console.error('❌ First valid template has no TMPL_ID:', firstTemplate);
+ }
}
}, [templateData, selectedTemplateId, isValidTemplate, determineTemplateType, columnsJSON]);
const handleTemplateChange = (templateId: string) => {
- const template = availableTemplates.find(t => t.TMPL_ID === templateId);
- if (template) {
- const templateTypeToSet = determineTemplateType(template);
- setSelectedTemplateId(templateId);
- setTemplateType(templateTypeToSet);
- setHasChanges(false);
- setValidationErrors([]);
-
- if (currentSpread && template) {
- initSpread(currentSpread, template);
- }
+ const template = availableTemplates.find(t => t?.TMPL_ID === templateId);
+
+ // 🔍 템플릿과 TMPL_ID 검증
+ if (!template || !template.TMPL_ID) {
+ console.error('❌ Template not found or invalid TMPL_ID:', templateId);
+ return;
+ }
+
+ const templateTypeToSet = determineTemplateType(template);
+ setSelectedTemplateId(templateId);
+ setTemplateType(templateTypeToSet);
+ setHasChanges(false);
+ setValidationErrors([]);
+
+ if (currentSpread) {
+ initSpread(currentSpread, template);
}
};
const selectedTemplate = React.useMemo(() => {
- return availableTemplates.find(t => t.TMPL_ID === selectedTemplateId);
+ const found = availableTemplates.find(t => t?.TMPL_ID === selectedTemplateId);
+ if (!found && selectedTemplateId) {
+ console.warn('⚠️ Selected template not found:', selectedTemplateId);
+ }
+ return found;
}, [availableTemplates, selectedTemplateId]);
const editableFields = React.useMemo(() => {
@@ -1293,17 +1312,29 @@ export function TemplateViewDialog({
}, [selectedTemplate, templateType, selectedRow, tableData, updateProgress, getSafeActiveSheet, createGrdListTableOptimized, setBatchValues, setBatchStyles, setupSheetProtectionAndEvents, setCellMappings, createCellStyle, isFieldEditable, columnsJSON, setupOptimizedListValidation, parseCellAddress, ensureRowCapacity, getCellAddress]);
React.useEffect(() => {
- if (!selectedTemplateId) {
+ // 🔍 안전성 검증: availableTemplates가 있고, selectedTemplateId가 없을 때만 실행
+ if (!selectedTemplateId && availableTemplates.length > 0) {
const only = availableTemplates[0];
+
+ // 🔍 TMPL_ID 검증
+ if (!only || !only.TMPL_ID) {
+ console.error('❌ First template has no TMPL_ID:', only);
+ return;
+ }
+
const type = determineTemplateType(only);
+
+ // 🔍 type이 null이 아닐 때만 진행
+ if (!type) {
+ console.warn('⚠️ Could not determine template type for:', only);
+ return;
+ }
// 선택되어 있지 않다면 자동 선택
- if (selectedTemplateId !== only.TMPL_ID) {
- setSelectedTemplateId(only.TMPL_ID);
- setTemplateType(type);
- }
+ setSelectedTemplateId(only.TMPL_ID);
+ setTemplateType(type);
- // 이미 스프레드가 마운트되어 있다면 즉시 초기화(선택 변경만으로도 리렌더되지만 안전하게 보강)
+ // 이미 스프레드가 마운트되어 있다면 즉시 초기화
if (currentSpread) {
initSpread(currentSpread, only);
}
@@ -1313,9 +1344,7 @@ export function TemplateViewDialog({
selectedTemplateId,
currentSpread,
determineTemplateType,
- initSpread,
- setTemplateType,
- setSelectedTemplateId
+ initSpread
]);
const handleSaveChanges = React.useCallback(async () => {
@@ -1491,8 +1520,8 @@ export function TemplateViewDialog({
<DialogTitle>SEDP Template - {formCode}</DialogTitle>
<DialogDescription>
<div className="space-y-3">
- {availableTemplates.length > 0 ? (
- // 템플릿이 2개 이상일 때: Select 박스 표시
+ {availableTemplates.length > 1 ? (
+ // 🔍 템플릿이 2개 이상일 때: Select 박스 표시
<div className="flex items-center gap-4">
<span className="text-sm font-medium">Template:</span>
<Select value={selectedTemplateId} onValueChange={handleTemplateChange}>
@@ -1500,20 +1529,22 @@ export function TemplateViewDialog({
<SelectValue placeholder="Select a template" />
</SelectTrigger>
<SelectContent>
- {availableTemplates.map(template => (
- <SelectItem key={template.TMPL_ID} value={template.TMPL_ID}>
- {template.NAME} ({template.TMPL_TYPE})
- </SelectItem>
- ))}
+ {availableTemplates
+ .filter(template => template?.TMPL_ID) // 🔍 TMPL_ID가 있는 것만 표시
+ .map(template => (
+ <SelectItem key={template.TMPL_ID} value={template.TMPL_ID}>
+ {template.NAME || 'Unnamed'} ({template.TMPL_TYPE || 'Unknown'})
+ </SelectItem>
+ ))}
</SelectContent>
</Select>
</div>
) : availableTemplates.length === 1 ? (
- // 템플릿이 정확히 1개일 때: 템플릿 이름을 텍스트로 표시
+ // 🔍 템플릿이 정확히 1개일 때: 템플릿 이름을 텍스트로 표시
<div className="flex items-center gap-4">
<span className="text-sm font-medium">Template:</span>
<span className="text-sm text-blue-600 font-medium">
- {availableTemplates[0].NAME} ({availableTemplates[0].TMPL_TYPE})
+ {availableTemplates[0]?.NAME || 'Unnamed'} ({availableTemplates[0]?.TMPL_TYPE || 'Unknown'})
</span>
</div>
) : null}
@@ -1581,7 +1612,7 @@ export function TemplateViewDialog({
{selectedTemplate && isClient && isDataValid ? (
<SpreadSheets
- key={`${templateType}-${selectedTemplate.TMPL_ID}-${selectedTemplateId}`}
+ key={`${templateType}-${selectedTemplate?.TMPL_ID || 'unknown'}-${selectedTemplateId}`}
workbookInitialized={initSpread}
hostStyle={hostStyle}
/>