Skip to content

Commit

Permalink
feat: certification details and form
Browse files Browse the repository at this point in the history
  • Loading branch information
pateljannat committed Sep 10, 2024
1 parent 60f2e86 commit 7da608e
Show file tree
Hide file tree
Showing 7 changed files with 318 additions and 80 deletions.
1 change: 1 addition & 0 deletions frontend/src/components/Controls/Link.vue
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ const options = createResource({
url: 'frappe.desk.search.search_link',
cache: [props.doctype, text.value],
method: 'POST',
auto: true,
params: {
txt: text.value,
doctype: props.doctype,
Expand Down
18 changes: 11 additions & 7 deletions frontend/src/components/Controls/Rating.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
{{ props.label }}
</label>
<div class="flex text-center">
<div v-for="index in 5">
{{ rating }}
<div v-for="index in 5" @mouseover="hoveredRating = index" @mouseleave="hoveredRating = 0">
<Star
:class="index <= rating ? 'fill-orange-500' : ''"
class="h-6 w-6 fill-gray-400 text-gray-50 mr-1 cursor-pointer"
class="h-6 w-6 fill-gray-400 text-gray-50 stroke-1 mr-1 cursor-pointer"
:class="{ 'fill-yellow-200': (index <= hoveredRating && index > rating), 'fill-yellow-500': index <= rating }"
@click="markRating(index)"
/>
</div>
Expand All @@ -18,7 +17,7 @@

<script setup>
import { Star } from 'lucide-vue-next'
import { ref } from 'vue'
import { ref, watch } from 'vue'
const props = defineProps({
id: {
Expand All @@ -36,8 +35,9 @@ const props = defineProps({
})
const emit = defineEmits(['update:modelValue'])
let rating = ref(props.modelValue)
console.log(props.modelValue)
const rating = ref(props.modelValue)
const hoveredRating = ref(0)
let emitChange = (value) => {
emit('update:modelValue', value)
}
Expand All @@ -46,4 +46,8 @@ function markRating(index) {
emitChange(index)
rating.value = index
}
watch(() => props.modelValue, (newVal) => {
rating.value = newVal
})
</script>
277 changes: 215 additions & 62 deletions frontend/src/components/Modals/Event.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,76 +11,118 @@
{{ event.title }}
</div>

<div class="flex flex-col space-y-3">
<div class="flex items-center space-x-1">
<BookOpen class="h-4 w-4 stroke-1.5" />
<span>
{{ event.course_title }}
</span>
</div>
<div class="flex items-center space-x-1">
<Calendar class="h-4 w-4 stroke-1.5" />
<span>
{{ dayjs(event.date).format("DD MMM YYYY") }}
</span>
</div>
<div class="flex items-center space-x-1">
<Clock class="h-4 w-4 stroke-1.5" />
<span>
{{ formatTime(event.start_time) }} - {{ formatTime(event.end_time) }}
</span>
</div>
<div class="flex items-center space-x-1">
<User class="h-4 w-4 stroke-1.5" />
<div class="flex flex-col space-y-4 text-sm text-gray-800">
<Tooltip :text="__('Email ID')">
<div class="flex items-center space-x-2 w-fit">
<User class="h-4 w-4 stroke-1.5" />
<span>
{{ event.member }}
</span>
</div>
</Tooltip>
<Tooltip :text="__('Course')">
<div class="flex items-center space-x-2 w-fit">
<BookOpen class="h-4 w-4 stroke-1.5" />
<span>
{{ event.course_title }}
</span>
</div>
</Tooltip>
<Tooltip v-if="event.batch_title" :text="__('Batch')">
<div class="flex items-center space-x-2 w-fit">
<Users class="h-4 w-4 stroke-1.5" />
<span>
{{ event.batch_title }}
</span>
</div>
</Tooltip>
<Tooltip :text="__('Date')">
<div class="flex items-center space-x-2 w-fit">
<Calendar class="h-4 w-4 stroke-1.5" />
<span>
{{ dayjs(event.date).format("DD MMM YYYY") }}
</span>
</div>
</Tooltip>
<Tooltip :text="__('Time')">
<div class="flex items-center space-x-2 w-fit">
<Clock class="h-4 w-4 stroke-1.5" />
<span>
{{ formatTime(event.start_time) }} - {{ formatTime(event.end_time) }}
</span>
</div>
</Tooltip>
</div>
<div class="flex items-center space-x-2 mt-auto">
<Button v-if="certificate.name" @click="openCertificate(certificate)" class="w-full">
<template #prefix>
<FileText class="h-4 w-4 stroke-1.5" />
</template>
{{ __("View Certificate") }}
</Button>
<Button v-else @click="openCallLink(event.venue)" class="w-full">
<template #prefix>
<Video class="h-4 w-4 stroke-1.5" />
</template>
<span>
{{ event.member }}
{{ __("Join Meeting") }}
</span>
</div>
</Button>
</div>
<Button @click="openCallLink(event.venue)" class="mt-auto">
<template #prefix>
<Video class="h-4 w-4 stroke-1.5" />
</template>
<span>
{{ __("Join Meeting") }}
</span>
</Button>
</div>
<div class="flex flex-col space-y-4 border-l w-1/2 p-5">
{{ evaluation.rating }}
<Rating v-model="evaluation.rating" :label="__('Rating')"/>
<FormControl type="select" :options='[{
value: "Pending",
label: __("Pending")
}, {
value: "In Progress",
label: __("In Progress")
}, {
value: "Pass",
label: __("Pass")
}, {
value: "Fail",
label: __("Fail")
}]'
v-model="evaluation.status" :label="__('Status')" />
<FormControl type="textarea" v-model="evaluation.summary" :label="__('Summary')" />
<Button variant="solid" @click="saveEvaluation()">
{{ __("Save") }}
</Button>
</div>
<Tabs :tabs='tabs' v-model="tabIndex" class="border-l w-1/2">
<template #default="{ tab }">
<div v-if="tab.label == 'Evaluation'" class="flex flex-col space-y-4 p-5">
<Rating v-model="evaluation.rating" :label="__('Rating')"/>
<FormControl type="select" :options='[{
value: "Pending",
label: __("Pending")
}, {
value: "In Progress",
label: __("In Progress")
}, {
value: "Pass",
label: __("Pass")
}, {
value: "Fail",
label: __("Fail")
}]'
v-model="evaluation.status" :label="__('Status')" />
<FormControl type="textarea" v-model="evaluation.summary" :label="__('Summary')" />
<Button variant="solid" @click="saveEvaluation()">
{{ __("Save") }}
</Button>
</div>
<div v-else class="flex flex-col space-y-4 p-5">

<FormControl type="checkbox" v-model="certificate.published" :label="__('Published')" />
<Link v-model="certificate.template" :label="__('Template')" doctype="Print Format" :filters='{
"doc_type": "LMS Certificate"
}' />
<FormControl type="date" v-model="certificate.issue_date" :label="__('Issue Date')" />
<FormControl type="date" v-model="certificate.expiry_date" :label="__('Expiry Date')" />
<Button variant="solid" @click="saveCertificate()">
{{ __("Save") }}
</Button>
</div>
</template>
</Tabs>
</div>
</template>
</Dialog>
</template>
<script setup>
import { Dialog, Button, FormControl, createResource } from 'frappe-ui';
import { User, Calendar, Clock, Video, BookOpen } from "lucide-vue-next"
import { inject, reactive, watch } from "vue"
import { Dialog, Button, FormControl, createResource, Tabs, Tooltip } from 'frappe-ui';
import { User, Calendar, Clock, Video, BookOpen, FileText, GraduationCap, Users, ClipboardList } from "lucide-vue-next"
import { inject, reactive, watch, ref, computed } from "vue"
import { formatTime, showToast } from "@/utils"
import Rating from "@/components/Controls/Rating.vue"
import Link from "@/components/Controls/Link.vue"
const show = defineModel()
const dayjs = inject("$dayjs")
const tabIndex = ref(0)
const showCertification = ref(false)
const props = defineProps({
event: {
Expand All @@ -89,10 +131,26 @@ const props = defineProps({
},
});
const evaluation = reactive({
rating: 0,
status: "Pending",
summary: "",
const evaluation = reactive({})
const certificate = reactive({})
const defaultTemplate = createResource({
url: "frappe.client.get_value",
makeParams(values) {
return {
doctype: "Property Setter",
fieldname: "value",
filters: {
doc_type: "LMS Certificate",
property: "default_print_format"
}
}
},
auto: true,
onSuccess(data) {
certificate.template = data.value
}
})
const openCallLink = (link) => {
Expand All @@ -105,6 +163,7 @@ const evaluationResource = createResource({
return {
member: props.event.member,
course: props.event.course,
batch_name: props.event.batch_name,
date: props.event.date,
start_time: props.event.start_time,
end_time: props.event.end_time,
Expand All @@ -113,7 +172,10 @@ const evaluationResource = createResource({
summary: evaluation.summary,
}
},
auto: false
auto: false,
onSuccess(data) {
evaluation.name = data.name
}
})
const evaluationDetails = createResource({
Expand All @@ -131,6 +193,10 @@ const evaluationDetails = createResource({
for (const key in data) {
if (key in evaluation)
evaluation[key] = data[key]
if (key == "rating")
evaluation.rating = data.rating * 5
if (evaluation.status == "Pass")
showCertification.value = true
}
},
auto: false
Expand All @@ -139,18 +205,105 @@ const evaluationDetails = createResource({
const saveEvaluation = () => {
evaluationResource.submit({}, {
onSuccess: () => {
show.value = false
if (evaluation.status == "Pass") {
showCertification.value = true
} else {
show.value = false
}
showToast( __("Success"), __("Evaluation saved successfully"), "check")
}
})
}
const certificateResource = createResource({
url: "lms.lms.api.save_certificate_details",
makeParams(values) {
return {
member: props.event.member,
course: props.event.course,
batch_name: props.event.batch_name,
published: certificate.published,
issue_date: certificate.issue_date,
expiry_date: certificate.expiry_date,
template: certificate.template,
}
},
auto: false,
onSuccess(data) {
certificate.name = data
}
})
const certificateDetails = createResource({
url: "frappe.client.get",
makeParams(values) {
return {
doctype: "LMS Certificate",
filters: {
member: props.event.member,
course: props.event.course,
}
}
},
onSuccess(data) {
for (const key in data) {
if (key in certificate)
certificate[key] = data[key]
certificate.name = data.name
showCertification.value = true
}
},
onError(err) {
certificate.template = defaultTemplate.data.value
},
auto: false
})
const saveCertificate = () => {
certificateResource.submit({}, {
onSuccess: () => {
showToast( __("Success"), __("Certificate saved successfully"), "check")
}
})
}
watch(show, () => {
if (show.value) {
evaluation.rating = 0
evaluation.status = "Pending"
evaluation.summary = ""
evaluationDetails.reload()
certificate.published = true
certificate.issue_date = dayjs().format("YYYY-MM-DD")
certificate.expiry_date = null
certificate.template = null
certificate.name = null
certificateDetails.reload()
}
})
const openCertificate = (certificate) => {
window.open(
`/api/method/frappe.utils.print_format.download_pdf?doctype=LMS+Certificate&name=${certificate.name}&format=${encodeURIComponent(certificate.template)}`
)
}
const tabs = computed(() => {
const tabsArray = [
{
label: __("Evaluation"),
icon: ClipboardList,
},
]
if (showCertification.value) {
tabsArray.push({
label: __("Certificate"),
icon: GraduationCap,
})
}
return tabsArray
})
</script>
Loading

0 comments on commit 7da608e

Please sign in to comment.