fix: cleanup ui
This commit is contained in:
@@ -15,13 +15,13 @@
|
|||||||
"markdown-it": "^14.0.0",
|
"markdown-it": "^14.0.0",
|
||||||
"pinia": "^2.0.33",
|
"pinia": "^2.0.33",
|
||||||
"socket.io-client": "^4.7.2",
|
"socket.io-client": "^4.7.2",
|
||||||
"tailwindcss": "^3.2.7",
|
"tailwindcss": "^3.3.3",
|
||||||
"vue": "^3.2.25",
|
"vue": "^3.2.25",
|
||||||
"vue-chartjs": "^5.0.0",
|
"vue-chartjs": "^5.0.0",
|
||||||
"vue-router": "^4.0.12"
|
"vue-router": "^4.0.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^2.0.0",
|
"@vitejs/plugin-vue": "^5.0.3",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"postcss": "^8.4.5",
|
"postcss": "^8.4.5",
|
||||||
"vite": "^5.0.11"
|
"vite": "^5.0.11"
|
||||||
|
|||||||
@@ -153,8 +153,8 @@ const props = defineProps({
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: theme('colors.gray.200');
|
background-color: theme('colors.orange.100');
|
||||||
color: theme('colors.gray.700');
|
color: theme('colors.orange.600');
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-group {
|
.avatar-group {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="border border-gray-200 rounded-md min-w-80">
|
<div class="shadow rounded-md min-w-80">
|
||||||
<iframe
|
<iframe
|
||||||
v-if="course.data.video_link"
|
v-if="course.data.video_link"
|
||||||
:src="video_link"
|
:src="video_link"
|
||||||
@@ -70,13 +70,13 @@
|
|||||||
<div class="mt-8 mb-4 font-medium">
|
<div class="mt-8 mb-4 font-medium">
|
||||||
{{ __('This course has:') }}
|
{{ __('This course has:') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center mb-4">
|
<div class="flex items-center mb-3">
|
||||||
<BookOpen class="h-5 w-5 stroke-1.5 text-gray-600" />
|
<BookOpen class="h-5 w-5 stroke-1.5 text-gray-600" />
|
||||||
<span class="ml-2">
|
<span class="ml-2">
|
||||||
{{ course.data.lesson_count }} {{ __('Lessons') }}
|
{{ course.data.lesson_count }} {{ __('Lessons') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center mb-4">
|
<div class="flex items-center mb-3">
|
||||||
<Users class="h-5 w-5 stroke-1.5 text-gray-600" />
|
<Users class="h-5 w-5 stroke-1.5 text-gray-600" />
|
||||||
<span class="ml-2">
|
<span class="ml-2">
|
||||||
{{ course.data.enrollment_count_formatted }}
|
{{ course.data.enrollment_count_formatted }}
|
||||||
|
|||||||
@@ -52,10 +52,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { Star } from 'lucide-vue-next'
|
import { Star } from 'lucide-vue-next'
|
||||||
import { createResource, Button } from 'frappe-ui'
|
import { createResource, Button } from 'frappe-ui'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref, inject } from 'vue'
|
||||||
import UserAvatar from '@/components/UserAvatar.vue'
|
import UserAvatar from '@/components/UserAvatar.vue'
|
||||||
import ReviewModal from '@/components/Modals/ReviewModal.vue'
|
import ReviewModal from '@/components/Modals/ReviewModal.vue'
|
||||||
|
|
||||||
|
const user = inject('$user')
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
courseName: {
|
courseName: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -81,12 +83,9 @@ const hasReviewed = createResource({
|
|||||||
owner: props.membership?.member,
|
owner: props.membership?.member,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
auto: true,
|
auto: user.data?.name ? true : false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const reversedRange = (count) =>
|
|
||||||
Array.from({ length: count }, (_, index) => count - index)
|
|
||||||
|
|
||||||
const reviews = createResource({
|
const reviews = createResource({
|
||||||
url: 'lms.lms.utils.get_reviews',
|
url: 'lms.lms.utils.get_reviews',
|
||||||
cache: ['course_reviews', props.courseName],
|
cache: ['course_reviews', props.courseName],
|
||||||
@@ -96,26 +95,6 @@ const reviews = createResource({
|
|||||||
auto: true,
|
auto: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const rating_percent = computed(() => {
|
|
||||||
let rating_count = {}
|
|
||||||
let rating_percent = {}
|
|
||||||
|
|
||||||
for (const key of [1, 2, 3, 4, 5]) {
|
|
||||||
rating_count[key] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const review of reviews?.data) {
|
|
||||||
rating_count[review.rating] += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
;[1, 2, 3, 4, 5].forEach((key) => {
|
|
||||||
rating_percent[key] = (
|
|
||||||
(rating_count[key] / reviews.data.length) *
|
|
||||||
100
|
|
||||||
).toFixed(2)
|
|
||||||
})
|
|
||||||
return rating_percent
|
|
||||||
})
|
|
||||||
const showReviewModal = ref(false)
|
const showReviewModal = ref(false)
|
||||||
|
|
||||||
function openReviewModal() {
|
function openReviewModal() {
|
||||||
|
|||||||
@@ -1,34 +1,69 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex border rounded-md p-2 mb-4 h-full">
|
<div class="flex shadow rounded-md p-4 h-full">
|
||||||
<div class="mr-4">
|
|
||||||
<img
|
<img
|
||||||
:src="job.company_logo"
|
:src="job.company_logo"
|
||||||
class="w-11 h-11 rounded-lg object-contain"
|
class="w-12 h-12 rounded-lg object-contain mr-4"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<div class="text-lg font-semibold mb-2">
|
<div class="text-xl font-semibold mb-2">
|
||||||
{{ job.job_title }}
|
{{ job.job_title }}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center mb-2 text-gray-700">
|
<div>
|
||||||
<div class="mr-5">
|
{{ __('posted by') }}
|
||||||
|
<span class="font-medium">
|
||||||
{{ job.company_name }}
|
{{ job.company_name }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center my-4">
|
||||||
<MapPin class="h-4 w-4 mr-1 stroke-1.5" />
|
<Badge :label="job.type" theme="green" size="lg" class="mr-4" />
|
||||||
<span class="text-gray-700">
|
<Badge :label="job.location" theme="gray" size="lg">
|
||||||
{{ job.location }}
|
<template #prefix>
|
||||||
|
<MapPin class="h-4 w-4 stroke-1.5" />
|
||||||
|
</template>
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ __('posted on') }}
|
||||||
|
<span class="font-medium">
|
||||||
|
{{ dayjs(job.creation).format('DD MMM YYYY') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="flex flex-col shadow rounded-md p-4 h-full">
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<div>
|
||||||
|
<div class="text-xl font-semibold mb-2">
|
||||||
|
{{ job.job_title }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ __("posted by") }}
|
||||||
|
<span class="font-medium">
|
||||||
|
{{ job.company_name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img
|
||||||
|
:src="job.company_logo"
|
||||||
|
class="w-12 h-12 rounded-lg object-contain"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-between mt-8">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<Badge :label="job.type" theme="green" />
|
<Badge :label="job.type" theme="green" size="lg" class="mr-4"/>
|
||||||
<div class="ml-5">
|
<Badge :label="job.location" theme="gray" size="lg">
|
||||||
|
<template #prefix>
|
||||||
|
<MapPin class="h-4 w-4 stroke-1.5" />
|
||||||
|
</template>
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="font-medium">
|
||||||
{{ dayjs(job.creation).format('DD MMM YYYY') }}
|
{{ dayjs(job.creation).format('DD MMM YYYY') }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { MapPin } from 'lucide-vue-next'
|
import { MapPin } from 'lucide-vue-next'
|
||||||
|
|||||||
@@ -1,28 +1,40 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dropdown :options="userDropdownOptions">
|
<Dropdown :options="userDropdownOptions">
|
||||||
<template v-slot="{ open }">
|
<template v-slot="{ open }">
|
||||||
<button class="flex h-12 py-2 items-center rounded-md duration-300 ease-in-out" :class="isCollapsed
|
<button
|
||||||
|
class="flex h-12 py-2 items-center rounded-md duration-300 ease-in-out"
|
||||||
|
:class="
|
||||||
|
isCollapsed
|
||||||
? 'px-0 w-auto'
|
? 'px-0 w-auto'
|
||||||
: open
|
: open
|
||||||
? 'bg-white shadow-sm px-2 w-52'
|
? 'bg-white shadow-sm px-2 w-52'
|
||||||
: 'hover:bg-gray-200 px-2 w-52'
|
: 'hover:bg-gray-200 px-2 w-52'
|
||||||
">
|
"
|
||||||
|
>
|
||||||
<LMSLogo class="w-8 h-8 rounded flex-shrink-0" />
|
<LMSLogo class="w-8 h-8 rounded flex-shrink-0" />
|
||||||
<div class="flex flex-1 flex-col text-left duration-300 ease-in-out" :class="isCollapsed
|
<div
|
||||||
|
class="flex flex-1 flex-col text-left duration-300 ease-in-out"
|
||||||
|
:class="
|
||||||
|
isCollapsed
|
||||||
? 'opacity-0 ml-0 w-0 overflow-hidden'
|
? 'opacity-0 ml-0 w-0 overflow-hidden'
|
||||||
: 'opacity-100 ml-2 w-auto'
|
: 'opacity-100 ml-2 w-auto'
|
||||||
">
|
"
|
||||||
|
>
|
||||||
<div class="text-base font-medium text-gray-900 leading-none">
|
<div class="text-base font-medium text-gray-900 leading-none">
|
||||||
LMS
|
Learning
|
||||||
</div>
|
</div>
|
||||||
<div v-if="user" class="mt-1 text-sm text-gray-700 leading-none">
|
<div v-if="user" class="mt-1 text-sm text-gray-700 leading-none">
|
||||||
{{ convertToTitleCase(user.split('@')[0]) }}
|
{{ convertToTitleCase(user.split('@')[0]) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="duration-300 ease-in-out" :class="isCollapsed
|
<div
|
||||||
|
class="duration-300 ease-in-out"
|
||||||
|
:class="
|
||||||
|
isCollapsed
|
||||||
? 'opacity-0 ml-0 w-0 overflow-hidden'
|
? 'opacity-0 ml-0 w-0 overflow-hidden'
|
||||||
: 'opacity-100 ml-2 w-auto'
|
: 'opacity-100 ml-2 w-auto'
|
||||||
">
|
"
|
||||||
|
>
|
||||||
<ChevronDown class="h-4 w-4 text-gray-700" />
|
<ChevronDown class="h-4 w-4 text-gray-700" />
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
@@ -44,7 +56,7 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { logout, user } = sessionStore()
|
const { logout, user } = sessionStore()
|
||||||
let { isLoggedIn } = sessionStore();
|
let { isLoggedIn } = sessionStore()
|
||||||
|
|
||||||
const userDropdownOptions = [
|
const userDropdownOptions = [
|
||||||
{
|
{
|
||||||
@@ -52,12 +64,12 @@ const userDropdownOptions = [
|
|||||||
label: 'Log out',
|
label: 'Log out',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
logout.submit().then(() => {
|
logout.submit().then(() => {
|
||||||
isLoggedIn = false;
|
isLoggedIn = false
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
condition: () => {
|
condition: () => {
|
||||||
return isLoggedIn
|
return isLoggedIn
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'log-in',
|
icon: 'log-in',
|
||||||
@@ -67,17 +79,21 @@ const userDropdownOptions = [
|
|||||||
},
|
},
|
||||||
condition: () => {
|
condition: () => {
|
||||||
return !isLoggedIn
|
return !isLoggedIn
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
]
|
||||||
|
|
||||||
function convertToTitleCase(str) {
|
function convertToTitleCase(str) {
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return ""
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
return str.toLowerCase().split(' ').map(function (word) {
|
return str
|
||||||
return word.charAt(0).toUpperCase().concat(word.substr(1));
|
.toLowerCase()
|
||||||
}).join(' ');
|
.split(' ')
|
||||||
|
.map(function (word) {
|
||||||
|
return word.charAt(0).toUpperCase().concat(word.substr(1))
|
||||||
|
})
|
||||||
|
.join(' ')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div class="text-base h-screen">
|
||||||
<header
|
<header
|
||||||
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
|
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
|
||||||
>
|
>
|
||||||
@@ -16,12 +17,32 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div></div>
|
<div></div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import {
|
||||||
|
createDocumentResource,
|
||||||
|
Button,
|
||||||
|
Breadcrumbs,
|
||||||
|
createResource,
|
||||||
|
} from 'frappe-ui'
|
||||||
|
import { inject } from 'vue'
|
||||||
|
import { Plus } from 'lucide-vue-next'
|
||||||
|
|
||||||
|
const user = inject('$user')
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
job: {
|
job: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const job = createResource({
|
||||||
|
url: 'lms.lms.api.get_job_details',
|
||||||
|
params: {
|
||||||
|
job: props.job,
|
||||||
|
},
|
||||||
|
cache: ['job'],
|
||||||
|
auto: true,
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import JobCard from '@/components/JobCard.vue'
|
|||||||
const user = inject('$user')
|
const user = inject('$user')
|
||||||
|
|
||||||
const jobs = createResource({
|
const jobs = createResource({
|
||||||
url: 'lms.lms.utils.get_job_opportunities',
|
url: 'lms.lms.api.get_job_opportunities',
|
||||||
cache: ['jobs'],
|
cache: ['jobs'],
|
||||||
auto: true,
|
auto: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -361,12 +361,6 @@ const hideLesson = () => {
|
|||||||
transition: margin 0.1s ease-in-out;
|
transition: margin 0.1s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
iframe {
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lesson-content p {
|
.lesson-content p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.7;
|
line-height: 1.7;
|
||||||
|
|||||||
2419
frontend/yarn.lock
2419
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user