feat: review submission
This commit is contained in:
@@ -2,10 +2,12 @@
|
|||||||
<DesktopLayout>
|
<DesktopLayout>
|
||||||
<router-view />
|
<router-view />
|
||||||
</DesktopLayout>
|
</DesktopLayout>
|
||||||
|
<Dialogs />
|
||||||
<Toasts />
|
<Toasts />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import DesktopLayout from '@/components/DesktopLayout.vue'
|
import DesktopLayout from '@/components/DesktopLayout.vue'
|
||||||
import { Toasts } from 'frappe-ui'
|
import { Toasts } from 'frappe-ui'
|
||||||
|
import { Dialogs } from '@/utils/dialogs'
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
{{ reviews.data.length }} {{ __("reviews") }}
|
{{ reviews.data.length }} {{ __("reviews") }}
|
||||||
</div>
|
</div>
|
||||||
<Button @click="openReviewModal()">
|
<Button v-if="membership" @click="openReviewModal()">
|
||||||
<span>
|
<span>
|
||||||
{{ __("Write a review") }}
|
{{ __("Write a review") }}
|
||||||
</span>
|
</span>
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ReviewModal v-model="showReviewModal" v-model:reloadReviews="reviews"/>
|
<ReviewModal v-model="showReviewModal" v-model:reloadReviews="reviews" :courseName="courseName"/>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Star } from 'lucide-vue-next'
|
import { Star } from 'lucide-vue-next'
|
||||||
@@ -80,6 +80,10 @@ const props = defineProps({
|
|||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
membership: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -94,7 +98,7 @@ const reviews = createResource({
|
|||||||
},
|
},
|
||||||
auto: true,
|
auto: true,
|
||||||
});
|
});
|
||||||
|
console.log(reviews)
|
||||||
const rating_percent = computed(() => {
|
const rating_percent = computed(() => {
|
||||||
let rating_count = {};
|
let rating_count = {};
|
||||||
let rating_percent = {};
|
let rating_percent = {};
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const props = defineProps({
|
|||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: String,
|
type: Number,
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
{
|
{
|
||||||
label: "Submit",
|
label: "Submit",
|
||||||
variant: "solid",
|
variant: "solid",
|
||||||
onClick: ({ close }) => submitReview(close)
|
onClick: (close) => submitReview(close)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}'>
|
}'>
|
||||||
@@ -30,12 +30,23 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Dialog, Textarea, createResource } from 'frappe-ui'
|
import { Dialog, Textarea, createResource } from 'frappe-ui'
|
||||||
import { defineModel, ref } from "vue"
|
import { defineModel, reactive } from "vue"
|
||||||
import Rating from '@/components/Rating.vue';
|
import Rating from '@/components/Rating.vue';
|
||||||
|
import { createToast } from "@/utils/"
|
||||||
|
|
||||||
const show = defineModel()
|
const show = defineModel()
|
||||||
const reviews = defineModel("reloadReviews")
|
const reviews = defineModel("reloadReviews")
|
||||||
let review = ref({})
|
let review = reactive({
|
||||||
|
review: "",
|
||||||
|
rating: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
courseName: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const createReview = createResource({
|
const createReview = createResource({
|
||||||
url: "frappe.client.insert",
|
url: "frappe.client.insert",
|
||||||
@@ -43,22 +54,28 @@ const createReview = createResource({
|
|||||||
return {
|
return {
|
||||||
doc: {
|
doc: {
|
||||||
doctype: "LMS Course Review",
|
doctype: "LMS Course Review",
|
||||||
|
course: props.courseName,
|
||||||
...values,
|
...values,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
function submitReview(close) {
|
function submitReview(close) {
|
||||||
|
review.rating = (review.rating)/5;
|
||||||
createReview.submit(review, {
|
createReview.submit(review, {
|
||||||
validate() {
|
validate() {
|
||||||
/* if (!review.value.rating) {
|
if (!review.rating) {
|
||||||
return __("Please select a rating")
|
return "Please enter a rating."
|
||||||
}
|
}
|
||||||
if (!review.value.review) {
|
|
||||||
return __("Please write a review")
|
|
||||||
} */
|
|
||||||
}, onSuccess() {
|
}, onSuccess() {
|
||||||
reviews.reload()
|
reviews.value.reload()
|
||||||
|
},
|
||||||
|
onError(err) {
|
||||||
|
createToast({
|
||||||
|
text: err.messages?.[0] || err,
|
||||||
|
icon: 'x',
|
||||||
|
iconClasses: 'text-red-600 bg-red-300',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
close();
|
close();
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<CourseOutline :courseName="course.data.name"/>
|
<CourseOutline :courseName="course.data.name"/>
|
||||||
</div>
|
</div>
|
||||||
<CourseReviews v-if="course.data.avg_rating" :courseName="course.data.name" :avg_rating="course.data.avg_rating"/>
|
<CourseReviews v-if="course.data.avg_rating" :courseName="course.data.name" :avg_rating="course.data.avg_rating" :membership="course.data.membership"/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<CourseCardOverlay :course="course"/>
|
<CourseCardOverlay :course="course"/>
|
||||||
|
|||||||
@@ -5,9 +5,10 @@
|
|||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"review",
|
|
||||||
"rating",
|
"rating",
|
||||||
"course"
|
"course",
|
||||||
|
"column_break_lrtk",
|
||||||
|
"review"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -20,7 +21,8 @@
|
|||||||
"fieldname": "rating",
|
"fieldname": "rating",
|
||||||
"fieldtype": "Rating",
|
"fieldtype": "Rating",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Rating"
|
"label": "Rating",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "course",
|
"fieldname": "course",
|
||||||
@@ -28,12 +30,17 @@
|
|||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Course",
|
"label": "Course",
|
||||||
"options": "LMS Course"
|
"options": "LMS Course",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_lrtk",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-11-16 17:23:50.697891",
|
"modified": "2023-12-21 15:25:16.744558",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "LMS Course Review",
|
"name": "LMS Course Review",
|
||||||
@@ -50,11 +57,24 @@
|
|||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "LMS Student",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"search_fields": "course",
|
"search_fields": "course",
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"title_field": "course",
|
"title_field": "course",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,14 @@ from frappe.utils import cint
|
|||||||
|
|
||||||
|
|
||||||
class LMSCourseReview(Document):
|
class LMSCourseReview(Document):
|
||||||
pass
|
def validate(self):
|
||||||
|
self.validate_if_already_reviewed()
|
||||||
|
|
||||||
|
def validate_if_already_reviewed(self):
|
||||||
|
if frappe.db.exists(
|
||||||
|
"LMS Course Review", {"course": self.course, "owner": self.owner}
|
||||||
|
):
|
||||||
|
frappe.throw(frappe._("You have already reviewed this course"))
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
Reference in New Issue
Block a user