79 lines
2.8 KiB
Vue
79 lines
2.8 KiB
Vue
<template>
|
|
<div class="container mt-4">
|
|
<h2>온라인 문제 풀이</h2>
|
|
|
|
<div v-if="errorMessage" class="alert alert-danger mt-3">
|
|
{{ errorMessage }}
|
|
</div>
|
|
|
|
<!-- 1단계: 과목 선택 -->
|
|
<div v-if="!attemptId" class="card p-4 mt-3">
|
|
<h4>응시할 과목을 선택하세요</h4>
|
|
|
|
<div class="form-group mt-2">
|
|
<select v-model="selectedSubjectId" class="form-control">
|
|
<option :value="null" disabled>-- 과목 선택 --</option>
|
|
<option v-for="subject in subjects" :key="subject.id" :value="subject.id">
|
|
{{ subject.name }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
|
|
<button class="btn btn-primary mt-3" :disabled="!selectedSubjectId || loading" @click="handleStartExam">응시 시작</button>
|
|
</div>
|
|
|
|
<!-- 2단계: 문제 풀이 -->
|
|
<div v-if="attemptId && !result" class="mt-3">
|
|
<div v-for="(q, index) in questions" :key="q.questionId" class="card p-3 mb-3">
|
|
<h5>문제 {{ index + 1 }}. {{ q.prompt }}</h5>
|
|
|
|
<div v-for="choice in q.choices" :key="choice.optionKey" class="form-check mt-2">
|
|
<input
|
|
:id="'q-' + q.questionId + '-' + choice.optionKey"
|
|
v-model="selectedAnswers[q.questionId]"
|
|
class="form-check-input"
|
|
type="radio"
|
|
:name="'question-' + q.questionId"
|
|
:value="choice.optionKey"
|
|
/>
|
|
|
|
<label class="form-check-label" :for="'q-' + q.questionId + '-' + choice.optionKey">
|
|
<strong>{{ choice.optionKey }}.</strong>
|
|
{{ choice.content }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<button class="btn btn-success" :disabled="loading" @click="handleSubmitExam">답안 제출 및 채점</button>
|
|
</div>
|
|
|
|
<!-- 3단계: 채점 결과 -->
|
|
<div v-if="result" class="card p-4 mt-3">
|
|
<h3>채점 결과: 총점 {{ result.totalScore }} / {{ result.answers.length }}점</h3>
|
|
|
|
<p class="text-muted">제출 시각: {{ result.submittedAt }}</p>
|
|
|
|
<div v-for="(ans, idx) in result.answers" :key="ans.questionId" class="border-top pt-3 mt-3">
|
|
<h5>
|
|
문제 {{ idx + 1 }}. {{ ans.questionText }}
|
|
|
|
<span :class="ans.correct ? 'badge bg-success' : 'badge bg-danger'">
|
|
{{ ans.correct ? '정답 (+1점)' : '오답 (0점)' }}
|
|
</span>
|
|
</h5>
|
|
|
|
<p class="mb-1">
|
|
내 선택:
|
|
{{ ans.selectedOption ? `${ans.selectedOption} (${ans.selectedContent})` : '무응답' }}
|
|
</p>
|
|
|
|
<p v-if="ans.explanation" class="text-info mb-0"><strong>해설:</strong> {{ ans.explanation }}</p>
|
|
</div>
|
|
|
|
<button class="btn btn-secondary mt-4" @click="resetQuiz">다른 과목 응시하기</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" src="./quiz.component.ts"></script>
|