332 lines
8.2 KiB
Vue
332 lines
8.2 KiB
Vue
<template>
|
|
<div v-if="user.data?.is_moderator || isStudent" class="">
|
|
<header
|
|
class="sticky top-0 z-10 flex items-center justify-between border-b bg-surface-white px-3 py-2.5 sm:px-5"
|
|
>
|
|
<Breadcrumbs class="h-7" :items="breadcrumbs" />
|
|
<div class="flex items-center space-x-2">
|
|
<Button
|
|
v-if="user.data?.is_moderator"
|
|
@click="openCertificateDialog = true"
|
|
>
|
|
{{ __('Generate Certificates') }}
|
|
</Button>
|
|
<Button v-if="user.data?.is_moderator" @click="openAnnouncementModal()">
|
|
<span>
|
|
{{ __('Make an Announcement') }}
|
|
</span>
|
|
<template #suffix>
|
|
<SendIcon class="h-4 stroke-1.5" />
|
|
</template>
|
|
</Button>
|
|
</div>
|
|
</header>
|
|
<div
|
|
v-if="batch.data"
|
|
class="grid grid-cols-[75%,25%] h-[calc(100vh-3.2rem)]"
|
|
>
|
|
<div class="border-r">
|
|
<Tabs
|
|
v-model="tabIndex"
|
|
as="div"
|
|
:tabs="tabs"
|
|
tablistClass="overflow-y-hidden bg-surface-white"
|
|
>
|
|
<template #tab="{ tab, selected }" class="overflow-x-hidden">
|
|
<div>
|
|
<button
|
|
class="group -mb-px flex items-center gap-1 border-b border-transparent py-2.5 text-base text-ink-gray-5 duration-300 ease-in-out hover:border-outline-gray-3 hover:text-ink-gray-9"
|
|
:class="{ 'text-ink-gray-9': selected }"
|
|
>
|
|
<component
|
|
v-if="tab.icon"
|
|
:is="tab.icon"
|
|
class="h-4 stroke-1.5"
|
|
/>
|
|
{{ __(tab.label) }}
|
|
<Badge
|
|
v-if="tab.count"
|
|
:class="{
|
|
'text-ink-gray-9 border border-gray-900': selected,
|
|
}"
|
|
variant="subtle"
|
|
theme="gray"
|
|
size="sm"
|
|
>
|
|
{{ tab.count }}
|
|
</Badge>
|
|
</button>
|
|
</div>
|
|
</template>
|
|
<template #tab-panel="{ tab }">
|
|
<div class="pt-5 px-5 pb-10">
|
|
<div v-if="tab.label == 'Courses'">
|
|
<BatchCourses :batch="batch.data.name" />
|
|
</div>
|
|
<div v-else-if="tab.label == 'Dashboard' && isStudent">
|
|
<BatchDashboard :batch="batch" :isStudent="isStudent" />
|
|
</div>
|
|
<div v-else-if="tab.label == 'Dashboard'">
|
|
<BatchStudents :batch="batch.data" />
|
|
</div>
|
|
<div v-else-if="tab.label == 'Classes'">
|
|
<LiveClass :batch="batch.data.name" />
|
|
</div>
|
|
<div v-else-if="tab.label == 'Assessments'">
|
|
<Assessments :batch="batch.data.name" />
|
|
</div>
|
|
<div v-else-if="tab.label == 'Announcements'">
|
|
<Announcements :batch="batch.data.name" />
|
|
</div>
|
|
<div v-else-if="tab.label == 'Discussions'">
|
|
<Discussions
|
|
doctype="LMS Batch"
|
|
:docname="batch.data.name"
|
|
:title="__('Discussions')"
|
|
:key="batch.data.name"
|
|
:singleThread="true"
|
|
:scrollToBottom="false"
|
|
/>
|
|
</div>
|
|
<div v-else-if="tab.label == 'Feedback'">
|
|
<BatchFeedback :batch="batch.data.name" />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</Tabs>
|
|
</div>
|
|
<div class="p-5">
|
|
<div class="text-ink-gray-7 font-semibold mb-4">
|
|
{{ __('About this batch') }}:
|
|
</div>
|
|
<div
|
|
v-html="batch.data.description"
|
|
class="leading-5 mb-4 text-ink-gray-7"
|
|
></div>
|
|
|
|
<div class="flex items-center avatar-group overlap mb-5">
|
|
<div
|
|
class="h-6 mr-1"
|
|
:class="{
|
|
'avatar-group overlap': batch.data.instructors.length > 1,
|
|
}"
|
|
>
|
|
<UserAvatar
|
|
v-for="instructor in batch.data.instructors"
|
|
:user="instructor"
|
|
/>
|
|
</div>
|
|
<CourseInstructors :instructors="batch.data.instructors" />
|
|
</div>
|
|
<DateRange
|
|
:startDate="batch.data.start_date"
|
|
:endDate="batch.data.end_date"
|
|
class="mb-3"
|
|
/>
|
|
<div class="flex items-center mb-4 text-ink-gray-7">
|
|
<Clock class="h-4 w-4 stroke-1.5 mr-2" />
|
|
<span>
|
|
{{ formatTime(batch.data.start_time) }} -
|
|
{{ formatTime(batch.data.end_time) }}
|
|
</span>
|
|
</div>
|
|
<div
|
|
v-if="batch.data.timezone"
|
|
class="flex items-center mb-4 text-ink-gray-7"
|
|
>
|
|
<Globe class="h-4 w-4 stroke-1.5 mr-2" />
|
|
<span>
|
|
{{ batch.data.timezone }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<AnnouncementModal
|
|
v-model="showAnnouncementModal"
|
|
:batch="batch.data.name"
|
|
:students="batch.data.students"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div v-else-if="!user.data?.name" class="">
|
|
<div class="text-base border rounded-md w-1/3 mx-auto my-32">
|
|
<div class="border-b px-5 py-3 font-medium">
|
|
<span
|
|
class="inline-flex items-center before:bg-surface-red-5 before:w-2 before:h-2 before:rounded-md before:mr-2"
|
|
></span>
|
|
{{ __('Not Permitted') }}
|
|
</div>
|
|
<div class="px-5 py-3">
|
|
<div v-if="user.data" class="mb-4 leading-6">
|
|
{{
|
|
__(
|
|
'You are not a member of this batch. Please checkout our upcoming batches.'
|
|
)
|
|
}}
|
|
</div>
|
|
<div v-else class="mb-4 leading-6">
|
|
{{ __('Please login to access this page.') }}
|
|
</div>
|
|
<router-link
|
|
v-if="user.data"
|
|
:to="{
|
|
name: 'Batches',
|
|
params: {
|
|
batchName: batch.data?.name,
|
|
},
|
|
}"
|
|
>
|
|
<Button variant="solid" class="w-full">
|
|
{{ __('Upcoming Batches') }}
|
|
</Button>
|
|
</router-link>
|
|
<Button
|
|
v-else
|
|
variant="solid"
|
|
class="w-full"
|
|
@click="redirectToLogin()"
|
|
>
|
|
{{ __('Login') }}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<BulkCertificates v-model="openCertificateDialog" :batch="batch.data" />
|
|
</template>
|
|
<script setup>
|
|
import { Breadcrumbs, Button, createResource, Tabs, Badge } from 'frappe-ui'
|
|
import { computed, inject, ref } from 'vue'
|
|
import CourseInstructors from '@/components/CourseInstructors.vue'
|
|
import UserAvatar from '@/components/UserAvatar.vue'
|
|
import {
|
|
Clock,
|
|
LayoutDashboard,
|
|
BookOpen,
|
|
Laptop,
|
|
BookOpenCheck,
|
|
Mail,
|
|
SendIcon,
|
|
MessageCircle,
|
|
Globe,
|
|
ClipboardPen,
|
|
} from 'lucide-vue-next'
|
|
import { formatTime, updateDocumentTitle } from '@/utils'
|
|
import BatchDashboard from '@/components/BatchDashboard.vue'
|
|
import BatchCourses from '@/components/BatchCourses.vue'
|
|
import LiveClass from '@/components/LiveClass.vue'
|
|
import BatchStudents from '@/components/BatchStudents.vue'
|
|
import Assessments from '@/components/Assessments.vue'
|
|
import Announcements from '@/components/Annoucements.vue'
|
|
import AnnouncementModal from '@/components/Modals/AnnouncementModal.vue'
|
|
import Discussions from '@/components/Discussions.vue'
|
|
import DateRange from '@/components/Common/DateRange.vue'
|
|
import BulkCertificates from '@/components/Modals/BulkCertificates.vue'
|
|
import BatchFeedback from '@/components/BatchFeedback.vue'
|
|
|
|
const user = inject('$user')
|
|
const showAnnouncementModal = ref(false)
|
|
const openCertificateDialog = ref(false)
|
|
|
|
const props = defineProps({
|
|
batchName: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
})
|
|
|
|
const batch = createResource({
|
|
url: 'lms.lms.utils.get_batch_details',
|
|
cache: ['batch', props.batchName],
|
|
params: {
|
|
batch: props.batchName,
|
|
},
|
|
auto: true,
|
|
})
|
|
|
|
const breadcrumbs = computed(() => {
|
|
let crumbs = [{ label: 'Batches', route: { name: 'Batches' } }]
|
|
if (!isStudent.value) {
|
|
crumbs.push({
|
|
label: 'Details',
|
|
route: {
|
|
name: 'BatchDetail',
|
|
params: {
|
|
batchName: batch.data?.name,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
crumbs.push({
|
|
label: batch?.data?.title,
|
|
route: { name: 'Batch', params: { batchName: props.batchName } },
|
|
})
|
|
return crumbs
|
|
})
|
|
|
|
const isStudent = computed(() => {
|
|
return (
|
|
user?.data &&
|
|
batch.data?.students?.length &&
|
|
batch.data?.students.includes(user.data.name)
|
|
)
|
|
})
|
|
|
|
const tabIndex = ref(0)
|
|
const tabs = computed(() => {
|
|
let batchTabs = []
|
|
batchTabs.push({
|
|
label: 'Dashboard',
|
|
icon: LayoutDashboard,
|
|
})
|
|
|
|
batchTabs.push({
|
|
label: 'Courses',
|
|
icon: BookOpen,
|
|
})
|
|
|
|
batchTabs.push({
|
|
label: 'Classes',
|
|
icon: Laptop,
|
|
})
|
|
|
|
if (user.data?.is_moderator) {
|
|
batchTabs.push({
|
|
label: 'Assessments',
|
|
icon: BookOpenCheck,
|
|
})
|
|
}
|
|
|
|
batchTabs.push({
|
|
label: 'Announcements',
|
|
icon: Mail,
|
|
})
|
|
|
|
batchTabs.push({
|
|
label: 'Discussions',
|
|
icon: MessageCircle,
|
|
})
|
|
|
|
batchTabs.push({
|
|
label: 'Feedback',
|
|
icon: ClipboardPen,
|
|
})
|
|
return batchTabs
|
|
})
|
|
|
|
const redirectToLogin = () => {
|
|
window.location.href = `/login?redirect-to=/batches`
|
|
}
|
|
|
|
const openAnnouncementModal = () => {
|
|
showAnnouncementModal.value = true
|
|
}
|
|
|
|
const pageMeta = computed(() => {
|
|
return {
|
|
title: batch.data?.title,
|
|
description: batch.data?.description,
|
|
}
|
|
})
|
|
|
|
updateDocumentTitle(pageMeta)
|
|
</script>
|