Skip to content

Commit

Permalink
Merge pull request #20 from sigi-ro/feature/student-course-show
Browse files Browse the repository at this point in the history
Update student course show
  • Loading branch information
LiamThursfield committed Nov 18, 2023
2 parents 9bf36ce + 83762e6 commit 0dbac13
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 126 deletions.
23 changes: 23 additions & 0 deletions resources/js/components/core/icons/IconMinus.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<template>
<!-- Part of the tabler icon set: https://github.com/tabler/tabler-icons -->
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M5 12l14 0" />
</svg>
</template>

<script>
export default {
name: "IconMinus"
}
</script>
286 changes: 160 additions & 126 deletions resources/js/pages/student/admin/home/Show.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,164 +7,164 @@
<small>By <b>{{ course.creator.name }}</b></small>
</div>

<div class="grid grid-rows-1 md:grid-rows-2 grid-flow-col gap-x-2">
<div class="bg-white p-6 shadow-subtle rounded-lg row-span-2 ...">
<h2 class="font-semibold">Course Content</h2>
<hr
class="my-2 h-px border-t-0 bg-transparent bg-gradient-to-r from-black via-neutral-500 to-transparent opacity-25 dark:opacity-100"
/>
<div class="flex flex-row space-x-4">
<div class="max-w-sm w-full ">
<div class="bg-white rounded-xl shadow-subtle">
<h2 class="border-b font-semibold px-6 py-3">
Course Content
</h2>

<div
v-for="(menuSection, menuSectionKey) in course.sections"
:key="menuSectionKey"
class="menu-section"
>
<button
class="menu-subheading font-semibold"
<div
v-for="(section, sectionIndex) in course.sections"
:key="`section-${sectionIndex}`"
>
{{ menuSection.title }}
<small class="font-weight-light">
{{ menuSection.lecture_count + ' lectures' + ' | ' + menuSection.content_length + ' minutes'}}
</small>
</button>
<div
class="
cursor-pointer px-6 py-3
hover:bg-theme-primary-subtle-hover
"
:class="{
'bg-theme-primary-subtle-hover': sectionIndex === activeSection
}"
@click="toggleSection(sectionIndex)"
>
<div class="flex flex-1 flex-row items-center justify-between">
<h3 class="font-bold">
{{ sectionIndex + 1 }}. {{ section.title }}
</h3>

<template class="root-menu" v-show="menuSection.child_items.length">
<collapse-transition dimension="height">
<ul
class="sub-menu"
>
<course-side-menu-item
v-for="(child, key) in menuSection.child_items"
:key="`${menuSectionKey}.${key}`"
class="sub-menu-item"
:menu-item="child"
:menu-item-key="`${menuSectionKey}.${key}`"
:selected-lecture="lecture"
:menu-item-level="2"
:toggled-items="toggledItems"
@openItem="onMenuItemOpened"
@toggleItem="onMenuItemToggled(child, key)"
<component
:is="(toggledSections[sectionIndex]) ? 'icon-minus' : 'icon-plus'"
class="w-5"
/>
</ul>
</collapse-transition>
</template>
</div>

<div
class="menu-separator"
></div>
</div>
</div>
<p class="text-sm">
0/{{ section.child_items.length }}| {{ section.content_length }} min
</p>
</div>


<transition name="slide-left">
<div
v-if="toggledSections[sectionIndex]"
>
<div
v-for="(lecture, lectureIndex) in section.child_items"
:key="`lecture-${lectureIndex}`"
class="
cursor-pointer flex flex-row px-6 py-1 space-x-1
hover:bg-theme-primary-subtle-hover
"
:class="{
'bg-theme-primary-subtle-hover': isLectureActive(sectionIndex, lectureIndex)
}"
>
<button
type="button"
@click="checkMarkComplete(lecture)"
>
<component
:is="lecture.completed ? 'icon-square-check-filled' : 'icon-square-check'"
class="w-5"
:class="{
'text-theme-success-contrast' : lecture.completed
}"
/>
</button>

<div class="col-span-3 ...">
<div v-if="isLoadingLecture">
<icon-loader-circle class="animate-spin-slow w-5"/>
<div
@click="setActiveLecture(sectionIndex, lectureIndex, lecture)"
>
<p class="text-sm">{{ (lectureIndex + 1) }}. {{ lecture.title }}</p>
<p class="text-xs">{{ lecture.content_length}} min</p>
</div>
</div>
</div>
</transition>
</div>
</div>
<div
v-if="lecture && !isLoadingLecture"
class="bg-white p-6 shadow-subtle rounded-lg row-span-2"
>
<h2 class="font-semibold">{{ lecture.title }}</h2>
<hr
class="my-2 h-px border-t-0 bg-transparent bg-gradient-to-r from-black via-neutral-500 to-transparent opacity-25 dark:opacity-100"
/>
</div>

<div class="container max-w-screen-lg mx-auto">
<div class="text-center">
<iframe :src="lecture.video_url" width="960" height="360" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>
</div>
<hr
class="my-6 h-px border-t-0 bg-transparent bg-gradient-to-r from-black via-neutral-500 to-transparent opacity-25 dark:opacity-100"
<transition name="slide-right">
<div v-if="lecture && !isLoadingLecture" class="w-full">
<div class="bg-white overflow-hidden relative rounded-lg shadow-subtle">
<iframe
class="aspect-ratio-16-9 w-full"
:src="lecture.video_url"
allowfullscreen
allow="autoplay; fullscreen; picture-in-picture"
frameborder="0"
/>
<div class="mb-4 grid grid-cols-4 gap-4">
<button
class="
button button-default-responsive button-primary
flex flex-row items-center
"
title="Mark Lecture Complete"
@click="checkMarkComplete(lecture)"
:disabled="lecture.completed"
>
<icon-square-check-filled
v-if="lecture.completed"
class="w-5 md:mr-2"
/>
<icon-square-check
v-else
class="w-5 md:mr-2"
/>
</div>

