커스텀 훅 분리 및 react query 최적화
This commit is contained in:
@@ -14,23 +14,10 @@ import { useCodes, useDeleteCode, useReorderCodes } from "@/hooks/queries/useCod
|
||||
import type { CodeInfo } from "@/types/commonCode";
|
||||
|
||||
// Drag and Drop
|
||||
import {
|
||||
DndContext,
|
||||
closestCenter,
|
||||
KeyboardSensor,
|
||||
PointerSensor,
|
||||
useSensor,
|
||||
useSensors,
|
||||
DragOverlay,
|
||||
type DragStartEvent,
|
||||
type DragEndEvent,
|
||||
} from "@dnd-kit/core";
|
||||
import {
|
||||
arrayMove,
|
||||
SortableContext,
|
||||
sortableKeyboardCoordinates,
|
||||
verticalListSortingStrategy,
|
||||
} from "@dnd-kit/sortable";
|
||||
import { DndContext, DragOverlay } from "@dnd-kit/core";
|
||||
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { useDragAndDrop } from "@/hooks/useDragAndDrop";
|
||||
import { useSearchAndFilter } from "@/hooks/useSearchAndFilter";
|
||||
|
||||
interface CodeDetailPanelProps {
|
||||
categoryCode: string;
|
||||
@@ -42,35 +29,36 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
||||
const deleteCodeMutation = useDeleteCode();
|
||||
const reorderCodesMutation = useReorderCodes();
|
||||
|
||||
// 로컬 상태
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [showActiveOnly, setShowActiveOnly] = useState(false);
|
||||
// 검색 및 필터링 훅 사용
|
||||
const {
|
||||
searchTerm,
|
||||
setSearchTerm,
|
||||
showActiveOnly,
|
||||
setShowActiveOnly,
|
||||
filteredItems: filteredCodes,
|
||||
} = useSearchAndFilter(codes, {
|
||||
searchFields: ["code_name", "code_value"],
|
||||
});
|
||||
|
||||
// 모달 상태
|
||||
const [showFormModal, setShowFormModal] = useState(false);
|
||||
const [editingCode, setEditingCode] = useState<CodeInfo | null>(null);
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||
const [deletingCode, setDeletingCode] = useState<CodeInfo | null>(null);
|
||||
|
||||
// 드래그 상태
|
||||
const [activeId, setActiveId] = useState<string | null>(null);
|
||||
|
||||
// Drag and Drop 센서
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor),
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
}),
|
||||
);
|
||||
|
||||
// 필터링된 코드 목록
|
||||
const filteredCodes = codes.filter((code) => {
|
||||
const matchesSearch =
|
||||
code.code_name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
code.code_value.toLowerCase().includes(searchTerm.toLowerCase());
|
||||
|
||||
const matchesActive = !showActiveOnly || code.is_active === "Y";
|
||||
|
||||
return matchesSearch && matchesActive;
|
||||
// 드래그 앤 드롭 훅 사용
|
||||
const dragAndDrop = useDragAndDrop({
|
||||
items: filteredCodes,
|
||||
onReorder: async (reorderedItems) => {
|
||||
await reorderCodesMutation.mutateAsync({
|
||||
categoryCode,
|
||||
codes: reorderedItems.map((item) => ({
|
||||
codeValue: item.id,
|
||||
sortOrder: item.sortOrder,
|
||||
})),
|
||||
});
|
||||
},
|
||||
getItemId: (code) => code.code_value,
|
||||
});
|
||||
|
||||
// 새 코드 생성
|
||||
@@ -108,38 +96,7 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
||||
}
|
||||
};
|
||||
|
||||
// 드래그 시작 핸들러
|
||||
const handleDragStart = (event: DragStartEvent) => {
|
||||
setActiveId(event.active.id as string);
|
||||
};
|
||||
|
||||
// 드래그 앤 드롭 처리
|
||||
const handleDragEnd = async (event: DragEndEvent) => {
|
||||
setActiveId(null);
|
||||
const { active, over } = event;
|
||||
|
||||
if (over && active.id !== over.id) {
|
||||
const oldIndex = filteredCodes.findIndex((code) => code.code_value === active.id);
|
||||
const newIndex = filteredCodes.findIndex((code) => code.code_value === over.id);
|
||||
|
||||
const newOrder = arrayMove(filteredCodes, oldIndex, newIndex);
|
||||
|
||||
// 순서 업데이트를 위한 데이터 준비
|
||||
const reorderData = newOrder.map((code, index) => ({
|
||||
codeValue: code.code_value,
|
||||
sortOrder: index + 1,
|
||||
}));
|
||||
|
||||
try {
|
||||
await reorderCodesMutation.mutateAsync({
|
||||
categoryCode,
|
||||
codes: reorderData,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("코드 순서 변경 실패:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
// 드래그 앤 드롭 로직은 useDragAndDrop 훅에서 처리
|
||||
|
||||
if (!categoryCode) {
|
||||
return (
|
||||
@@ -213,12 +170,7 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
||||
</div>
|
||||
) : (
|
||||
<div className="p-2">
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragStart={handleDragStart}
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<DndContext {...dragAndDrop.dndContextProps}>
|
||||
<SortableContext
|
||||
items={filteredCodes.map((code) => code.code_value)}
|
||||
strategy={verticalListSortingStrategy}
|
||||
@@ -237,10 +189,10 @@ export function CodeDetailPanel({ categoryCode }: CodeDetailPanelProps) {
|
||||
</SortableContext>
|
||||
|
||||
<DragOverlay>
|
||||
{activeId ? (
|
||||
{dragAndDrop.activeItem ? (
|
||||
<div className="cursor-grabbing rounded-lg border border-gray-300 bg-white p-3 shadow-lg">
|
||||
{(() => {
|
||||
const activeCode = filteredCodes.find((code) => code.code_value === activeId);
|
||||
const activeCode = dragAndDrop.activeItem;
|
||||
if (!activeCode) return null;
|
||||
return (
|
||||
<div className="flex items-start justify-between">
|
||||
|
||||
Reference in New Issue
Block a user