fix: course creation form validations

This commit is contained in:
Jannat Patel
2024-02-28 23:42:17 +05:30
parent 60a917e60c
commit 8f504a8043
5 changed files with 139 additions and 51 deletions

View File

@@ -55,7 +55,7 @@
{{ resume.file_name }} {{ resume.file_name }}
</span> </span>
<span class="text-sm text-gray-500 mt-1"> <span class="text-sm text-gray-500 mt-1">
{{ getFileSize() }} {{ getFileSize(resume.file_size) }}
</span> </span>
</div> </div>
</div> </div>
@@ -67,7 +67,7 @@
import { Dialog, FileUploader, Button, createResource } from 'frappe-ui' import { Dialog, FileUploader, Button, createResource } from 'frappe-ui'
import { FileText } from 'lucide-vue-next' import { FileText } from 'lucide-vue-next'
import { ref, inject, defineModel } from 'vue' import { ref, inject, defineModel } from 'vue'
import { createToast } from '@/utils/' import { createToast, getFileSize } from '@/utils/'
const resume = ref(null) const resume = ref(null)
const show = defineModel() const show = defineModel()
@@ -87,16 +87,6 @@ const validateFile = (file) => {
} }
} }
const getFileSize = () => {
let value = parseInt(resume.value.file_size)
if (value > 1048576) {
return (value / 1048576).toFixed(2) + 'M'
} else if (value > 1024) {
return (value / 1024).toFixed(2) + 'K'
}
return value
}
const jobApplication = createResource({ const jobApplication = createResource({
url: 'frappe.client.insert', url: 'frappe.client.insert',
makeParams(values) { makeParams(values) {

View File

@@ -48,6 +48,7 @@ import { sessionStore } from '@/stores/session'
import { Dropdown } from 'frappe-ui' import { Dropdown } from 'frappe-ui'
import { ChevronDown, LogIn, LogOut, User } from 'lucide-vue-next' import { ChevronDown, LogIn, LogOut, User } from 'lucide-vue-next'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { convertToTitleCase } from '../utils'
const router = useRouter() const router = useRouter()
const props = defineProps({ const props = defineProps({
@@ -94,18 +95,4 @@ const userDropdownOptions = [
}, },
}, },
] ]
function convertToTitleCase(str) {
if (!str) {
return ''
}
return str
.toLowerCase()
.split(' ')
.map(function (word) {
return word.charAt(0).toUpperCase().concat(word.substr(1))
})
.join(' ')
}
</script> </script>

View File

@@ -25,11 +25,15 @@
</Button> </Button>
</header> </header>
<div class="container mt-5"> <div class="container mt-5">
<Input v-model="course.title" :label="__('Title')" class="mb-2" /> <FormControl
<Input v-model="course.title"
:label="__('Title')"
class="mb-4"
/>
<FormControl
v-model="course.short_introduction" v-model="course.short_introduction"
:label="__('Short Introduction')" :label="__('Short Introduction')"
class="mb-2" class="mb-4"
/> />
<div class="mb-4"> <div class="mb-4">
<div class="mb-1.5 text-sm text-gray-700"> <div class="mb-1.5 text-sm text-gray-700">
@@ -37,35 +41,81 @@
</div> </div>
<TextEditor <TextEditor
:content="course.description" :content="course.description"
@change="(val) => (topic.reply = val)" @change="(val) => (course.description = val)"
:editable="true" :editable="true"
:fixedMenu="true" :fixedMenu="true"
editorClass="prose-sm max-w-none border-b border-x bg-gray-100 rounded-b-md py-1 px-2 min-h-[7rem]" editorClass="prose-sm max-w-none border-b border-x bg-gray-100 rounded-b-md py-1 px-2 min-h-[7rem]"
/> />
</div> </div>
<Input <FormControl
v-model="course.video_link" v-model="course.video_link"
:label="__('Preview Video')" :label="__('Preview Video')"
class="mb-2" class="mb-4"
/> />
<Input v-model="course.tags" :label="__('Tags')" class="mb-2" /> <FileUploader
v-if="!course.image"
:fileTypes="['image/*']"
:validateFile="validateFile"
@success="
(file) => {
console.log(file)
course.image = file
console.log(course.image)
}
"
>
<template v-slot="{ file, progress, uploading, openFileSelector }">
<div class="mb-4">
<Button @click="openFileSelector" :loading="uploading">
{{ uploading ? `Uploading ${progress}%` : 'Upload an image' }}
</Button>
</div>
</template>
</FileUploader>
<div v-else class="flex items-center">
<div class="border rounded-md p-2 mr-2">
<FileText class="h-5 w-5 stroke-1.5 text-gray-700" />
</div>
<div class="flex flex-col">
<span>
{{ course.image }}
</span>
<span class="text-sm text-gray-500 mt-1">
{{ getFileSize(course.image) }}
</span>
</div>
</div>
<FormControl v-model="course.tags" :label="__('Tags')" class="mb-4" />
<div class="flex items-center mb-4"> <div class="flex items-center mb-4">
<Checkbox v-model="course.published" :label="__('Published')" /> <FormControl
<Checkbox type="checkbox"
v-model="course.published"
:label="__('Published')"
/>
<FormControl
type="checkbox"
v-model="course.upcoming" v-model="course.upcoming"
:label="__('Upcoming')" :label="__('Upcoming')"
class="ml-20" class="ml-20"
/> />
</div> </div>
<Checkbox <div class="mb-4">
v-model="course.paid_course" <FormControl
:label="__('Paid Course')" type="checkbox"
class="mb-2" v-model="course.paid_course"
/> :label="__('Paid Course')"
<Input />
</div>
<FormControl
v-model="course.course_price" v-model="course.course_price"
:label="__('Course Price')" :label="__('Course Price')"
class="mb-2" class="mb-4"
/>
<Link
doctype="Currency"
v-model="course.currency"
:filters="{ enabled: 1 }"
:label="__('Currency')"
/> />
</div> </div>
</div> </div>
@@ -76,14 +126,16 @@
<script setup> <script setup>
import { import {
Breadcrumbs, Breadcrumbs,
Input,
TextEditor, TextEditor,
Checkbox,
Button, Button,
createDocumentResource,
createResource, createResource,
FormControl,
FileUploader,
} from 'frappe-ui' } from 'frappe-ui'
import { reactive, inject, onMounted } from 'vue' import { reactive, inject, onMounted } from 'vue'
import { convertToTitleCase, createToast, getFileSize } from '../utils'
import Link from '@/components/Controls/Link.vue'
import { FileText } from 'lucide-vue-next'
const user = inject('$user') const user = inject('$user')
@@ -103,7 +155,7 @@ const course = reactive({
upcoming: false, upcoming: false,
image: null, image: null,
paid_course: false, paid_course: false,
course_price: 0, course_price: null,
currency: '', currency: '',
}) })
@@ -118,14 +170,48 @@ const courseResource = createResource({
} }
}, },
}) })
console.log(courseResource)
const submitCourse = () => { const submitCourse = () => {
courseResource.submit( courseResource.submit(
{}, {},
{ {
validate() {}, validate() {
const mandatory_fields = [
'title',
'short_introduction',
'description',
'video_link',
'image',
]
for (const field of mandatory_fields) {
if (!course[field]) {
let fieldLabel = convertToTitleCase(field.split('_').join(' '))
return `${fieldLabel} is mandatory`
}
}
if (course.paid_course && (!course.course_price || !course.currency)) {
return 'Course price and currency are mandatory for paid courses'
}
},
onError(err) {
createToast({
title: 'Error',
text: err.messages?.[0] || err,
icon: 'x',
iconClasses: 'bg-red-600 text-white rounded-md p-px',
position: 'top-center',
timeout: 10,
})
},
} }
) )
} }
const validateFile = (file) => {
console.log(file)
let extension = file.name.split('.').pop().toLowerCase()
if (!['jpg', 'jpeg', 'png'].includes(extension)) {
return 'Only image file is allowed.'
}
}
</script> </script>

