From fefca6304eefea94f41057f9f934b0e19ceb54bb Mon Sep 17 00:00:00 2001 From: 0-Zz-ang Date: Fri, 22 Aug 2025 13:47:37 +0900 Subject: (박서영)Compliance 설문/응답 리스트 생성 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compliance-questions-draggable-list.tsx | 157 +++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 lib/compliance/questions/compliance-questions-draggable-list.tsx (limited to 'lib/compliance/questions/compliance-questions-draggable-list.tsx') diff --git a/lib/compliance/questions/compliance-questions-draggable-list.tsx b/lib/compliance/questions/compliance-questions-draggable-list.tsx new file mode 100644 index 00000000..6a226b54 --- /dev/null +++ b/lib/compliance/questions/compliance-questions-draggable-list.tsx @@ -0,0 +1,157 @@ +"use client"; + +import * as React from "react"; +import { Badge } from "@/components/ui/badge"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; +import { Sortable, SortableDragHandle, SortableItem } from "@/components/ui/sortable"; +import { GripVertical } from "lucide-react"; +import { complianceQuestions } from "@/db/schema/compliance"; +import { ComplianceQuestionEditSheet } from "./compliance-question-edit-sheet"; +import { ComplianceQuestionDeleteDialog } from "./compliance-question-delete-dialog"; +import { updateComplianceQuestion } from "@/lib/compliance/services"; +import { toast } from "sonner"; +import { useRouter } from "next/navigation"; + +interface SortableQuestionItemProps { + question: typeof complianceQuestions.$inferSelect; + onSuccess?: () => void; +} + +function SortableQuestionItem({ question, onSuccess }: SortableQuestionItemProps) { + return ( + + + +
+ + + + {question.questionNumber} + {question.questionText} +
+ + +
+
+
+ +
+
+
+ 질문 타입: + {question.questionType} +
+
+ 필수 여부: + + {question.isRequired ? '필수' : '선택'} + +
+
+ 상세 설명: + + {question.hasDetailText ? '필요' : '불필요'} + +
+
+ 파일 업로드: + + {question.hasFileUpload ? '필요' : '불필요'} + +
+
+ {question.conditionalValue && ( +
+ 조건: {question.conditionalValue} +
+ )} +
+
+
+
+ ); +} + +interface ComplianceQuestionsDraggableListProps { + questions: typeof complianceQuestions.$inferSelect[]; + onSuccess?: () => void; +} + +export function ComplianceQuestionsDraggableList({ + questions, + onSuccess +}: ComplianceQuestionsDraggableListProps) { + const [items, setItems] = React.useState(questions); + const router = useRouter(); + + React.useEffect(() => { + setItems(questions); + }, [questions]); + + const handleValueChange = async (newItems: typeof complianceQuestions.$inferSelect[]) => { + setItems(newItems); + + // 새로운 순서로 displayOrder 업데이트 + const updatedItems = newItems.map((item, index) => ({ + ...item, + displayOrder: index + 1, + })); + + // 서버에 순서 업데이트 + await updateDisplayOrders(updatedItems); + }; + + const updateDisplayOrders = async (updatedItems: typeof complianceQuestions.$inferSelect[]) => { + try { + // 각 질문의 displayOrder를 순차적으로 업데이트 + await Promise.all( + updatedItems.map((item, index) => + updateComplianceQuestion(item.id, { + displayOrder: index + 1, + }) + ) + ); + + toast.success("질문 순서가 업데이트되었습니다."); + router.refresh(); + + if (onSuccess) { + onSuccess(); + } + } catch (error) { + console.error("Error updating question order:", error); + toast.error("질문 순서 업데이트 중 오류가 발생했습니다."); + } + }; + + if (items.length === 0) { + return ( +
+ 아직 질문이 없습니다. 질문을 추가해보세요. +
+ ); + } + + return ( + + + {items.map((question) => ( + + ))} + + + ); +} -- cgit v1.2.3