Your IP : 216.73.217.77


Current Path : /home/users/unlimited/www/learnoid.codeskitter.site/resources/js/components/
Upload File :
Current File : /home/users/unlimited/www/learnoid.codeskitter.site/resources/js/components/CourseLessons.vue

<template>
    <section class="mb-5 p-3 rounded" style="background: #e2e8f0">
        <div class="text-center mt-3" style="cursor: pointer">
            <p class="text-decoration-none text-primary">
                <i class="bi bi-highlighter fs-5"></i> {{ $t('Learn with Ease: Step-by-Step Lessons') }}
            </p>
        </div>
        <div class="accordion" id="contentAccordion">
            <div v-if="Array.isArray(chapters)">
                <div v-for="(chapter, index) in (chapters || []).slice(
                    0,
                    chaptersToShow
                )" :key="index" class="border border-2 bg-white rounded mb-2" :class="{
                    'border-primary': activeIndex === index,
                    collapsed: activeIndex !== index,
                }">
                    <h2 class="m-0">
                        <button class="accordion-button bg-white border rounded" type="button"
                            :class="{ collapsed: index !== 0 }" :data-bs-toggle="'collapse'"
                            :data-bs-target="'#chapter' + index" aria-expanded="index === 0"
                            aria-controls="'chapter' + index" @click="toggleAccordion(index)">
                            <div class="accordion-content w-100">
                                <div class="d-flex justify-content-between align-items-center mb-3">
                                    <small class="me-2 text-muted">Class {{ index + 1 }}</small>
                                    <small v-if="chapter.duration > 0" class="me-2 text-muted chapter-duration">
                                        {{
                                            formatDuration(chapter?.duration ?? 0)
                                        }}
                                    </small>
                                </div>
                                <span class="chapter-title">{{
                                    chapter.title
                                }}</span>
                            </div>
                        </button>
                    </h2>
                    <div :id="'chapter' + index" class="accordion-collapse collapse my-1" :class="{ show: index === 0 }"
                        data-bs-parent="#contentAccordion">
                        <div class="accordion-body border-start border-end border-light p-0 mx-1">
                            <div v-for="(content, contentIndex) in chapter.contents" :key="content.id">
                                <!-- Content Link -->
                                <router-link v-if="
                                    course?.is_enrolled || content.is_free
                                " :to="authStore.userData
                                    ? `/play/${courseId}?content_id=${content.id}`
                                    : ''
                                    " @click.prevent="handleWaring" @click="markContentComplete(content.id)" :class="{
                                        'd-block px-3 py-2 rounded-3 border-light text-decoration-none text-dark content-link': true,
                                        active:
                                            content.id ==
                                            route.query.content_id ||
                                            (route.path !==
                                                '/details/[course_id]' &&
                                                !route.query.content_id &&
                                                contentIndex === 0),
                                        completed: content.completed,
                                        view: content.is_viewed,
                                    }">
                                    <div class="d-flex align-items-center" @click="handleView(content.id)">

                                        <Video v-if="
                                            content.type === 'video' &&
                                            content.media_id &&
                                            isPlayingVideo &&
                                            currentId == content.id
                                        " @click="togglePlay(content.id)"
                                            :colorClass="content.is_viewed ? 'text-primary' : 'text-muted'"
                                            class="mg-fluid me-3 svgEdit" />

                                        <Video v-if="
                                            content.type === 'video' &&
                                            content.media_id &&
                                            (!isPlayingVideo ||
                                                currentId != content.id)
                                        " @click="togglePlay(content.id)"
                                            :colorClass="content.is_viewed ? 'text-primary' : 'text-muted'"
                                            class="mg-fluid me-3 svgEdit" />

                                        <Video v-if="
                                            content.type === 'video' &&
                                            !content.media_id"
                                            :colorClass="content.is_viewed ? 'text-primary' : 'text-muted'"
                                            class="mg-fluid me-3 svgEdit" />

                                        <Audio v-if="
                                            content.type === 'audio' &&
                                            isPlayingAudio &&
                                            currentId == content.id" @click="togglePlayAudio(content.id)"
                                            class="img-fluid me-3 svgEdit" />

                                        <Audio v-if="
                                            content.type === 'audio' &&
                                            (!isPlayingAudio ||
                                                currentId != content.id)" @click="togglePlayAudio(content.id)"
                                            class="img-fluid me-3 svgEdit" />

                                        <Document v-if="content.type === 'document'"
                                            :colorClass="content.is_viewed ? 'text-primary' : 'text-muted'"
                                            class="img-fluid me-3 svgEdit" />


                                        <Image v-if="content.type === 'image'"
                                            :colorClass="content.is_viewed ? 'text-primary' : 'text-muted'"
                                            class="img-fluid me-3 svgEdit" />



                                        <span :class="content.is_viewed
                                            ? 'text-primary title-font'
                                            : 'text-muted title-font'
                                            ">{{ content.title }}</span>

                                        <div class="ms-auto d-flex justify-content-between align-items-center gap-3">
                                            <small v-if="content.duration > 0" class="text-muted"
                                                style="font-size: 0.625em">{{
                                                    formatDuration(content.duration ?? 0)
                                                }}
                                            </small>
                                            <small class="text-muted" style="font-size: 0.625em">
                                                <FontAwesomeIcon :icon="content.is_viewed
                                                    ? ''
                                                    : faCircle
                                                    " :class="content.is_viewed
                                                        ? ''
                                                        : 'text-primary'
                                                        " />
                                            </small>
                                        </div>
                                    </div>
                                </router-link>
                                <!-- Enroll Warning -->
                                <div v-else @click="enrollWarning"
                                    class="content d-block px-3 py-2 border-bottom border-light text-decoration-none text-dark">
                                    <div class="d-flex align-items-center">
                                        <Video v-if="content.type === 'video'" class="img-fluid me-3 svgEdit" />
                                        <Audio v-if="content.type === 'audio'" class="img-fluid me-3 svgEdit" />
                                        <Document v-if="content.type === 'document'"
                                            class="img-fluid me-3 svgEdit" />
                                        <Image v-if="content.type === 'image'" class="img-fluid me-3 svgEdit" />
                                        <span class="text-muted title-font">
                                            {{ content.title }}
                                        </span>
                                        <small class="text-muted ms-auto"><i class="bi bi-lock-fill"></i></small>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="text-center mt-3" style="cursor: pointer">
            <a @click.prevent="showMoreChapters" :class="chapters?.length === 0
                ? 'text-danger text-decoration-none'
                : 'text-decoration-none'
                ">
                {{
                    chapters?.length === 0
                        ? $t("No Content Available")
                        : chapters?.length > 4
                            ? $t("See More")
                            : ""
                }}
            </a>
        </div>

        <!-- exam & quiz start section -->

        <div v-if="$route.path.includes('/play')">
            <div class="text-center mt-3" style="cursor: pointer">
                <p class="text-decoration-none text-primary">
                    <i class="bi bi-patch-question-fill fs-5"></i> {{ $t('Exam & Quiz') }}
                </p>
            </div>

            <div class="accordion" id="accordionPanelsStayOpenExample">
                <div class="accordion-item">
                    <h2 class="accordion-header">
                        <button class="accordion-button" type="button" data-bs-toggle="collapse"
                            data-bs-target="#panelsStayOpen-collapseOne" aria-expanded="true"
                            aria-controls="panelsStayOpen-collapseOne">
                            {{ $t('Test Your Knowladge') }}
                        </button>
                    </h2>
                    <div id="panelsStayOpen-collapseOne" class="accordion-collapse collapse show">
                        <div class="accordion-body">
                            <div class="row">
                                <div class="col-6">
                                    <p>{{ $t('Exams') }}
                                        <FontAwesomeIcon class="text-primary" :icon="faGraduationCap" />
                                    </p>
                                    <div v-if="exams?.length > 0">
                                        <div v-for="(exam, index) in exams" :key="index">
                                            <button v-if="course?.is_enrolled"
                                                class="btn btn-primary w-100 text-white my-2"
                                                @click="startExam(exam.id)">{{ $t('Start') }}
                                                {{ $t('Exam') }} #{{ index + 1 }}</button>
                                        </div>
                                    </div>
                                    <p v-else class="text-muted">{{ $t('No exams available at the moment') }}.</p>
                                </div>
                                <div class="col-6">
                                    <p>{{ $t('Quizzes') }}
                                        <FontAwesomeIcon class="text-warning" :icon="faLightbulb" />
                                    </p>
                                    <div v-if="quizes?.length > 0">
                                        <div v-for="(quiz, index) in quizes" :key="index">
                                            <button v-if="course?.is_enrolled" @click="startQuiz(quiz.id)"
                                                class="btn btn-warning w-100 text-white my-2">{{ $t('Start') }}
                                                {{ $t('Quiz') }} #{{ index + 1 }}</button>
                                        </div>
                                    </div>
                                    <p v-else class="text-muted">{{ $t('No quizzes available at the moment') }}.</p>
                                </div>
                            </div>


                        </div>
                    </div>
                </div>
            </div>

        </div>

    </section>
