코드 활성/비활성화 해결 #78
|
|
@ -65,12 +65,26 @@ export class CommonCodeController {
|
|||
|
||||
// 프론트엔드가 기대하는 형식으로 데이터 변환
|
||||
const transformedData = result.data.map((code: any) => ({
|
||||
// 새로운 필드명 (카멜케이스)
|
||||
codeValue: code.code_value,
|
||||
codeName: code.code_name,
|
||||
codeNameEng: code.code_name_eng,
|
||||
description: code.description,
|
||||
sortOrder: code.sort_order,
|
||||
isActive: code.is_active === "Y",
|
||||
isActive: code.is_active,
|
||||
useYn: code.is_active,
|
||||
|
||||
// 기존 필드명도 유지 (하위 호환성)
|
||||
code_category: code.code_category,
|
||||
code_value: code.code_value,
|
||||
code_name: code.code_name,
|
||||
code_name_eng: code.code_name_eng,
|
||||
sort_order: code.sort_order,
|
||||
is_active: code.is_active,
|
||||
created_date: code.created_date,
|
||||
created_by: code.created_by,
|
||||
updated_date: code.updated_date,
|
||||
updated_by: code.updated_by,
|
||||
}));
|
||||
|
||||
return res.json({
|
||||
|
|
|
|||
|
|
@ -276,8 +276,11 @@ export class CommonCodeService {
|
|||
updatedBy: string
|
||||
) {
|
||||
try {
|
||||
// 디버깅: 받은 데이터 로그
|
||||
logger.info(`코드 수정 데이터:`, { categoryCode, codeValue, data });
|
||||
// codeValue가 undefined이거나 빈 문자열인지 확인
|
||||
if (!codeValue || codeValue === 'undefined') {
|
||||
throw new Error(`잘못된 코드 값입니다: ${codeValue}`);
|
||||
}
|
||||
|
||||
const code = await prisma.code_info.update({
|
||||
where: {
|
||||
code_category_code_value: {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
|||
})),
|
||||
});
|
||||
},
|
||||
getItemId: (code: CodeInfo) => code.code_value,
|
||||
getItemId: (code: CodeInfo) => code.codeValue || code.code_value,
|
||||
});
|
||||
|
||||
// 새 코드 생성
|
||||
|
|
@ -95,7 +95,7 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
|||
try {
|
||||
await deleteCodeMutation.mutateAsync({
|
||||
categoryCode,
|
||||
codeValue: deletingCode.code_value,
|
||||
codeValue: deletingCode.codeValue || deletingCode.code_value,
|
||||
});
|
||||
|
||||
setShowDeleteModal(false);
|
||||
|
|
@ -182,13 +182,13 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
|||
<div className="p-2">
|
||||
<DndContext {...dragAndDrop.dndContextProps}>
|
||||
<SortableContext
|
||||
items={filteredCodes.map((code) => code.code_value)}
|
||||
items={filteredCodes.map((code) => code.codeValue || code.code_value)}
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
<div className="space-y-1">
|
||||
{filteredCodes.map((code, index) => (
|
||||
<SortableCodeItem
|
||||
key={`${code.code_value}-${index}`}
|
||||
key={`${code.codeValue || code.code_value}-${index}`}
|
||||
code={code}
|
||||
categoryCode={categoryCode}
|
||||
onEdit={() => handleEditCode(code)}
|
||||
|
|
@ -208,20 +208,28 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
|||
<div className="flex items-start justify-between">
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className="font-medium text-gray-900">{activeCode.code_name}</h3>
|
||||
<h3 className="font-medium text-gray-900">
|
||||
{activeCode.codeName || activeCode.code_name}
|
||||
</h3>
|
||||
<Badge
|
||||
variant={activeCode.is_active === "Y" ? "default" : "secondary"}
|
||||
variant={
|
||||
activeCode.isActive === "Y" || activeCode.is_active === "Y"
|
||||
? "default"
|
||||
: "secondary"
|
||||
}
|
||||
className={cn(
|
||||
"transition-colors",
|
||||
activeCode.is_active === "Y"
|
||||
activeCode.isActive === "Y" || activeCode.is_active === "Y"
|
||||
? "bg-green-100 text-green-800"
|
||||
: "bg-gray-100 text-gray-600",
|
||||
)}
|
||||
>
|
||||
{activeCode.is_active === "Y" ? "활성" : "비활성"}
|
||||
{activeCode.isActive === "Y" || activeCode.is_active === "Y" ? "활성" : "비활성"}
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-gray-600">{activeCode.code_value}</p>
|
||||
<p className="mt-1 text-sm text-gray-600">
|
||||
{activeCode.codeValue || activeCode.code_value}
|
||||
</p>
|
||||
{activeCode.description && (
|
||||
<p className="mt-1 text-sm text-gray-500">{activeCode.description}</p>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode, code
|
|||
categoryCode,
|
||||
"codeValue",
|
||||
validationStates.codeValue.value,
|
||||
isEditing ? editingCode?.code_value : undefined,
|
||||
isEditing ? editingCode?.codeValue || editingCode?.code_value : undefined,
|
||||
validationStates.codeValue.enabled,
|
||||
);
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode, code
|
|||
categoryCode,
|
||||
"codeName",
|
||||
validationStates.codeName.value,
|
||||
isEditing ? editingCode?.code_value : undefined,
|
||||
isEditing ? editingCode?.codeValue || editingCode?.code_value : undefined,
|
||||
validationStates.codeName.enabled,
|
||||
);
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode, code
|
|||
categoryCode,
|
||||
"codeNameEng",
|
||||
validationStates.codeNameEng.value,
|
||||
isEditing ? editingCode?.code_value : undefined,
|
||||
isEditing ? editingCode?.codeValue || editingCode?.code_value : undefined,
|
||||
validationStates.codeNameEng.enabled,
|
||||
);
|
||||
|
||||
|
|
@ -102,18 +102,18 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode, code
|
|||
if (isEditing && editingCode) {
|
||||
// 수정 모드: 기존 데이터 로드 (codeValue는 표시용으로만 설정)
|
||||
form.reset({
|
||||
codeName: editingCode.code_name,
|
||||
codeNameEng: editingCode.code_name_eng || "",
|
||||
codeName: editingCode.codeName || editingCode.code_name,
|
||||
codeNameEng: editingCode.codeNameEng || editingCode.code_name_eng || "",
|
||||
description: editingCode.description || "",
|
||||
sortOrder: editingCode.sort_order,
|
||||
isActive: editingCode.is_active as "Y" | "N", // 타입 캐스팅
|
||||
sortOrder: editingCode.sortOrder || editingCode.sort_order,
|
||||
isActive: (editingCode.isActive || editingCode.is_active) as "Y" | "N", // 타입 캐스팅
|
||||
});
|
||||
|
||||
// codeValue는 별도로 설정 (표시용)
|
||||
form.setValue("codeValue" as any, editingCode.code_value);
|
||||
form.setValue("codeValue" as any, editingCode.codeValue || editingCode.code_value);
|
||||
} else {
|
||||
// 새 코드 모드: 자동 순서 계산
|
||||
const maxSortOrder = codes.length > 0 ? Math.max(...codes.map((c) => c.sort_order)) : 0;
|
||||
const maxSortOrder = codes.length > 0 ? Math.max(...codes.map((c) => c.sortOrder || c.sort_order)) : 0;
|
||||
|
||||
form.reset({
|
||||
codeValue: "",
|
||||
|
|
@ -132,7 +132,7 @@ export function CodeFormModal({ isOpen, onClose, categoryCode, editingCode, code
|
|||
// 수정
|
||||
await updateCodeMutation.mutateAsync({
|
||||
categoryCode,
|
||||
codeValue: editingCode.code_value,
|
||||
codeValue: editingCode.codeValue || editingCode.code_value,
|
||||
data: data as UpdateCodeData,
|
||||
});
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export function SortableCodeItem({
|
|||
isDragOverlay = false,
|
||||
}: SortableCodeItemProps) {
|
||||
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
||||
id: code.code_value,
|
||||
id: code.codeValue || code.code_value,
|
||||
disabled: isDragOverlay,
|
||||
});
|
||||
const updateCodeMutation = useUpdateCode();
|
||||
|
|
@ -39,14 +39,20 @@ export function SortableCodeItem({
|
|||
// 활성/비활성 토글 핸들러
|
||||
const handleToggleActive = async (checked: boolean) => {
|
||||
try {
|
||||
// codeValue 또는 code_value가 없으면 에러 처리
|
||||
const codeValue = code.codeValue || code.code_value;
|
||||
if (!codeValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
await updateCodeMutation.mutateAsync({
|
||||
categoryCode,
|
||||
codeValue: code.code_value,
|
||||
codeValue: codeValue,
|
||||
data: {
|
||||
codeName: code.code_name,
|
||||
codeNameEng: code.code_name_eng || "",
|
||||
codeName: code.codeName || code.code_name,
|
||||
codeNameEng: code.codeNameEng || code.code_name_eng || "",
|
||||
description: code.description || "",
|
||||
sortOrder: code.sort_order,
|
||||
sortOrder: code.sortOrder || code.sort_order,
|
||||
isActive: checked ? "Y" : "N",
|
||||
},
|
||||
});
|
||||
|
|
@ -70,12 +76,12 @@ export function SortableCodeItem({
|
|||
<div className="flex items-start justify-between">
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className="font-medium text-gray-900">{code.code_name}</h3>
|
||||
<h3 className="font-medium text-gray-900">{code.codeName || code.code_name}</h3>
|
||||
<Badge
|
||||
variant={code.is_active === "Y" ? "default" : "secondary"}
|
||||
variant={code.isActive === "Y" || code.is_active === "Y" ? "default" : "secondary"}
|
||||
className={cn(
|
||||
"cursor-pointer transition-colors",
|
||||
code.is_active === "Y"
|
||||
code.isActive === "Y" || code.is_active === "Y"
|
||||
? "bg-green-100 text-green-800 hover:bg-green-200 hover:text-green-900"
|
||||
: "bg-gray-100 text-gray-600 hover:bg-gray-200 hover:text-gray-700",
|
||||
updateCodeMutation.isPending && "cursor-not-allowed opacity-50",
|
||||
|
|
@ -84,16 +90,17 @@ export function SortableCodeItem({
|
|||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (!updateCodeMutation.isPending) {
|
||||
handleToggleActive(code.is_active !== "Y");
|
||||
const isActive = code.isActive === "Y" || code.is_active === "Y";
|
||||
handleToggleActive(!isActive);
|
||||
}
|
||||
}}
|
||||
onPointerDown={(e) => e.stopPropagation()}
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
>
|
||||
{code.is_active === "Y" ? "활성" : "비활성"}
|
||||
{code.isActive === "Y" || code.is_active === "Y" ? "활성" : "비활성"}
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-gray-600">{code.code_value}</p>
|
||||
<p className="mt-1 text-sm text-gray-600">{code.codeValue || code.code_value}</p>
|
||||
{code.description && <p className="mt-1 text-sm text-gray-500">{code.description}</p>}
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,13 +17,22 @@ export interface CodeCategory {
|
|||
export type CategoryInfo = CodeCategory;
|
||||
|
||||
export interface CodeInfo {
|
||||
code_category: string;
|
||||
code_value: string;
|
||||
code_name: string;
|
||||
code_name_eng?: string | null;
|
||||
// 백엔드 응답 필드 (변환된 형태)
|
||||
codeValue?: string;
|
||||
codeName?: string;
|
||||
codeNameEng?: string | null;
|
||||
description?: string | null;
|
||||
sort_order: number;
|
||||
is_active: string;
|
||||
sortOrder?: number;
|
||||
isActive?: string | boolean;
|
||||
useYn?: string;
|
||||
|
||||
// 기존 필드 (하위 호환성을 위해 유지)
|
||||
code_category?: string;
|
||||
code_value?: string;
|
||||
code_name?: string;
|
||||
code_name_eng?: string | null;
|
||||
sort_order?: number;
|
||||
is_active?: string;
|
||||
created_date?: string | null;
|
||||
created_by?: string | null;
|
||||
updated_date?: string | null;
|
||||
|
|
|
|||
Loading…
Reference in New Issue