feat: quiz base
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="text-base">
|
||||
<div class="course-outline text-base">
|
||||
<div class="mt-4">
|
||||
<Disclosure v-slot="{ open }" v-for="(chapter, index) in outline.data" :key="chapter.name" :defaultOpen="index == 0">
|
||||
<Disclosure v-slot="{ open }" v-for="(chapter, index) in outline.data" :key="chapter.name" :defaultOpen="chapter.idx == route.params.chapterNumber">
|
||||
<DisclosureButton class="flex w-full px-2 pt-2 pb-3">
|
||||
<ChevronRight
|
||||
:class="{'rotate-90 transform duration-200' : open, 'duration-200' : !open, 'open': index == 1}"
|
||||
@@ -11,13 +11,24 @@
|
||||
{{ chapter.title }}
|
||||
</div>
|
||||
</DisclosureButton>
|
||||
<DisclosurePanel class="px-10 pb-4">
|
||||
<DisclosurePanel class="pb-2">
|
||||
<div v-for="lesson in chapter.lessons" :key="lesson.name">
|
||||
<div class="flex items-center text-base mb-3">
|
||||
<MonitorPlay v-if="lesson.icon === 'icon-youtube'" class="h-4 w-4 text-gray-900 stroke-1 mr-2"/>
|
||||
<HelpCircle v-else-if="lesson.icon === 'icon-quiz'" class="h-4 w-4 text-gray-900 stroke-1 mr-2"/>
|
||||
<FileText v-else-if="lesson.icon === 'icon-list'" class="h-4 w-4 text-gray-900 stroke-1 mr-2"/>
|
||||
{{ lesson.title }}
|
||||
<div class="outline-lesson mb-2 px-8">
|
||||
<router-link :to='{
|
||||
name: "Lesson",
|
||||
params: {
|
||||
courseName: courseName,
|
||||
chapterNumber: lesson.number.split(".")[0],
|
||||
lessonNumber: lesson.number.split(".")[1],
|
||||
}
|
||||
}'>
|
||||
<div class="flex items-center text-base">
|
||||
<MonitorPlay v-if="lesson.icon === 'icon-youtube'" class="h-4 w-4 text-gray-900 stroke-1 mr-2"/>
|
||||
<HelpCircle v-else-if="lesson.icon === 'icon-quiz'" class="h-4 w-4 text-gray-900 stroke-1 mr-2"/>
|
||||
<FileText v-else-if="lesson.icon === 'icon-list'" class="h-4 w-4 text-gray-900 stroke-1 mr-2"/>
|
||||
{{ lesson.title }}
|
||||
</div>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</DisclosurePanel>
|
||||
@@ -29,7 +40,9 @@
|
||||
import { createResource } from "frappe-ui";
|
||||
import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/vue';
|
||||
import { ChevronRight, MonitorPlay, HelpCircle, FileText } from 'lucide-vue-next';
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
const route = useRoute();
|
||||
const props = defineProps({
|
||||
courseName: {
|
||||
type: String,
|
||||
@@ -45,4 +58,10 @@ const outline = createResource({
|
||||
},
|
||||
auto: true,
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
<style>
|
||||
.outline-lesson:has(.router-link-active) {
|
||||
background-color: theme('colors.gray.100');
|
||||
padding: 0.5rem 0 0.5rem 2rem;
|
||||
}
|
||||
</style>
|
||||
@@ -82,7 +82,7 @@ const props = defineProps({
|
||||
},
|
||||
membership: {
|
||||
type: Object,
|
||||
required: true,
|
||||
required: false,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -98,7 +98,7 @@ const reviews = createResource({
|
||||
},
|
||||
auto: true,
|
||||
});
|
||||
console.log(reviews)
|
||||
|
||||
const rating_percent = computed(() => {
|
||||
let rating_count = {};
|
||||
let rating_percent = {};
|
||||
|
||||
83
frontend/src/components/Quiz.vue
Normal file
83
frontend/src/components/Quiz.vue
Normal file
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div v-if="quiz.doc">
|
||||
<div v-if="activeQuestion == 0">
|
||||
<div class="bg-blue-100 py-2 px-2 mb-4 rounded-md text-sm text-blue-800">
|
||||
<div class="leading-relaxed">
|
||||
{{ __("This quiz consists of {0} questions.").format(quiz.doc.questions.length) }}
|
||||
</div>
|
||||
<div v-if="quiz.doc.passing_percentage" class="leading-relaxed">
|
||||
{{ __("You will have to get {0}% correct answers in order to pass the quiz.").format(quiz.doc.passing_percentage) }}
|
||||
</div>
|
||||
<div v-if="quiz.doc.max_attempts" class="leading-relaxed">
|
||||
{{ __("You can attempt this quiz {0}.").format(quiz.doc.max_attempts == 1 ? "1 time" : `${quiz.doc.max_attempts} times`) }}
|
||||
</div>
|
||||
<div v-if="quiz.doc.time" class="leading-relaxed">
|
||||
{{ __("The quiz has a time limit.For each question you will be given { 0} seconds.").format(quiz.doc.time) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="border text-center p-20 font-semibold text-lg rounded-md">
|
||||
<div>
|
||||
{{ quiz.doc.title }}
|
||||
</div>
|
||||
<Button @click="startQuiz" class="mt-2">
|
||||
<span>
|
||||
{{ __("Start") }}
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div v-for="index in quiz.doc.questions.length">
|
||||
<div v-if="index == activeQuestion">
|
||||
{{ questionDetails }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { createDocumentResource, Button } from 'frappe-ui';
|
||||
import { ref, watch, inject } from 'vue';
|
||||
|
||||
const user = inject("$user");
|
||||
|
||||
const props = defineProps({
|
||||
quizName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const activeQuestion = ref(0);
|
||||
const currentQuestion = ref("");
|
||||
|
||||
const quiz = createDocumentResource({
|
||||
doctype: "LMS Quiz",
|
||||
name: props.quizName,
|
||||
cache: ["quiz", props.quizName],
|
||||
});
|
||||
console.log(user.data)
|
||||
if (user.data) {
|
||||
quiz.reload();
|
||||
}
|
||||
|
||||
const questionDetails = createDocumentResource({
|
||||
doctype: "LMS Question",
|
||||
name: currentQuestion.value,
|
||||
cache: ["question", props.quizName, currentQuestion.value],
|
||||
});
|
||||
console.log(questionDetails)
|
||||
const startQuiz = () => {
|
||||
activeQuestion.value = 1;
|
||||
}
|
||||
|
||||
watch(activeQuestion, (value) => {
|
||||
if (value > 0) {
|
||||
currentQuestion.value = quiz.doc.questions[value - 1];
|
||||
console.log(currentQuestion.value)
|
||||
console.log(questionDetails)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user