feat: Add CSAT response submit action (#2506)

Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
Muhsin Keloth 2021-06-25 12:00:49 +05:30 committed by GitHub
parent 2f9637bde5
commit dbddb1ece4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 103 additions and 29 deletions

View file

@ -54,7 +54,7 @@ class Api::V1::Widget::MessagesController < Api::V1::Widget::BaseController
end end
def message_update_params def message_update_params
params.permit(message: [{ submitted_values: [:name, :title, :value] }]) params.permit(message: [{ submitted_values: [:name, :title, :value, { csat_survey_response: [:feedback_text, :rating] }] }])
end end
def permitted_params def permitted_params

View file

@ -1,21 +1,20 @@
<template> <template>
<div class="customer-satisfcation"> <div class="customer-satisfcation">
<div class="title"> <h6 class="title">
{{ $t('CSAT.TITLE') }} {{ title }}
</div> </h6>
<div class="ratings"> <div class="ratings">
<button <button
v-for="rating in ratings" v-for="rating in ratings"
:key="rating.key" :key="rating.key"
class="emoji-button" :class="buttonClass(rating)"
:class="{ selected: rating.key === selectedRating }"
@click="selectRating(rating)" @click="selectRating(rating)"
> >
{{ rating.emoji }} {{ rating.emoji }}
</button> </button>
</div> </div>
<form <form
v-if="!hasSubmitted" v-if="!isCSATSubmitted"
class="feedback-form" class="feedback-form"
@submit.prevent="onSubmit()" @submit.prevent="onSubmit()"
> >
@ -27,7 +26,7 @@
/> />
<button <button
class="button" class="button"
:disabled="!selectedRating" :disabled="isButtonDisabled"
:style="{ background: widgetColor, borderColor: widgetColor }" :style="{ background: widgetColor, borderColor: widgetColor }"
> >
<i v-if="!isUpdating" class="ion-ios-arrow-forward" /> <i v-if="!isUpdating" class="ion-ios-arrow-forward" />
@ -46,6 +45,12 @@ export default {
components: { components: {
Spinner, Spinner,
}, },
props: {
messageContentAttributes: {
type: Object,
default: () => {},
},
},
data() { data() {
return { return {
email: '', email: '',
@ -53,19 +58,54 @@ export default {
selectedRating: null, selectedRating: null,
isUpdating: false, isUpdating: false,
feedback: '', feedback: '',
hasSubmitted: false,
}; };
}, },
computed: { computed: {
...mapGetters({ ...mapGetters({
widgetColor: 'appConfig/getWidgetColor', widgetColor: 'appConfig/getWidgetColor',
}), }),
isCSATSubmitted() {
return (
this.messageContentAttributes &&
this.messageContentAttributes.csat_survey_response
);
},
isButtonDisabled() {
return !(this.selectedRating && this.feedback);
},
title() {
return this.isCSATSubmitted
? this.$t('CSAT.SUBMITTED_TITLE')
: this.$t('CSAT.TITLE');
},
},
mounted() {
if (this.isCSATSubmitted) {
const {
csat_survey_response: { rating },
} = this.messageContentAttributes;
this.selectedRating = rating;
}
}, },
methods: { methods: {
onSubmit() {}, buttonClass(rating) {
return [
{ selected: rating.value === this.selectedRating },
{ disabled: this.isCSATSubmitted },
{ hover: this.isCSATSubmitted },
'emoji-button',
];
},
onSubmit() {
this.$emit('submit', {
rating: this.selectedRating,
feedback: this.feedback,
});
},
selectRating(rating) { selectRating(rating) {
this.selectedRating = rating.key; this.selectedRating = rating.value;
}, },
}, },
}; };
@ -77,54 +117,72 @@ export default {
.customer-satisfcation { .customer-satisfcation {
@include light-shadow; @include light-shadow;
background: $color-white; background: $color-white;
border-bottom-left-radius: $space-smaller; border-bottom-left-radius: $space-smaller;
color: $color-body; border-radius: $space-small;
border-top: $space-micro solid $color-woot; border-top: $space-micro solid $color-woot;
border-radius: $space-one; color: $color-body;
display: inline-block; display: inline-block;
line-height: 1.5; line-height: 1.5;
width: 75%; margin-top: $space-smaller;
width: 80%;
.title { .title {
font-size: $font-size-default; font-size: $font-size-default;
font-weight: $font-weight-medium; font-weight: $font-weight-medium;
padding-top: $space-two; padding: $space-two $space-one 0;
text-align: center; text-align: center;
} }
.ratings { .ratings {
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;
padding: $space-two $space-normal; padding: $space-two $space-normal;
.emoji-button { .emoji-button {
font-size: $font-size-big;
outline: none;
box-shadow: none; box-shadow: none;
filter: grayscale(100%); filter: grayscale(100%);
&.selected { font-size: $font-size-big;
outline: none;
&.selected,
&:hover,
&:focus,
&:active {
filter: grayscale(0%); filter: grayscale(0%);
transform: scale(1.32); transform: scale(1.32);
} }
&.disabled {
cursor: default;
opacity: 0.5;
pointer-events: none;
}
} }
} }
.feedback-form { .feedback-form {
display: flex; display: flex;
input { input {
width: 100%;
border: none;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
padding: $space-one; border-bottom-left-radius: $space-small;
border: 0;
border-top: 1px solid $color-border; border-top: 1px solid $color-border;
padding: $space-one;
width: 100%;
} }
.button { .button {
appearance: none;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
border-top-left-radius: 0; border-top-left-radius: 0;
border-bottom-right-radius: $space-small;
font-size: $font-size-large; font-size: $font-size-large;
height: auto; height: auto;
margin-left: -1px; margin-left: -1px;
appearance: none;
.spinner { .spinner {
display: block; display: block;
padding: 0; padding: 0;

View file

@ -17,26 +17,26 @@ export const CSAT_RATINGS = [
{ {
key: 'disappointed', key: 'disappointed',
emoji: '😞', emoji: '😞',
value: 0, value: 1,
}, },
{ {
key: 'expressionless', key: 'expressionless',
emoji: '😑', emoji: '😑',
value: 1, value: 2,
}, },
{ {
key: 'neutral', key: 'neutral',
emoji: '😐', emoji: '😐',
value: 2, value: 3,
}, },
{ {
key: 'grinning', key: 'grinning',
emoji: '😀', emoji: '😀',
value: 3, value: 4,
}, },
{ {
key: 'smiling', key: 'smiling',
emoji: '😍', emoji: '😍',
value: 4, value: 5,
}, },
]; ];

View file

@ -143,7 +143,7 @@ export default {
return ( return (
this.messageContentAttributes.submitted_email || this.messageContentAttributes.submitted_email ||
(this.messageContentAttributes.submitted_values && (this.messageContentAttributes.submitted_values &&
this.contentType !== 'form') !['form', 'input_csat'].includes(this.contentType))
); );
}, },
responseMessage() { responseMessage() {

View file

@ -44,7 +44,11 @@
<div v-if="isArticle"> <div v-if="isArticle">
<chat-article :items="messageContentAttributes.items"></chat-article> <chat-article :items="messageContentAttributes.items"></chat-article>
</div> </div>
<customer-satisfaction v-if="isCSAT" /> <customer-satisfaction
v-if="isCSAT"
:message-content-attributes="messageContentAttributes.submitted_values"
@submit="onCSATSubmit"
/>
</div> </div>
</template> </template>
@ -121,6 +125,17 @@ export default {
messageId: this.messageId, messageId: this.messageId,
}); });
}, },
onCSATSubmit({ feedback, rating }) {
this.onResponse({
submittedValues: {
csat_survey_response: {
rating,
feedback_text: feedback,
},
},
messageId: this.messageId,
});
},
}, },
}; };
</script> </script>

View file

@ -59,6 +59,7 @@
}, },
"CSAT": { "CSAT": {
"TITLE": "Rate your conversation", "TITLE": "Rate your conversation",
"SUBMITTED_TITLE": "Thank you for submitting the rating",
"PLACEHOLDER": "Tell us more..." "PLACEHOLDER": "Tell us more..."
} }
} }