mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 19:17:48 +00:00 
			
		
		
		
	 d0611cb7f2
			
		
	
	d0611cb7f2
	
	
	
		
			
			# Pull Request Template ## Description This PR introduces basic customization options for the CSAT survey: * **Display Type**: Option to use star ratings instead of emojis. * **Message Text**: Customize the survey message (up to 200 characters). * **Survey Rules**: Send surveys based on labels — trigger when a conversation has or doesn't have a specific label. Fixes https://linear.app/chatwoot/document/improve-csat-responses-a61cf30e054e ## Type of change - [x] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? ### Loom videos **Website Channel (Widget)** https://www.loom.com/share/7f47836cde7940ae9d17b7997d060a18?sid=aad2ad0a-140a-4a09-8829-e01fa2e102c5 **Email Channel (Survey link)** https://www.loom.com/share/e92f4c4c0f73417ba300a25885e093ce?sid=4bb006f0-1c2a-4352-a232-8bf684e3d757 ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules --------- Co-authored-by: Pranav <pranavrajs@gmail.com>
		
			
				
	
	
		
			66 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			66 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <script setup>
 | |
| import { ref, defineProps, defineEmits } from 'vue';
 | |
| 
 | |
| const props = defineProps({
 | |
|   selectedRating: {
 | |
|     type: Number,
 | |
|     default: null,
 | |
|   },
 | |
|   isDisabled: {
 | |
|     type: Boolean,
 | |
|     default: false,
 | |
|   },
 | |
| });
 | |
| 
 | |
| const emit = defineEmits(['selectRating']);
 | |
| 
 | |
| const starRatings = [1, 2, 3, 4, 5];
 | |
| const hoveredRating = ref(0);
 | |
| 
 | |
| const onHoverRating = value => {
 | |
|   if (props.isDisabled) return;
 | |
|   hoveredRating.value = value;
 | |
| };
 | |
| 
 | |
| const selectRating = value => {
 | |
|   if (props.isDisabled) return;
 | |
|   emit('selectRating', value);
 | |
| };
 | |
| 
 | |
| const getStarClass = value => {
 | |
|   const isStarActive =
 | |
|     (hoveredRating.value > 0 &&
 | |
|       !props.isDisabled &&
 | |
|       hoveredRating.value >= value) ||
 | |
|     props.selectedRating >= value;
 | |
| 
 | |
|   const starTypeClass = isStarActive
 | |
|     ? 'i-ri-star-fill text-n-amber-9'
 | |
|     : 'i-ri-star-line text-n-slate-10';
 | |
| 
 | |
|   return starTypeClass;
 | |
| };
 | |
| </script>
 | |
| 
 | |
| <template>
 | |
|   <div class="flex justify-center py-5 px-4 gap-3">
 | |
|     <button
 | |
|       v-for="value in starRatings"
 | |
|       :key="value"
 | |
|       type="button"
 | |
|       class="rounded-full p-1 transition-all duration-200 focus:enabled:scale-[1.2] focus-within:enabled:scale-[1.2] hover:enabled:scale-[1.2] focus:outline-none flex items-center flex-shrink-0"
 | |
|       :class="{ 'cursor-not-allowed opacity-50': isDisabled }"
 | |
|       :disabled="isDisabled"
 | |
|       :aria-label="'Star ' + value"
 | |
|       @click="selectRating(value)"
 | |
|       @mouseenter="onHoverRating(value)"
 | |
|       @mouseleave="onHoverRating(0)"
 | |
|     >
 | |
|       <span
 | |
|         :class="getStarClass(value)"
 | |
|         class="transition-all duration-500 text-2xl"
 | |
|       />
 | |
|     </button>
 | |
|   </div>
 | |
| </template>
 |