백로그

0
티켓 없음

할 일

0
티켓 없음

진행 중

0
티켓 없음

리뷰

0
티켓 없음

완료 (15일)

1
높음 fabf13f7
서브 티켓 문항관리

문항관리 리디자인 - 유형/대상/언어 그룹 + 응답 통계

## 목표 기존 문항관리 페이지를 리디자인합니다. 문항 번호별 목록이 아닌, 검사 유형/대상/언어 그룹으로 목록을 보여주고, 선택하면 해당 문항들과 응답 통계가 표시됩니다. ## 변경 파일 ### 1. 컨트롤러 수정: `app/controllers/admin/survey_questions_controller.rb` #### index 액션 리디자인 - 기존 index: 문항 번호별 평면 목록 → 변경: 유형/대상/언어 그룹 목록 - 그룹 목록 데이터: ```ruby def index @groups = DiagnosisType.includes(:category, :target).where(active: true).order(:display_order) @locales = %w[ko en zh vi] end ``` - 각 그룹 = DiagnosisType × locale 조합 (예: "강점검사 - 성인 - 한국어") #### show 액션 (그룹 선택 시) - 라우트 변경 또는 새 액션 추가: `questions` 또는 기존 show 재활용 - 새 액션 `group_detail` 추가: ```ruby def group_detail @diagnosis_type = DiagnosisType.find(params[:diagnosis_type_id]) @locale = params[:locale] || "ko" @target = @diagnosis_type.target @questions = SurveyQuestion.includes(:translations, :category) .where(category_id: @diagnosis_type.category_id) .active .order(:part, :display_order) # 응답 통계 계산 # completed 세션의 response만 카운트 session_ids = DiagnosisSession.where(diagnosis_type: @diagnosis_type, status: "completed").pluck(:id) @response_stats = calculate_response_stats(@questions, session_ids) end ``` #### 응답 통계 계산 private 메서드 ```ruby def calculate_response_stats(questions, session_ids) return {} if session_ids.empty? stats = {} responses = DiagnosisResponse.where(diagnosis_session_id: session_ids, survey_question_id: questions.pluck(:id)) .group(:survey_question_id, :response_value) .count questions.each do |q| total = 0 distribution = {} if q.part == 1 # Part1: 1점~5점 분포 (1..5).each do |val| count = responses[[q.id, val.to_s]] || responses[[q.id, val]] || 0 distribution[val] = count total += count end else # Part2: A, B, C 선택지 분포 (response_value가 "A", "B", "C" 또는 1,2,3) # DiagnosisResponse의 response_value 확인 필요 # selected_option_id 또는 response_value로 구분 %w[1 2 3].each do |val| count = responses[[q.id, val]] || responses[[q.id, val.to_i]] || 0 distribution[val] = count total += count end end stats[q.id] = { distribution: distribution, total: total } end stats end ``` ### 2. 뷰 생성 #### `app/views/admin/survey_questions/index.html.erb` (리디자인) - 그룹 목록을 카드/테이블로 표시: - 진단 유형명 (category.name + target.name) - 언어 선택 탭 또는 버튼 (ko, en, zh, vi) - 문항 수 표시 - 클릭 시 → group_detail로 이동 #### `app/views/admin/survey_questions/group_detail.html.erb` (새 뷰) - 상단: 뒤로 가기 + 그룹 정보 (유형, 대상, 언어) - Part 1 섹션 (1~12번): ``` Q1. [문항 내용 - 해당 target/locale의 번역] 1점: 0 (0%) | 2점: 0 (0%) | 3점: 0 (0%) | 4점: 0 (0%) | 5점: 0 (0%) ``` - 각 점수의 count와 percentage 표시 - percentage = (count / total * 100).round(1) - 바 차트(간단한 inline width %)로 시각화 - Part 2 섹션 (1~36번): ``` Q1. [문항 내용] A선택지: [텍스트] 0 (0%) | B선택지: [텍스트] 0 (0%) | C선택지: [텍스트] 0 (0%) ``` - Part2 문항은 `SurveyQuestionTranslation`에서 해당 target, locale의 텍스트 가져오기 - 선택지 텍스트는 translation에 포함되어 있을 수 있음 - 확인 필요 ### 3. 라우트 추가 (`config/routes.rb`) ```ruby resources :survey_questions, except: :destroy do collection { get :group_detail } member do patch :soft_delete patch :restore end end ``` ## 모델 관계 참고 - `SurveyQuestion`: category_id, part(1 or 2), dna_type, display_order - `SurveyQuestionTranslation`: survey_question_id, target_id, locale, question_text - `DiagnosisResponse`: diagnosis_session_id, survey_question_id, response_value, selected_option_id - `DiagnosisType`: category_id, target_id, slug - `DiagnosisCategory`: name (예: "강점검사") - `DiagnosisTarget`: name, slug (예: "성인", "adult") ## 스타일 참고 - 기존 admin Tailwind 패턴 따르기 - 통계 바: `<div class="bg-admin-primary/20 rounded-full h-2"><div class="bg-admin-primary rounded-full h-2" style="width: X%"></div></div>` - 테이블 스타일은 기존 admin 패턴 ## 주의사항 - DiagnosisResponse의 response_value 형식을 실제 DB 데이터로 확인할 것 (docker compose exec web rails runner "DiagnosisResponse.limit(5).pluck(:response_value, :selected_option_id)") - Part2 선택지가 어떻게 저장되는지 확인 필요 - 대량 데이터 쿼리 시 성능 고려 (group/count로 집계) ## 완료 기준 - /admin/survey_questions 에서 유형/대상별 그룹 목록 표시 - 그룹 선택 시 문항 + 응답 통계 표시 - Part1: 1~5점 분포 (count + percentage) - Part2: A/B/C 선택지 분포 (count + percentage)

A
admin-survey-dev
12 days