<span class="hidden md:inline">
{{ lecture.completed ? 'Completed':'Mark Complete' }}
</span>
</button>
<div class="bg-white mt-4 p-6 overflow-hidden relative rounded-lg shadow-subtle ">
<div
class="flex items-center justify-content-between space-x-6"
>
<h2 class="flex-1 font-semibold">
{{ lecture.title }}
</h2>

<button
v-if="lecture.files && lecture.files.length"
class="
button button-default-responsive button-primary-subtle
flex flex-row items-center
"
v-if="showPDFPanel || (lecture.files && lecture.files.length)"
class="button button-primary-subtle button-small flex flex-row items-center text-sm"
title="Download PDFs"
@click="downloadPDFs(lecture)"
>
<icon-book-download
class="w-5 md:mr-2"
/>
<span class="hidden md:inline">
Download PDFs
<span
class="hidden md:inline"
>
{{ (showPDFPanel) ? 'Cancel' : 'Download PDFs' }}
</span>
</button>
</div>
<div class="mb-4 px-2 space-y-2 mt-4" v-if="lecture.id === lectureToViewId && lecture.files && showPDFPanel">
<h2 class="font-semibold">Files</h2>
<ul class="list-group">
<li
v-for="file in lecture.files"
:key="`file-` + file.id"
class="
flex flex-row items-start justify-between py-2 space-x-4
ease-in-out duration-300 transition-all
hover:bg-gray-100
"
>
<div class="flex flex-row items-start">
<!-- Open file in new tab -->
<transition-group
class="mt-4"
name="slide-left"
tag="div"
>
<div v-if="showPDFPanel"
key="downloads"
>
<h3 class="font-semibold">Files</h3>
<ul class="mt-2">
<li
v-for="(file, index) in lecture.files"
class="mt-1"
:key="`file-${index}`"
>
<a
v-if="file.url"
class="
flex flex-row items-center justify-center rounded text-theme-base-subtle-contrast
ease-in-out duration-300 transition-colors
focus:text-theme-primary focus:outline-none
hover:text-theme-primary
flex flex-row items-center space-x-2 text-theme-primary
hover:text-theme-primary-hover
"
:href="file.url"
rel="noreferrer noopener nofollow"
target="_blank"
@click.stop=""
>
<icon-external-link class="w-5 mr-2" />
{{ file.file_name }}
<icon-external-link class="w-4" />
<p class="text-sm font-semibold">{{ file.file_name }}</p>
</a>
</div>
</li>
</ul>
</div>
<p
v-if="lecture.description"
class="font-weight-light"
>
{{ lecture.description }}
</p>
<p
v-else
class="font-weight-light"
>
{{ course.description }}
</p>
</li>
</ul>
</div>
<div
v-else
key="description"
>
<p class="mt-2">{{ lecture.description }}</p>
</div>
</transition-group>
</div>
</div>
</div>
</transition>

</div>

<confirmation-modal
Expand All @@ -180,19 +180,22 @@
</template>

<script>
import _ from 'lodash';
import CourseSideMenuItem from "../../../../components/student/menus/CourseSideMenuItem";
import IconSquareCheck from "../../../../components/core/icons/IconSquareCheck";
import CollapseTransition from "@ivanv/vue-collapse-transition";
import ConfirmationModal from "../../../../components/core/modals/ConfirmationModal";
import IconSquareCheckFilled from "../../../../components/core/icons/IconSquareCheckFilled";
import IconBookDownload from "../../../../components/core/icons/IconBookDownload";
import IconPlus from "../../../../components/core/icons/IconPlus";
export default {
name: "StudentAdminCourseShow",
layout: 'student-admin-layout',
components: {
IconPlus,
IconBookDownload,
IconSquareCheckFilled,
IconSquareCheck,
Expand All @@ -208,6 +211,13 @@ export default {
},
data() {
return {
activeSection: 0,
activeSectionLecture: 0,
toggledSections: {
0: true
},
mountedItems: {},
toggledItems: {},
lecture: null,
Expand Down Expand Up @@ -242,6 +252,26 @@ export default {
this.isLoadingLecture = false;
},
methods: {
toggleSection(section) {
this.$set(this.toggledSections, section, !this.toggledSections[section]);
},
isLectureActive(sectionIndex, lectureIndex) {
return this.activeSection === sectionIndex && this.activeSectionLecture === lectureIndex
},
setActiveLecture(sectionIndex, lectureIndex, lecture) {
this.activeSection = sectionIndex;
this.activeSectionLecture = lectureIndex;
this.lecture = _.cloneDeep(lecture);
this.showPDFPanel = false;
// Make it look as if it is loading, as (although counter-intuitive) it's a better UX
// As it makes it more obvious that the active course has changed
this.isLoadingLecture = true;
setTimeout(() => {
this.isLoadingLecture = false;
}, 300);
},
onMenuItemOpened(item, itemKey) {
this.$set(this.toggledItems, itemKey, true);
},
Expand All @@ -256,6 +286,10 @@ export default {
this.isLoadingLecture = false;
},
checkMarkComplete(item) {
if (item.completed) {
return;
}
this.showConfirmMarkCompleteModal = true;
this.itemToMarkComplete = item;
},
Expand All @@ -282,7 +316,7 @@ export default {
},
downloadPDFs(lecture) {
this.lectureToViewId = lecture.id;
this.showPDFPanel = true;
this.showPDFPanel = !this.showPDFPanel;
}
}
}
Expand Down

0 comments on commit 0dbac13

Please sign in to comment.