View File

@@ -41,6 +41,29 @@ export function formatNumberIntoCurrency(number, currency) {
return '' return ''
} }
export function convertToTitleCase(str) {
if (!str) {
return ''
}
return str
.toLowerCase()
.split(' ')
.map(function (word) {
return word.charAt(0).toUpperCase().concat(word.substr(1))
})
.join(' ')
}
export function getFileSize(file_size) {
let value = parseInt(file_size)
if (value > 1048576) {
return (value / 1048576).toFixed(2) + 'M'
} else if (value > 1024) {
return (value / 1024).toFixed(2) + 'K'
}
return value
}
export function getTimezones() { export function getTimezones() {
return [ return [
'Pacific/Midway', 'Pacific/Midway',

View File

@@ -75,7 +75,8 @@
{ {
"fieldname": "video_link", "fieldname": "video_link",
"fieldtype": "Data", "fieldtype": "Data",
"label": "Video Embed Link" "label": "Video Embed Link",
"reqd": 1
}, },
{ {
"fieldname": "short_introduction", "fieldname": "short_introduction",
@@ -92,7 +93,8 @@
{ {
"fieldname": "image", "fieldname": "image",
"fieldtype": "Attach Image", "fieldtype": "Attach Image",
"label": "Preview Image" "label": "Preview Image",
"reqd": 1
}, },
{ {
"fieldname": "tags", "fieldname": "tags",
@@ -266,7 +268,7 @@
} }
], ],
"make_attachments_public": 1, "make_attachments_public": 1,
"modified": "2023-12-21 12:27:32.559901", "modified": "2024-02-28 11:20:47.700649",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "LMS", "module": "LMS",
"name": "LMS Course", "name": "LMS Course",