</template>

<style scoped lang="scss">
.accordion-button {
    border: 2px solid transparent;
    /* Transparent border initially */
    transition: border-color 0.3s;
    /* Smooth transition for border color */
}

.accordion-button:not(.collapsed) {
    border-color: var(--bs-primary);
    /* Change to primary color when active */
}

.content {
    cursor: pointer;
}

.content-link.active {
    background-color: #f3e9fe;
}

.content-link.view {
    color: #f3e9fe;
    text-decoration: line-through;
}

.progress-bar-container {
    background-color: #f5f5f5;
    border-radius: 5px;
    height: 10px;
    margin-bottom: 10px;
}

.progress-bar {
    background-color: #4caf50;
    height: 100%;
    border-radius: 5px;
}

.chapter-duration {
    position: absolute;
    right: 12px;
    top: 12px;
}

.chapter-title {
    cursor: pointer;
    font-size: 1rem;
}

.title-font {
    font-size: 0.75rem;
    font-weight: 500;
}

.svgEdit {
    padding: 4px;
    border-radius: 12px;
    background: #f7f2f2;
}
</style>

<script setup>
import { defineProps, ref, computed, onMounted } from "vue";
import Swal from "sweetalert2";
import { useRoute, useRouter } from "vue-router";
import { useAuthStore } from "@/stores/auth";
import { useExamStore } from "../stores/exam";
import { useQuizStore } from "../stores/quiz";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { faCircle, faGraduationCap, faLightbulb } from "@fortawesome/free-solid-svg-icons";
import Video from "@/icons/video.vue";
import Image from "@/icons/image.vue";
import Document from "@/icons/document.vue";
import Audio from "@/icons/audio.vue";


