helpdesk_rating_five_stars/views/rating_templates.xml
2025-11-26 10:39:26 +07:00

375 lines
16 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Web Rating Form Template -->
<template id="rating_form_page" name="Rating Form Page">
<t t-call="web.layout">
<t t-set="head">
<style>
.rating_form_container {
max-width: 600px;
margin: 80px auto;
padding: 40px;
text-align: center;
background: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0,0,0,0.15);
}
.rating_form_title {
font-size: 28px;
font-weight: 600;
color: #212529;
margin-bottom: 16px;
}
.rating_form_description {
font-size: 16px;
color: #6c757d;
margin-bottom: 32px;
line-height: 1.6;
}
.rating_form_ticket_info {
background: #f8f9fa;
padding: 16px;
border-radius: 6px;
margin-bottom: 32px;
font-size: 14px;
color: #495057;
}
.rating_form_ticket_info strong {
color: #212529;
}
.rating_form_widget_container {
margin: 32px 0;
display: flex;
justify-content: center;
}
.rating_form_submit_container {
margin-top: 32px;
}
.rating_form_submit_btn {
background: #007bff;
color: white;
border: none;
padding: 12px 32px;
font-size: 16px;
font-weight: 500;
border-radius: 6px;
cursor: pointer;
transition: background 0.2s;
}
.rating_form_submit_btn:hover {
background: #0056b3;
}
.rating_form_submit_btn:disabled {
background: #6c757d;
cursor: not-allowed;
}
.rating_form_feedback {
margin-top: 24px;
}
.rating_form_feedback textarea {
width: 100%;
min-height: 100px;
padding: 12px;
border: 1px solid #ced4da;
border-radius: 6px;
font-size: 14px;
font-family: inherit;
resize: vertical;
}
.rating_form_feedback textarea:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0,123,255,0.1);
}
.rating_form_feedback_label {
display: block;
text-align: left;
font-size: 14px;
font-weight: 500;
color: #495057;
margin-bottom: 8px;
}
@media (max-width: 768px) {
.rating_form_container {
margin: 40px 20px;
padding: 24px;
}
.rating_form_title {
font-size: 24px;
}
}
</style>
</t>
<div class="rating_form_container">
<h1 class="rating_form_title">Rate Your Experience</h1>
<p class="rating_form_description">
We value your feedback! Please rate your experience with our support team.
</p>
<t t-if="ticket_name">
<div class="rating_form_ticket_info">
<strong>Ticket:</strong> <t t-esc="ticket_name"/>
</div>
</t>
<form id="rating_form" method="POST" t-att-action="'/rating/' + token + '/submit'">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" id="rating_value_input" name="rating_value" value="0"/>
<div class="rating_form_widget_container">
<div id="rating_stars_widget" class="rating-stars-container rating-stars-large">
<span class="rating-star rating-star-empty rating-star-interactive" data-star="1" role="button" aria-label="Rate 1 star out of 5"></span>
<span class="rating-star rating-star-empty rating-star-interactive" data-star="2" role="button" aria-label="Rate 2 stars out of 5"></span>
<span class="rating-star rating-star-empty rating-star-interactive" data-star="3" role="button" aria-label="Rate 3 stars out of 5"></span>
<span class="rating-star rating-star-empty rating-star-interactive" data-star="4" role="button" aria-label="Rate 4 stars out of 5"></span>
<span class="rating-star rating-star-empty rating-star-interactive" data-star="5" role="button" aria-label="Rate 5 stars out of 5"></span>
</div>
</div>
<div class="rating_form_feedback">
<label class="rating_form_feedback_label" for="feedback_text">
Additional Comments (Optional)
</label>
<textarea
id="feedback_text"
name="feedback"
placeholder="Tell us more about your experience..."
maxlength="1000">
</textarea>
</div>
<div class="rating_form_submit_container">
<button type="submit"
class="rating_form_submit_btn"
id="submit_rating_btn"
disabled="disabled">
Submit Rating
</button>
</div>
</form>
</div>
<script type="text/javascript">
// Initialize the rating widget when DOM is ready
document.addEventListener('DOMContentLoaded', function() {
const widgetContainer = document.getElementById('rating_stars_widget');
const ratingInput = document.getElementById('rating_value_input');
const submitBtn = document.getElementById('submit_rating_btn');
const stars = widgetContainer.querySelectorAll('.rating-star');
let selectedRating = 0;
let hoverRating = 0;
// Update star display
function updateStars(rating) {
stars.forEach(function(star, index) {
const starValue = index + 1;
if (starValue &lt;= rating) {
star.textContent = '★';
star.classList.remove('rating-star-empty');
star.classList.add('rating-star-filled');
} else {
star.textContent = '☆';
star.classList.remove('rating-star-filled');
star.classList.add('rating-star-empty');
}
});
}
// Handle star click
stars.forEach(function(star) {
star.addEventListener('click', function() {
selectedRating = parseInt(this.getAttribute('data-star'));
ratingInput.value = selectedRating;
submitBtn.disabled = false;
updateStars(selectedRating);
});
// Handle hover
star.addEventListener('mouseenter', function() {
hoverRating = parseInt(this.getAttribute('data-star'));
updateStars(hoverRating);
});
});
// Handle mouse leave from container
widgetContainer.addEventListener('mouseleave', function() {
hoverRating = 0;
updateStars(selectedRating);
});
// Keyboard navigation
widgetContainer.setAttribute('tabindex', '0');
widgetContainer.addEventListener('keydown', function(e) {
let handled = false;
switch(e.key) {
case 'ArrowRight':
case 'ArrowUp':
if (selectedRating &lt; 5) {
selectedRating++;
ratingInput.value = selectedRating;
submitBtn.disabled = false;
updateStars(selectedRating);
}
handled = true;
break;
case 'ArrowLeft':
case 'ArrowDown':
if (selectedRating &gt; 1) {
selectedRating--;
ratingInput.value = selectedRating;
submitBtn.disabled = false;
updateStars(selectedRating);
}
handled = true;
break;
case 'Home':
selectedRating = 1;
ratingInput.value = selectedRating;
submitBtn.disabled = false;
updateStars(selectedRating);
handled = true;
break;
case 'End':
selectedRating = 5;
ratingInput.value = selectedRating;
submitBtn.disabled = false;
updateStars(selectedRating);
handled = true;
break;
}
if (handled) {
e.preventDefault();
e.stopPropagation();
}
});
});
</script>
</t>
</template>
<!-- Rating Confirmation Page -->
<template id="rating_confirmation_page" name="Rating Confirmation Page">
<t t-call="web.layout">
<t t-set="head">
<style>
.rating_confirmation_container {
max-width: 600px;
margin: 80px auto;
padding: 40px;
text-align: center;
background: #f8f9fa;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.rating_stars_display {
font-size: 48px;
color: #ffc107;
margin: 20px 0;
letter-spacing: 4px;
}
.rating_confirmation_title {
font-size: 28px;
font-weight: 600;
color: #28a745;
margin-bottom: 16px;
}
.rating_confirmation_message {
font-size: 16px;
color: #6c757d;
line-height: 1.6;
}
.rating_checkmark {
font-size: 64px;
color: #28a745;
margin-bottom: 20px;
}
.rating_update_notice {
background: #fff3cd;
border: 1px solid #ffc107;
border-radius: 6px;
padding: 12px;
margin-top: 20px;
font-size: 14px;
color: #856404;
}
</style>
</t>
<div class="rating_confirmation_container">
<div class="rating_checkmark"></div>
<h1 class="rating_confirmation_title">
<t t-if="is_update">Rating Updated!</t>
<t t-else="">Thank You for Your Feedback!</t>
</h1>
<div class="rating_stars_display">
<t t-esc="stars_html"/>
</div>
<p class="rating_confirmation_message">
<t t-if="is_update">
Your rating has been updated to <strong><t t-esc="rating_value"/> stars</strong>.
<br/>
Thank you for updating your feedback.
</t>
<t t-else="">
Your rating of <strong><t t-esc="rating_value"/> stars</strong> has been recorded successfully.
<br/>
We appreciate you taking the time to share your experience with us.
</t>
</p>
<t t-if="is_update">
<div class="rating_update_notice">
<strong>Note:</strong> Your previous rating has been replaced with this new rating.
</div>
</t>
</div>
</t>
</template>
<!-- Rating Error Page -->
<template id="rating_error_page" name="Rating Error Page">
<t t-call="web.layout">
<t t-set="head">
<style>
.rating_error_container {
max-width: 600px;
margin: 80px auto;
padding: 40px;
text-align: center;
background: #f8f9fa;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.rating_error_icon {
font-size: 64px;
color: #dc3545;
margin-bottom: 20px;
}
.rating_error_title {
font-size: 28px;
font-weight: 600;
color: #dc3545;
margin-bottom: 16px;
}
.rating_error_message {
font-size: 16px;
color: #6c757d;
line-height: 1.6;
}
</style>
</t>
<div class="rating_error_container">
<div class="rating_error_icon"></div>
<h1 class="rating_error_title"><t t-esc="error_title"/></h1>
<p class="rating_error_message">
<t t-esc="error_message"/>
</p>
</div>
</t>
</template>
</odoo>