From 35ad6fd173e9f937f86a00d07ed4c08ae41326cc Mon Sep 17 00:00:00 2001 From: 0-Zz-ang Date: Mon, 25 Aug 2025 14:10:48 +0900 Subject: compliance 조건부 질문 관련사항 수정 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../compliance-question-create-dialog.tsx | 173 +++++++--------- .../questions/compliance-question-edit-sheet.tsx | 230 +++++++++++++-------- 2 files changed, 222 insertions(+), 181 deletions(-) (limited to 'lib/compliance/questions') diff --git a/lib/compliance/questions/compliance-question-create-dialog.tsx b/lib/compliance/questions/compliance-question-create-dialog.tsx index c0e050ab..b05c2e0d 100644 --- a/lib/compliance/questions/compliance-question-create-dialog.tsx +++ b/lib/compliance/questions/compliance-question-create-dialog.tsx @@ -45,9 +45,16 @@ const questionSchema = z.object({ questionText: z.string().min(1, "질문 내용을 입력하세요"), questionType: z.string().min(1, "질문 유형을 선택하세요"), isRequired: z.boolean(), + isConditional: z.boolean(), hasDetailText: z.boolean(), hasFileUpload: z.boolean(), conditionalValue: z.string().optional(), +}).refine((data) => { + // 필수 질문이거나 조건부 질문이어야 함 + return data.isRequired || data.isConditional; +}, { + message: "필수 질문 또는 조건부 질문 중 하나는 선택해야 합니다.", + path: ["isRequired", "isConditional"] }); type QuestionFormData = z.infer; @@ -72,6 +79,7 @@ export function ComplianceQuestionCreateDialog({ questionText: "", questionType: "", isRequired: false, + isConditional: false, hasDetailText: false, hasFileUpload: false, conditionalValue: "", @@ -132,10 +140,16 @@ export function ComplianceQuestionCreateDialog({ // 새로운 질문의 displayOrder는 기존 질문 개수 + 1 const currentQuestionsCount = await getComplianceQuestionsCount(templateId); + // 디버깅을 위한 로그 + console.log("Form data:", data); + console.log("isConditional:", form.watch("isConditional")); + console.log("parentQuestionId:", parentQuestionId); + console.log("Final parentQuestionId:", form.watch("isConditional") && parentQuestionId ? Number(parentQuestionId) : null); + const newQuestion = await createComplianceQuestion({ templateId, ...data, - parentQuestionId: data.isConditional && parentQuestionId ? Number(parentQuestionId) : null, + parentQuestionId: form.watch("isConditional") && parentQuestionId ? Number(parentQuestionId) : null, displayOrder: currentQuestionsCount + 1, }); @@ -204,9 +218,13 @@ export function ComplianceQuestionCreateDialog({ 템플릿에 새로운 질문을 추가합니다. + +
+ + + {/* 필수 질문과 조건부 질문 체크박스 */} +
+ ( + + + + +
+ 필수 질문 + + 응답자가 반드시 답변해야 하는 질문 + +
+
+ )} + /> + + ( + + + + +
+ 조건부 질문 + + 특정 조건에 따라 표시되는 질문 + +
+
+ )} + /> +
+ + {/* 유효성 검사 에러 메시지 */} + {(form.formState.errors.isRequired || form.formState.errors.isConditional) && ( +
+ {form.formState.errors.isRequired?.message || form.formState.errors.isConditional?.message || "필수 질문 또는 조건부 질문 중 하나는 선택해야 합니다."} +
+ )} + @@ -245,7 +316,7 @@ export function ComplianceQuestionCreateDialog({ render={({ field }) => ( 질문 유형 - @@ -266,13 +337,14 @@ export function ComplianceQuestionCreateDialog({ {/* 옵션 관리 (선택형 질문일 때만) */} {isSelectionType && ( -
+
옵션 관리
)} - {/* 조건부 질문 체크박스 */} - - -
- ( - - - - -
- 필수 질문 - - 응답자가 반드시 답변해야 하는 질문 - -
-
- )} - /> - - ( - - - - -
- 상세 설명 - - 추가 설명 입력 가능 - -
-
- )} - /> - - ( - - - - -
- 파일 업로드 - - 파일 첨부 가능 - -
-
- )} - /> -
- - {/* 조건부 질문 체크박스 */} - ( - - - - -
- 조건부 질문 - - 특정 조건에 따라 표시되는 질문 - -
-
- )} - /> + {/* 조건부 질문일 때만 부모 질문과 조건값 표시 */} {form.watch("isConditional") && ( @@ -550,7 +534,10 @@ export function ComplianceQuestionCreateDialog({ > 취소 - diff --git a/lib/compliance/questions/compliance-question-edit-sheet.tsx b/lib/compliance/questions/compliance-question-edit-sheet.tsx index 064cafc1..e5fc6242 100644 --- a/lib/compliance/questions/compliance-question-edit-sheet.tsx +++ b/lib/compliance/questions/compliance-question-edit-sheet.tsx @@ -14,6 +14,14 @@ import { SheetTitle, SheetTrigger, } from "@/components/ui/sheet"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; import { Form, FormControl, @@ -81,6 +89,8 @@ export function ComplianceQuestionEditSheet({ const [selectableParents, setSelectableParents] = React.useState>([]); const [parentQuestionId, setParentQuestionId] = React.useState(question.parentQuestionId || null); const [showOptionForm, setShowOptionForm] = React.useState(false); + const [showOptionsDeleteDialog, setShowOptionsDeleteDialog] = React.useState(false); + const [pendingQuestionTypeChange, setPendingQuestionTypeChange] = React.useState(null); const form = useForm({ resolver: zodResolver(questionSchema), @@ -156,6 +166,12 @@ export function ComplianceQuestionEditSheet({ try { setIsLoading(true); + // 디버깅을 위한 로그 + console.log("Edit form data:", data); + console.log("Current isConditional:", data.isConditional); + console.log("Current parentQuestionId:", parentQuestionId); + console.log("Current conditionalValue:", data.conditionalValue); + // 조건부 질문 관련 데이터 처리 const updateData = { ...data, @@ -166,6 +182,8 @@ export function ComplianceQuestionEditSheet({ // isConditional과 parentQuestionId는 제거 (스키마에 없음) delete (updateData as any).isConditional; + console.log("Final updateData:", updateData); + await updateComplianceQuestion(question.id, updateData); toast.success("질문이 성공적으로 수정되었습니다."); @@ -226,6 +244,51 @@ export function ComplianceQuestionEditSheet({ )} /> + {/* 필수 질문과 조건부 질문 체크박스 */} +
+ ( + + + + +
+ 필수 질문 + + 응답자가 반드시 답변해야 하는 질문 + +
+
+ )} + /> + + ( + + + + +
+ 조건부 질문 + + 특정 조건에 따라 표시되는 질문 + +
+
+ )} + /> +
+ ( 질문 유형 - { + const currentType = field.value; + const isCurrentSelectionType = [QUESTION_TYPES.RADIO, QUESTION_TYPES.CHECKBOX, QUESTION_TYPES.DROPDOWN].includes((currentType || "").toUpperCase() as any); + const isNewSelectionType = [QUESTION_TYPES.RADIO, QUESTION_TYPES.CHECKBOX, QUESTION_TYPES.DROPDOWN].includes(newValue.toUpperCase() as any); + + // 선택형에서 비선택형으로 변경하고 기존 옵션이 있는 경우 + if (isCurrentSelectionType && !isNewSelectionType && options.length > 0) { + setPendingQuestionTypeChange(newValue); + setShowOptionsDeleteDialog(true); + } else { + field.onChange(newValue); + } + }} + defaultValue={(field.value || "").toUpperCase()} + > @@ -401,93 +479,6 @@ export function ComplianceQuestionEditSheet({
)} -
- ( - - - - -
- 필수 질문 - - 응답자가 반드시 답변해야 하는 질문 - -
-
- )} - /> - - ( - - - - -
- 상세 설명 - - 추가 설명 입력 가능 - -
-
- )} - /> - - ( - - - - -
- 파일 업로드 - - 파일 첨부 가능 - -
-
- )} - /> -
- - {/* 조건부 질문 체크박스 */} - ( - - - - -
- 조건부 질문 - - 특정 조건에 따라 표시되는 질문 - -
-
- )} - /> - {/* 조건부 질문일 때만 부모 질문과 조건값 표시 */} {form.watch("isConditional") && (
@@ -567,6 +558,69 @@ export function ComplianceQuestionEditSheet({ + + {/* 옵션 삭제 확인 다이얼로그 */} + + + + 옵션 삭제 확인 + + 질문 유형을 변경하면 기존 옵션들이 모두 삭제됩니다. 계속하시겠습니까? + + + +
+
+

삭제될 옵션들:

+ {options.map((option, index) => ( +
+ 옵션 {index + 1}: {option.optionValue} - {option.optionText} +
+ ))} +
+
+ + + + + +
+
); } -- cgit v1.2.3