feat: badges
This commit is contained in:
9
frontend/src/components/BadgePopover.vue
Normal file
9
frontend/src/components/BadgePopover.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template></template>
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
badge: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
@@ -140,7 +140,7 @@ const coverImage = createResource({
|
||||
|
||||
const setActiveTab = () => {
|
||||
let fragments = route.path.split('/')
|
||||
let sections = ['certificates', 'roles', 'evaluations']
|
||||
let sections = ['certificates', 'achievements', 'roles', 'evaluations']
|
||||
sections.forEach((section) => {
|
||||
if (fragments.includes(section)) {
|
||||
activeTab.value = convertToTitleCase(section)
|
||||
@@ -154,6 +154,7 @@ watchEffect(() => {
|
||||
let route = {
|
||||
About: { name: 'ProfileAbout' },
|
||||
Certificates: { name: 'ProfileCertificates' },
|
||||
Achievements: { name: 'ProfileAchievements' },
|
||||
Roles: { name: 'ProfileRoles' },
|
||||
Evaluations: { name: 'ProfileEvaluator' },
|
||||
}[activeTab.value]
|
||||
@@ -170,7 +171,11 @@ const isSessionUser = () => {
|
||||
}
|
||||
|
||||
const getTabButtons = () => {
|
||||
let buttons = [{ label: 'About' }, { label: 'Certificates' }]
|
||||
let buttons = [
|
||||
{ label: 'About' },
|
||||
{ label: 'Certificates' },
|
||||
{ label: 'Achievements' },
|
||||
]
|
||||
if ($user.data?.is_moderator) buttons.push({ label: 'Roles' })
|
||||
if (isSessionUser() && $user.data?.is_evaluator)
|
||||
buttons.push({ label: 'Evaluations' })
|
||||
|
||||
65
frontend/src/pages/ProfileAchievements.vue
Normal file
65
frontend/src/pages/ProfileAchievements.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div class="mt-7 mb-10">
|
||||
<h2 class="mb-3 text-lg font-semibold text-gray-900">
|
||||
{{ __('Achievements') }}
|
||||
</h2>
|
||||
<div class="grid grid-cols-5 gap-4">
|
||||
<div v-if="badges.data" v-for="badge in badges.data">
|
||||
<Popover trigger="hover" hoverDelay="0.0">
|
||||
<template #target>
|
||||
<img :src="badge.badge_image" :alt="badge.badge" class="h-[80px]" />
|
||||
</template>
|
||||
<template #body-main>
|
||||
<div class="w-[250px] text-base">
|
||||
<img
|
||||
:src="badge.badge_image"
|
||||
:alt="badge.badge"
|
||||
class="bg-gray-100 rounded-t-md"
|
||||
/>
|
||||
<div class="p-5">
|
||||
<div class="text-2xl font-semibold mb-2">
|
||||
{{ badge.badge }}
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
{{ badge.badge_description }}
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<span class="text-xs text-gray-700 font-medium mb-1">
|
||||
{{ __('Issued on') }}:
|
||||
</span>
|
||||
{{ dayjs(badge.issued_on).format('DD MMM YYYY') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { createResource, Popover } from 'frappe-ui'
|
||||
import BadgePopover from '@/components/BadgePopover.vue'
|
||||
import { inject } from 'vue'
|
||||
|
||||
const dayjs = inject('$dayjs')
|
||||
|
||||
const props = defineProps({
|
||||
profile: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const badges = createResource({
|
||||
url: 'frappe.client.get_list',
|
||||
params: {
|
||||
doctype: 'LMS Badge Assignment',
|
||||
fields: ['name', 'badge', 'badge_image', 'badge_description', 'issued_on'],
|
||||
filters: {
|
||||
member: props.profile.data.name,
|
||||
},
|
||||
},
|
||||
auto: true,
|
||||
})
|
||||
</script>
|
||||
@@ -72,6 +72,11 @@ const routes = [
|
||||
path: 'certificates',
|
||||
component: () => import('@/pages/ProfileCertificates.vue'),
|
||||
},
|
||||
{
|
||||
name: 'ProfileAchievements',
|
||||
path: 'achievements',
|
||||
component: () => import('@/pages/ProfileAchievements.vue'),
|
||||
},
|
||||
{
|
||||
name: 'ProfileRoles',
|
||||
path: 'roles',
|
||||
|
||||
Reference in New Issue
Block a user