fix: ui issues

This commit is contained in:
Jannat Patel
2024-01-25 15:24:52 +05:30
parent f4e581f6cb
commit 8f317d2f44
9 changed files with 254 additions and 89 deletions

View File

@@ -16,13 +16,13 @@
}" }"
class="h-5 w-5 text-gray-900 stroke-1 mr-2" class="h-5 w-5 text-gray-900 stroke-1 mr-2"
/> />
<div class="text-base"> <div class="text-base font-medium">
{{ chapter.title }} {{ chapter.title }}
</div> </div>
</DisclosureButton> </DisclosureButton>
<DisclosurePanel class="pb-2"> <DisclosurePanel class="pb-2">
<div v-for="lesson in chapter.lessons" :key="lesson.name"> <div v-for="lesson in chapter.lessons" :key="lesson.name">
<div class="outline-lesson mb-2 pl-9"> <div class="outline-lesson my-2 pl-9">
<router-link <router-link
:to="{ :to="{
name: 'Lesson', name: 'Lesson',
@@ -91,6 +91,6 @@ const openChapter = (index) => {
<style> <style>
.outline-lesson:has(.router-link-active) { .outline-lesson:has(.router-link-active) {
background-color: theme('colors.gray.100'); background-color: theme('colors.gray.100');
padding: 0.5rem 0 0.5rem 2rem; padding: 0.5rem 0 0.5rem 2.25rem;
} }
</style> </style>

View File

@@ -0,0 +1,45 @@
<template>
<div class="flex border rounded-md p-2 mb-4 h-full">
<div class="mr-4">
<img
:src="job.company_logo"
class="w-11 h-11 rounded-lg object-contain"
/>
</div>
<div>
<div class="text-lg font-semibold mb-2">
{{ job.job_title }}
</div>
<div class="flex items-center mb-2 text-gray-700">
<div class="mr-5">
{{ job.company_name }}
</div>
<div class="flex items-center">
<MapPin class="h-4 w-4 mr-1 stroke-1.5" />
<span class="text-gray-700">
{{ job.location }}
</span>
</div>
</div>
<div class="flex items-center">
<Badge :label="job.type" theme="green" />
<div class="ml-5">
{{ dayjs(job.creation).format('DD MMM YYYY') }}
</div>
</div>
</div>
</div>
</template>
<script setup>
import { MapPin } from 'lucide-vue-next'
import { Badge } from 'frappe-ui'
import { inject } from 'vue'
const dayjs = inject('$dayjs')
const props = defineProps({
job: {
type: Object,
default: null,
},
})
</script>

View File

@@ -4,7 +4,7 @@
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"
> >
<Breadcrumbs class="h-7" :items="breadcrumbs" /> <Breadcrumbs class="h-7" :items="breadcrumbs" />
<Button @click="openAnnouncementModal()"> <Button v-if="user.data?.is_moderator" @click="openAnnouncementModal()">
<span> <span>
{{ __('Make an Announcement') }} {{ __('Make an Announcement') }}
</span> </span>

View File

@@ -1,93 +1,112 @@
<template> <template>
<div class="h-screen text-base"> <div class="h-screen text-base">
<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"
> >
<Breadcrumbs class="h-7" :items="[{ label: __('All Batches'), route: { name: 'Batches' } }]"/> <Breadcrumbs
<div class="flex"> class="h-7"
<Button variant="solid"> :items="[{ label: __('All Batches'), route: { name: 'Batches' } }]"
<template #prefix> />
<Plus class="h-4 w-4" /> <div class="flex">
</template> <Button variant="solid">
{{ __("New Batch") }} <template #prefix>
</Button> <Plus class="h-4 w-4" />
</div> </template>
</header> {{ __('New Batch') }}
<div class="mx-5 py-5"> </Button>
<Tabs class="overflow-hidden" v-model="tabIndex" :tabs="tabs"> </div>
<template #tab="{ tab, selected }"> </header>
<div> <div class="pb-5">
<button <Tabs v-model="tabIndex" :tabs="tabs" tablistClass="overflow-x-visible">
class="group -mb-px flex items-center gap-2 border-b border-transparent py-2.5 text-base text-gray-600 duration-300 ease-in-out hover:border-gray-400 hover:text-gray-900" <template #tab="{ tab, selected }">
:class="{ 'text-gray-900': selected }"> <div>
<component v-if="tab.icon" :is="tab.icon" class="h-5" /> <button
{{ __(tab.label) }} class="group -mb-px flex items-center gap-2 border-b border-transparent py-2.5 text-base text-gray-600 duration-300 ease-in-out hover:border-gray-400 hover:text-gray-900"
<Badge :class="{ 'text-gray-900 border border-gray-900': selected }" variant="subtle" theme="gray" :class="{ 'text-gray-900': selected }"
size="sm"> >
{{ tab.count }} <component v-if="tab.icon" :is="tab.icon" class="h-5" />
</Badge> {{ __(tab.label) }}
</button> <Badge
</div> :class="
</template> selected
<template #default="{ tab }"> ? 'text-gray-800 border border-gray-800'
<div v-if="tab.batches && tab.batches.value.length" class="grid grid-cols-1 sm:grid-cols-3 md:grid-cols-4 gap-8 mt-5"> : 'border border-gray-500'
<router-link v-for="batch in tab.batches.value" "
:to="{ name: 'BatchDetail', params: { batchName: batch.name } }"> variant="subtle"
<BatchCard :batch="batch" /> theme="gray"
</router-link> size="sm"
</div> >
<div v-else class="grid flex-1 place-items-center text-xl font-medium text-gray-500"> {{ tab.count }}
<div class="flex flex-col items-center justify-center mt-4"> </Badge>
<div> </button>
{{ __("No {0} batches found").format(tab.label.toLowerCase()) }} </div>
</div> </template>
</div> <template #default="{ tab }">
</div> <div
</template> v-if="tab.batches && tab.batches.value.length"
</Tabs> class="grid grid-cols-1 sm:grid-cols-3 md:grid-cols-4 gap-5 mt-5 mx-5"
</div> >
</div> <router-link
v-for="batch in tab.batches.value"
:to="{ name: 'BatchDetail', params: { batchName: batch.name } }"
>
<BatchCard :batch="batch" />
</router-link>
</div>
<div
v-else
class="grid flex-1 place-items-center text-xl font-medium text-gray-500"
>
<div class="flex flex-col items-center justify-center mt-4">
<div>
{{ __('No {0} batches found').format(tab.label.toLowerCase()) }}
</div>
</div>
</div>
</template>
</Tabs>
</div>
</div>
</template> </template>
<script setup> <script setup>
import { createResource, Breadcrumbs, Button, Tabs, Badge } from "frappe-ui"; import { createResource, Breadcrumbs, Button, Tabs, Badge } from 'frappe-ui'
import { Plus } from "lucide-vue-next" import { Plus } from 'lucide-vue-next'
import BatchCard from '@/components/BatchCard.vue'; import BatchCard from '@/components/BatchCard.vue'
import { inject, ref, computed } from "vue"; import { inject, ref, computed } from 'vue'
const user = inject("$user") const user = inject('$user')
const batches = createResource({ const batches = createResource({
url: "lms.lms.utils.get_batches", url: 'lms.lms.utils.get_batches',
cache: ["batches", user?.data?.email], cache: ['batches', user?.data?.email],
auto: true, auto: true,
}); })
const tabIndex = ref(0) const tabIndex = ref(0)
const tabs = [ const tabs = [
{ {
label: "Upcoming", label: 'Upcoming',
batches: computed(() => batches.data?.upcoming || []), batches: computed(() => batches.data?.upcoming || []),
count: computed(() => batches.data?.upcoming?.length), count: computed(() => batches.data?.upcoming?.length),
}, },
]; ]
if (user.data?.is_moderator) { if (user.data?.is_moderator) {
tabs.push({ tabs.push({
label: "Archived", label: 'Archived',
batches: computed(() => batches.data?.archived), batches: computed(() => batches.data?.archived),
count: computed(() => batches.data?.archived?.length), count: computed(() => batches.data?.archived?.length),
}); })
tabs.push({ tabs.push({
label: "Private", label: 'Private',
batches: computed(() => batches.data?.private), batches: computed(() => batches.data?.private),
count: computed(() => batches.data?.private?.length), count: computed(() => batches.data?.private?.length),
}) })
} }
if (user.data) { if (user.data) {
tabs.push({ tabs.push({
label: "Enrolled", label: 'Enrolled',
batches: computed(() => batches.data?.enrolled), batches: computed(() => batches.data?.enrolled),
count: computed(() => batches.data?.enrolled?.length) count: computed(() => batches.data?.enrolled?.length),
}) })
} }
</script>
</script>

View File

@@ -9,7 +9,7 @@
:items="[{ label: __('All Courses'), route: { name: 'Courses' } }]" :items="[{ label: __('All Courses'), route: { name: 'Courses' } }]"
/> />
<div class="flex"> <div class="flex">
<Button variant="solid"> <Button v-if="user.data.is_moderator" variant="solid">
<template #prefix> <template #prefix>
<Plus class="h-4 w-4" /> <Plus class="h-4 w-4" />
</template> </template>
@@ -17,8 +17,8 @@
</Button> </Button>
</div> </div>
</header> </header>
<div class="mx-5 py-5"> <div class="pb-5">
<Tabs class="overflow-hidden" v-model="tabIndex" :tabs="tabs"> <Tabs v-model="tabIndex" :tabs="tabs" tablistClass="overflow-x-visible">
<template #tab="{ tab, selected }"> <template #tab="{ tab, selected }">
<div> <div>
<button <button
@@ -28,7 +28,11 @@
<component v-if="tab.icon" :is="tab.icon" class="h-5" /> <component v-if="tab.icon" :is="tab.icon" class="h-5" />
{{ __(tab.label) }} {{ __(tab.label) }}
<Badge <Badge
:class="{ 'text-gray-900 border border-gray-900': selected }" :class="
selected
? 'text-gray-800 border border-gray-800'
: 'border border-gray-500'
"
variant="subtle" variant="subtle"
theme="gray" theme="gray"
size="sm" size="sm"
@@ -41,7 +45,7 @@
<template #default="{ tab }"> <template #default="{ tab }">
<div <div
v-if="tab.courses && tab.courses.value.length" v-if="tab.courses && tab.courses.value.length"
class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8 mt-5" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8 mt-5 mx-5"
> >
<router-link <router-link
v-for="course in tab.courses.value" v-for="course in tab.courses.value"

View File

@@ -0,0 +1,27 @@
<template>
<header
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
>
<Breadcrumbs
class="h-7"
:items="[{ label: __('Jobs'), route: { name: 'Jobs' } }]"
/>
<div class="flex">
<Button v-if="user.data?.name" variant="solid">
<template #prefix>
<Plus class="h-4 w-4" />
</template>
{{ __('New Job') }}
</Button>
</div>
</header>
<div></div>
</template>
<script setup>
const props = defineProps({
job: {
type: String,
required: true,
},
})
</script>

View File

@@ -0,0 +1,48 @@
<template>
<div class="h-screen text-base">
<header
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-3 py-2.5 sm:px-5"
>
<Breadcrumbs
class="h-7"
:items="[{ label: __('Jobs'), route: { name: 'Jobs' } }]"
/>
<div class="flex">
<Button v-if="user.data?.name" variant="solid">
<template #prefix>
<Plus class="h-4 w-4" />
</template>
{{ __('New Job') }}
</Button>
</div>
</header>
<div v-if="jobs.data">
<div class="grid grid-cols-2 gap-5 p-5">
<div v-if="jobs.data.length" v-for="job in jobs.data">
<router-link
:to="{
name: 'JobDetail',
params: { job: job.name },
}"
>
<JobCard :job="job" />
</router-link>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { Button, Breadcrumbs, createResource } from 'frappe-ui'
import { Plus } from 'lucide-vue-next'
import { inject } from 'vue'
import JobCard from '@/components/JobCard.vue'
const user = inject('$user')
const jobs = createResource({
url: 'lms.lms.utils.get_job_opportunities',
cache: ['jobs'],
auto: true,
})
</script>

View File

@@ -54,6 +54,17 @@ const routes = [
name: 'Statistics', name: 'Statistics',
component: () => import('@/pages/Statistics.vue'), component: () => import('@/pages/Statistics.vue'),
}, },
{
path: '/job-openings',
name: 'Jobs',
component: () => import('@/pages/Jobs.vue'),
},
{
path: '/job-openings/:job',
name: 'JobDetail',
component: () => import('@/pages/JobDetail.vue'),
props: true,
},
] ]
let router = createRouter({ let router = createRouter({

View File

@@ -1726,3 +1726,14 @@ def get_order_summary(doctype, docname, country=None):
details.total_amount_formatted = fmt_money(details.amount, 0, details.currency) details.total_amount_formatted = fmt_money(details.amount, 0, details.currency)
return details return details
@frappe.whitelist(allow_guest=True)
def get_job_opportunities():
jobs = frappe.get_all(
"Job Opportunity",
{"status": "Open", "disabled": False},
["job_title", "location", "type", "company_name", "company_logo", "name", "creation"],
order_by="creation desc",
)
return jobs