const authStore = useAuthStore();
const examStore = useExamStore();
const quizStore = useQuizStore();
const route = useRoute();
const router = useRouter();
const activeIndex = ref(0);

let currentId = ref(route.params.content_id);
let chaptersToShow = ref(5);

let props = defineProps({
    chapters: {
        type: Array,
        default: () => [],
    },
    courseId: Number,
    isPlayingVideo: Boolean,
    isPlayingAudio: Boolean,
    course: Object,
    contentData: Object,
    exams: Array,
    quizes: Array,
});

const markContentComplete = (contentId) => {
    const content = findContentById(contentId);
    if (content) {
        content.is_viewed = true;
    }
};

// Helper function to find content by ID
function findContentById(contentId) {
    for (const chapter of props.chapters) {
        for (const content of chapter.contents) {
            if (content.id === contentId) return content;
        }
    }
    return null;
}

// Method to mark a content as completed

const showMoreChapters = () => {
    chaptersToShow.value += 1;
};

const emit = defineEmits([
    "playVideo",
    "pauseVideo",
    "pauseAudio",
    "playAudio",
]);

// Play/Pause Video
const togglePlay = (contentId) => {
    currentId.value = contentId;
    if (props.isPlayingVideo) {
        // Use props.isPlaying instead
        emit("pauseVideo", contentId);
    } else {
        emit("playVideo", contentId);
    }
};

const togglePlayAudio = (contentId) => {
    currentId.value = contentId;
    if (props.isPlayingAudio) {
        // Use props.isPlaying instead
        emit("pauseAudio", contentId);
    } else {
        emit("playAudio", contentId);
    }
};

function formatDuration(duration) {
    if (duration >= 60) {
        const hours = Math.floor(duration / 60);
        const minutes = duration % 60;
        return `${hours} hour${hours > 1 ? "s" : ""}${minutes > 0 ? ` ${minutes} min` : ""
            }`;
    }
    return `${duration} min`;
}

const handleWaring = () => {
    if (!authStore.userData) {
        Swal.fire({
            icon: "error",
            title: "Sorry...",
            text: "You need to log in to access this page.",
            confirmButtonText: "Go to Login",
        }).then((result) => {
            if (result.isConfirmed) {
                window.location.href = "/login";
            }
        });
    }
};

function enrollWarning() {
    Swal.fire({
        icon: "warning",
        title: "Enroll Required",
        text: "You need to enroll the course to view the content",
        showConfirmButton: true,
    });
}

// Method to toggle the accordion
const toggleAccordion = (index) => {
    activeIndex.value = activeIndex.value === index ? -1 : index;
};

const startExam = (examId) => {
    Swal.fire({
        title: "Are you sure?",
        text: "Warning! If you start the exam and submit it, you won't be able to re-take the exam later. Are you sure you want to proceed?",
        icon: "warning",
        showCancelButton: true,
        confirmButtonColor: "#3085d6",
        cancelButtonColor: "#d33",
        confirmButtonText: "Yes, Start the Exam!"
    }).then((result) => {
        if (result.isConfirmed) {
            examStore.isResetTimer = true;
            router.push(`/exam/${examId}`);
        }
    });
};
const startQuiz = (quizId) => {
    Swal.fire({
        title: "Are you sure?",
        text: "Warning! If you start the quiz and submit it, you won't be able to re-take the quiz later. Are you sure you want to proceed?",
        icon: "warning",
        showCancelButton: true,
        confirmButtonColor: "#3085d6",
        cancelButtonColor: "#d33",
        confirmButtonText: "Yes, Start the quiz!"
    }).then((result) => {
        if (result.isConfirmed) {
            quizStore.isResetTimer = true;
            router.push(`/quiz/${quizId}`);
        }
    });
};

</script>