feat: review submission

This commit is contained in:
Jannat Patel
2023-12-21 17:25:08 +05:30
parent afcb15148f
commit e1d61c9eb9
7 changed files with 70 additions and 20 deletions

View File

@@ -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>

View File

@@ -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 = {};

View File

@@ -16,7 +16,7 @@ const props = defineProps({
default: '', default: '',
}, },
modelValue: { modelValue: {
type: String, type: Number,
default: 0, default: 0,
}, },
}) })

View File

@@ -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();

View File

@@ -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"/>

View File

@@ -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
} }

View File

@@ -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()