feat: NumberingRuleDesigner에서 파트 업데이트 및 삭제 로직 개선
- 파트 업데이트 및 삭제 시 id 대신 order를 사용하여 로직을 개선하였습니다. - savedRules 상태 업데이트 시 깊은 복사를 통해 객체 참조를 분리하여 클로저 문제를 방지하였습니다. - 규칙 선택 시 깊은 복사를 통해 좌측 목록과 편집 영역의 객체가 공유되지 않도록 하여 데이터 무결성을 강화하였습니다. - 관련 로깅을 추가하여 상태 변경 시 디버깅을 용이하게 하였습니다.
This commit is contained in:
parent
d28e703cd2
commit
34202be843
|
|
@ -260,22 +260,24 @@ export const NumberingRuleDesigner: React.FC<NumberingRuleDesignerProps> = ({
|
||||||
toast.success(`규칙 ${newPart.order}가 추가되었습니다`);
|
toast.success(`규칙 ${newPart.order}가 추가되었습니다`);
|
||||||
}, [currentRule, maxRules]);
|
}, [currentRule, maxRules]);
|
||||||
|
|
||||||
const handleUpdatePart = useCallback((partId: string, updates: Partial<NumberingRulePart>) => {
|
// partOrder 기반으로 파트 업데이트 (id가 null일 수 있으므로 order 사용)
|
||||||
|
const handleUpdatePart = useCallback((partOrder: number, updates: Partial<NumberingRulePart>) => {
|
||||||
setCurrentRule((prev) => {
|
setCurrentRule((prev) => {
|
||||||
if (!prev) return null;
|
if (!prev) return null;
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
parts: prev.parts.map((part) => (part.id === partId ? { ...part, ...updates } : part)),
|
parts: prev.parts.map((part) => (part.order === partOrder ? { ...part, ...updates } : part)),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleDeletePart = useCallback((partId: string) => {
|
// partOrder 기반으로 파트 삭제 (id가 null일 수 있으므로 order 사용)
|
||||||
|
const handleDeletePart = useCallback((partOrder: number) => {
|
||||||
setCurrentRule((prev) => {
|
setCurrentRule((prev) => {
|
||||||
if (!prev) return null;
|
if (!prev) return null;
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
parts: prev.parts.filter((part) => part.id !== partId).map((part, index) => ({ ...part, order: index + 1 })),
|
parts: prev.parts.filter((part) => part.order !== partOrder).map((part, index) => ({ ...part, order: index + 1 })),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -295,8 +297,6 @@ export const NumberingRuleDesigner: React.FC<NumberingRuleDesignerProps> = ({
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const existing = savedRules.find((r) => r.ruleId === currentRule.ruleId);
|
|
||||||
|
|
||||||
// 파트별 기본 autoConfig 정의
|
// 파트별 기본 autoConfig 정의
|
||||||
const defaultAutoConfigs: Record<string, any> = {
|
const defaultAutoConfigs: Record<string, any> = {
|
||||||
sequence: { sequenceLength: 3, startFrom: 1 },
|
sequence: { sequenceLength: 3, startFrom: 1 },
|
||||||
|
|
@ -345,15 +345,30 @@ export const NumberingRuleDesigner: React.FC<NumberingRuleDesignerProps> = ({
|
||||||
const response = await saveNumberingRuleToTest(ruleToSave);
|
const response = await saveNumberingRuleToTest(ruleToSave);
|
||||||
|
|
||||||
if (response.success && response.data) {
|
if (response.success && response.data) {
|
||||||
|
// 깊은 복사하여 savedRules와 currentRule이 다른 객체를 참조하도록 함
|
||||||
|
const currentData = JSON.parse(JSON.stringify(response.data)) as NumberingRuleConfig;
|
||||||
|
|
||||||
|
// setSavedRules 내부에서 prev를 사용해서 existing 확인 (클로저 문제 방지)
|
||||||
setSavedRules((prev) => {
|
setSavedRules((prev) => {
|
||||||
if (existing) {
|
const savedData = JSON.parse(JSON.stringify(response.data)) as NumberingRuleConfig;
|
||||||
return prev.map((r) => (r.ruleId === ruleToSave.ruleId ? response.data! : r));
|
const existsInPrev = prev.some((r) => r.ruleId === ruleToSave.ruleId);
|
||||||
|
|
||||||
|
console.log("🔍 [handleSave] setSavedRules:", {
|
||||||
|
ruleId: ruleToSave.ruleId,
|
||||||
|
existsInPrev,
|
||||||
|
prevCount: prev.length,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existsInPrev) {
|
||||||
|
// 기존 규칙 업데이트
|
||||||
|
return prev.map((r) => (r.ruleId === ruleToSave.ruleId ? savedData : r));
|
||||||
} else {
|
} else {
|
||||||
return [...prev, response.data!];
|
// 새 규칙 추가
|
||||||
|
return [...prev, savedData];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setCurrentRule(response.data);
|
setCurrentRule(currentData);
|
||||||
setSelectedRuleId(response.data.ruleId);
|
setSelectedRuleId(response.data.ruleId);
|
||||||
|
|
||||||
await onSave?.(response.data);
|
await onSave?.(response.data);
|
||||||
|
|
@ -366,11 +381,27 @@ export const NumberingRuleDesigner: React.FC<NumberingRuleDesignerProps> = ({
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}, [currentRule, savedRules, onSave, currentTableName]);
|
}, [currentRule, onSave, currentTableName, menuObjid]);
|
||||||
|
|
||||||
const handleSelectRule = useCallback((rule: NumberingRuleConfig) => {
|
const handleSelectRule = useCallback((rule: NumberingRuleConfig) => {
|
||||||
|
console.log("🔍 [handleSelectRule] 규칙 선택:", {
|
||||||
|
ruleId: rule.ruleId,
|
||||||
|
ruleName: rule.ruleName,
|
||||||
|
partsCount: rule.parts?.length || 0,
|
||||||
|
parts: rule.parts?.map(p => ({ id: p.id, order: p.order, partType: p.partType })),
|
||||||
|
});
|
||||||
|
|
||||||
setSelectedRuleId(rule.ruleId);
|
setSelectedRuleId(rule.ruleId);
|
||||||
setCurrentRule(rule);
|
// 깊은 복사하여 객체 참조 분리 (좌측 목록과 편집 영역의 객체가 공유되지 않도록)
|
||||||
|
const ruleCopy = JSON.parse(JSON.stringify(rule)) as NumberingRuleConfig;
|
||||||
|
|
||||||
|
console.log("🔍 [handleSelectRule] 깊은 복사 후:", {
|
||||||
|
ruleId: ruleCopy.ruleId,
|
||||||
|
partsCount: ruleCopy.parts?.length || 0,
|
||||||
|
parts: ruleCopy.parts?.map(p => ({ id: p.id, order: p.order, partType: p.partType })),
|
||||||
|
});
|
||||||
|
|
||||||
|
setCurrentRule(ruleCopy);
|
||||||
toast.info(`"${rule.ruleName}" 규칙을 불러왔습니다`);
|
toast.info(`"${rule.ruleName}" 규칙을 불러왔습니다`);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
@ -595,12 +626,12 @@ export const NumberingRuleDesigner: React.FC<NumberingRuleDesignerProps> = ({
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
|
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
|
||||||
{currentRule.parts.map((part) => (
|
{currentRule.parts.map((part, index) => (
|
||||||
<NumberingRuleCard
|
<NumberingRuleCard
|
||||||
key={part.id}
|
key={`part-${part.order}-${index}`}
|
||||||
part={part}
|
part={part}
|
||||||
onUpdate={(updates) => handleUpdatePart(part.id, updates)}
|
onUpdate={(updates) => handleUpdatePart(part.order, updates)}
|
||||||
onDelete={() => handleDeletePart(part.id)}
|
onDelete={() => handleDeletePart(part.order)}
|
||||||
isPreview={isPreview}
|
isPreview={isPreview}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue