<div class="csi">
<div class="csi__form">
<center><div id="csi-survey">
<div class="csi-survey-header"><p style="color:white;text-align:center">Пожалуйста, оставьте отзыв о работе службы поддержки<p/>
</div>
<template v-if="step === 1">
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">
Какие впечатления от общения с поддержкой?
</div>
<div class="csi-survey-votes">
<div
v-for="vote in votes"
:data-vote="vote"
:class="{'csi-survey__vote': true, 'is-active': vote <= currentVote }"
>
<button
@click="setVote()"
:data-vote="vote"
class="csi-survey__vote-button"
>
{{vote}}
</button>
</div>
</div>
<template v-if="currentVote">
<div class="csi-survey-votes__transcript" :class="voteData.class">
{{voteData.text}}
</div>
</template>
</template>
<template v-if="(currentVote === 5 || currentVote === 4) && step === 2">
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">
Это приятно. <br />А в этом окошке можете предложить что-нибудь
улучшить
</div>
<div>
<label for="comment-positive" class="csi-survey__comment"
>Оставьте Ваш комментарий</label
>
<textarea
name="comment-positive"
id="comment-positive"
v-model="values.comment"
class="comment"
:maxlength="maxComment"
></textarea>
<div class="comment-counter">
{{values.comment ? values.comment.length : 0}}/{{maxComment}}
</div>
</div>
</template>
<template v-if="(currentVote === 5 || currentVote === 4) && step === 3">
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">Спасибо</div>
</template>
<template v-if="currentVote === 3 && step === 2">
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">Что повлияло на вашу оценку?</div>
<div class="csi-survey-options">
<template v-for="option in questions[2].options">
<div
class="csi-survey-options__item"
:class="{'is-active': option.id === values.questions[2] }"
>
<button
class="csi-survey-options__button"
:data-option="option.id"
:data-question="2"
@click="setOption()"
>
<span :data-option="option.id" :data-question="2"
>{{option.label}}</span
>
</button>
</div>
</template>
<template v-if="values.questions[2] === 5">
<div>
<label for="comment-neutral" class="csi-survey__comment"
>Оставьте Ваш комментарий</label
>
<textarea
name="comment-neutral"
id="comment-neutral"
class="comment"
v-model="values.comment"
:maxlength="maxComment"
></textarea>
<div class="comment-counter">
{{values.comment ? values.comment.length : 0}}/{{maxComment}}
</div>
</div>
</template>
</div>
</template>
<template v-if="currentVote === 3 && step === 3">
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">
Мы можем связаться с вами ещё раз. <br />Вы не против?
</div>
<div class="csi-survey-options">
<template v-for="option in questions[3].options">
<div class="csi-survey-options__item">
<button
class="csi-survey-options__button"
:data-option="option.id"
:data-question="3"
@click="setFeedback(option.value,option.value,!option.value)"
>
<span :data-option="option.id" :data-question="3"
>{{option.label}}</span
>
</button>
</div>
</template>
</div>
</template>
<template v-if="currentVote === 3 && step === 4 && feedback">
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">Как удобнее?</div>
<div class="csi-survey-options">
<template v-if="feedback">
<div class="csi-survey-options__item">
<input
id="email"
name="email"
type="email"
v-model="client.email"
placeholder="На почте"
class="csi-survey-options__input"
/>
</div>
<div class="csi-survey-options__item">
<input
id="phone"
name="phone"
v-model="client.phone"
placeholder="По телефону"
class="csi-survey-options__input"
/>
</div>
</template>
</div>
</template>
<template v-if="currentVote === 3 && step === 4 && !feedback">
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">
Cпасибо за оценку. <br />Нам важно ваше мнение.
</div>
</template>
<template v-if="currentVote === 3 && step === 5 && feedback">
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">
Хорошо. <br />Свяжемся в течение суток.
</div>
</template>
<template v-if="(currentVote === 2 || currentVote === 1) && step === 2">
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">
Расскажите, пожалуйста, что пошло не так.
</div>
<div class="csi-survey-options">
<template v-for="option in questions[1].options">
<div
class="csi-survey-options__item"
:class="{'is-active': option.id === values.questions[1] }"
>
<button
class="csi-survey-options__button"
:data-option="option.id"
:data-question="1"
@click="setOption()"
>
<span :data-option="option.id" :data-question="1"
>{{option.label}}</span
>
</button>
</div>
</template>
<template v-if="values.questions[1] === 4">
<div>
<label for="comment-negative" class="csi-survey__comment"
>Оставьте Ваш комментарий</label
>
<textarea
name="comment-negative"
id="comment-negative"
class="comment"
v-model="values.comment"
:maxlength="maxComment"
></textarea>
<div class="comment-counter">
{{values.comment ? values.comment.length : 0}}/{{maxComment}}
</div>
</div>
</template>
</div>
</template>
<template v-if="(currentVote === 2 || currentVote === 1) && step === 3">
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">
Мы позовём другого оператора и постараемся помочь. <br />Как будет
удобнее?
</div>
<div class="csi-survey-options">
<template>
<div class="csi-survey-options__item">
<input
id="email"
name="email"
type="email"
v-model="client.email"
placeholder="На почте"
class="csi-survey-options__input"
/>
</div>
<div class="csi-survey-options__item">
<input
id="phone"
name="phone"
v-model="client.phone"
placeholder="По телефону"
class="csi-survey-options__input"
/>
</div>
</template>
<div class="csi-survey-options__item">
<button
class="csi-survey-options__button"
@click="setFeedback(false, false, true)"
>
Не хочу с вами разговаривать
</button>
</div>
</div>
</template>
<template
v-if="(currentVote === 2 || currentVote === 1) && step === 4 && feedback"
>
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">
Хорошо. <br />Свяжемся в течение суток.
</div>
</template>
<template
v-if="(currentVote === 2 || currentVote === 1) && step === 4 && !feedback"
>
<div class="csi-survey__indicator">Шаг {{step}}</div>
<div class="csi-survey__heading">
Хорошо, что рассказали. <br />Будем исправляться.
</div>
</template>
<div class="csi-survey__action-buttons">
<div>
<button v-if="isBack" @click.prevent="prev()" class="main-button">
⇐ Назад
</button>
</div>
<div>
<button
v-if="isNext && !isFinish"
@click.prevent="next()"
class="main-button"
>
Дальше ⇒
</button>
<button v-if="isFinish" @click.prevent="finish()" class="main-button">
✓ Завершить
</button>
</div>
</div>
<template v-if="debug">
<div class="debug-info">
<div>//debug</div>
<div>Текущий шаг: {{step}}</div>
<div>Выбранная оценка: {{currentVote}}</div>
<div>Ответ (отрицательная оценка): {{values.questions[1]}}</div>
<div>Ответ (нейтральная оценка): {{values.questions[2]}}</div>
<div>Комментарий: {{values.comment}}</div>
<div>Обратная связь: {{feedback ? 'Да' : 'Нет'}}</div>
<div>Телефон: {{client.phone}}</div>
<div>Email: {{client.email}}</div>
</div>
</template>
</div>
</div>
</div>
<style>
html {
padding: 0;
margin: 0;
height: 100%;
}
body {
background: #d6dade;
padding: 0;
margin: 0;
height: 100%;
}
.csi {
height: 100%;
min-width: 350px;
display: flex;
justify-content: center;
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
}
.csi__form {
display: flex;
flex-direction: column;
justify-content: center;
width: 100%;
min-width: 350px;
max-width: 450px;
padding: 10px;
box-sizing: border-box;
}
#csi-survey {
background: #fff;
box-sizing: border-box;
border: 1px solid rgb(0 0 0 / 15%);
padding: 16px;
border-radius: 3px;
margin: 0 auto;
min-width: 330px;
width: 100%;
max-width: 430px;
font-family: Arial, Helvetica, sans-serif;
box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
-webkit-box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
-moz-box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently supported by Chrome, Edge, Opera and Firefox */
}
.csi-survey-header {
height: 60px;
background: #000000;
display: flex;
margin-bottom: 16px;
border-radius: 3px;
}
.csi-survey-header__logo {
line-height: 60px;
padding: 10px 20px;
}
.csi-survey__indicator {
margin-bottom: 16px;
text-align: center;
color: #cdd0d2;
font-size: 14px;
}
.csi-survey__heading {
margin-bottom: 16px;
}
.csi-survey__heading {
font-family: Arial, Helvetica, sans-serif;
font-size: 18px;
font-weight: bold;
text-align: center;
}
.csi-survey-votes {
display: flex;
justify-content: center;
margin-bottom: 16px;
}
.csi-survey__vote {
flex: 1;
text-align: center;
margin: 5px;
}
.csi-survey__vote-button {
width: 50px;
height: 50px;
padding: 0; /* iOS clear */
background: #000;
color: #fff;
border: 5px solid #000;
border-radius: 50%;
cursor: pointer;
font-size: 24px;
font-family: Arial, Helvetica, sans-serif;
font-weight: bold;
transition: all 275ms;
}
.csi-survey__vote-button:hover {
background: #cfcfcf;
color: #333333;
border: 5px solid #cfcfcf;
}
.csi-survey__vote.is-active .csi-survey__vote-button {
background: #cfcfcf;
color: #333333;
border: 5px solid #cfcfcf;
}
.csi-survey__vote.is-active:hover .csi-survey__vote-button {
background: #cfcfcf;
color: #333333;
border: 5px solid #cfcfcf;
}
.csi-survey-votes__transcript {
text-align: center;
margin-bottom: 16px;
}
.csi-survey-votes__transcript.negative {
color: #e47162;
}
.csi-survey-votes__transcript.neutral {
color: #cdd0d2;
}
.csi-survey-votes__transcript.positive {
color: #00ffd1;
}
.csi-survey-options {
margin-bottom: 16px;
}
.csi-survey-options__item {
text-align: center;
margin-bottom: 8px;
}
.csi-survey-options__item.is-active .csi-survey-options__button {
background: #cfcfcf;
color: #000000;
}
.csi-survey-options__button {
border: 0;
background: #000000;
color: #ffffff;
font-size: 14px;
font-weight: bold;
cursor: pointer;
box-sizing: border-box;
padding: 12px 15px;
border-radius: 3px;
transition: all 275ms;
}
.csi-survey-options__button:hover {
background: #cfcfcf;
color: #000000;
}
.csi-survey-options__input {
box-sizing: border-box;
width: 60%;
padding: 8px 16px;
font-size: 1rem;
color: #464a4c;
border: 1px solid rgb(0 0 0 / 15%);
border-radius: 0.25rem;
text-align: center;
font-weight: bold;
transition: all 275ms;
}
.csi-survey-options__input:focus {
outline: none !important;
border: 1px solid #e6e6e6;
background: #fafafa;
}
.csi-survey-options__input:focus::placeholder {
color: transparent;
}
.csi-survey__comment {
color: #8e8e8e;
display: inline-block;
margin-bottom: 0.5rem;
touch-action: manipulation;
font-size: 14px;
}
.csi-survey__action-buttons {
display: flex;
justify-content: space-between;
margin-bottom: 16px;
}
.main-button {
background: #000000;
color: #ffffff;
font-size: 14px;
line-height: 14px;
font-weight: bold;
border: 0;
border-radius: 3px;
padding: 8px 16px;
cursor: pointer;
transition: all 275ms;
}
.main-button:hover {
background: #cfcfcf;
color: #000000;
}
textarea.comment {
min-height: 150px;
padding: 0.5rem 0.75rem;
display: block;
width: 100%;
box-sizing: border-box;
margin-bottom: 16px;
font-size: 1rem;
color: #464a4c;
border: 1px solid rgb(0 0 0 / 15%);
border-radius: 0.25rem;
transition: all 275ms;
}
textarea.comment:focus {
outline: none !important;
border: 1px solid #e6e6e6;
background: #fafafa;
}
textarea.comment::-webkit-scrollbar {
width: 8px;
height: 8px;
}
textarea.comment::-webkit-scrollbar-thumb {
background-color: rgba(170, 170, 170, 0.5);
border-radius: 6px;
}
textarea.comment::-webkit-scrollbar-thumb:hover {
background-color: rgba(170, 170, 170, 1);
border-radius: 6px;
}
textarea.comment {
scrollbar-width: thin;
scrollbar-color: #aaa;
}
.comment-counter {
text-align: right;
margin-bottom: 16px;
margin-top: -10px;
font-size: 12px;
color: #cdd0d2;
}
.debug-info {
font-size: 12px;
word-break: break-all;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active до версии 2.1.8 */ {
opacity: 0;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
let app = new Vue({
el: "#csi-survey",
data: {
step: 1,
currentVote: null,
feedback: true,
client: {
email: null,
phone: null,
},
values: {
questions: {
1: null,
2: null,
3: null,
},
comment: null,
},
maxComment: 300,
maxSteps: {
positive: 3,
neutral: 5,
negative: 4,
},
votes: [1, 2, 3, 4, 5],
questions: {
1: {
id: 1,
text: "Расскажите, пожалуйста, что пошло не так.",
options: [
{
id: 1,
label: "Мне никак не помогли",
},
{
id: 2,
label: "Меня запутали",
},
{
id: 3,
label: "Мне нагрубили",
},
{
id: 4,
label: "Другое",
},
],
},
2: {
id: 2,
text: "Что повлияло на вашу оценку?",
options: [
{
id: 1,
label: "Долго отвечали",
},
{
id: 2,
label: "Непонятно объяснили",
},
{
id: 3,
label: "Не разобрались в проблеме",
},
{
id: 4,
label: "Не помогли",
},
{
id: 5,
label: "Другое",
},
],
},
3: {
id: 3,
text: "",
options: [
{
id: 1,
label: "Давайте попробуем",
value: true,
},
{
id: 2,
label: "Не надо, но спасибо",
value: false,
},
],
},
},
debug: false,
},
computed: {
isBack() {
if (this.step === 1) {
return false;
} else {
return true;
}
},
isNext() {
if (
!this.currentVote ||
((this.currentVote === 4 || this.currentVote === 5) &&
(this.step === 2 || this.step === 3)) ||
(this.currentVote === 3 &&
this.step === 4 &&
this.feedback === false) ||
(this.currentVote === 3 &&
this.step === 5 &&
this.feedback === true) ||
(this.currentVote === 3 && this.step === 3) ||
(this.currentVote === 3 &&
this.step === 4 &&
this.feedback === true) ||
(this.currentVote === 3 &&
this.step === 2 &&
this.values.questions[2] === null) ||
((this.currentVote === 1 || this.currentVote === 2) &&
this.step === 2 &&
this.values.questions[1] === null) ||
((this.currentVote === 1 || this.currentVote === 2) &&
this.step === 3) ||
((this.currentVote === 1 || this.currentVote === 2) &&
this.step === 4)
) {
return false;
} else {
return true;
}
},
isFinish() {
if (
((this.currentVote === 4 || this.currentVote === 5) &&
this.step === 2) ||
(this.currentVote === 3 &&
this.step === 4 &&
this.feedback === true) ||
((this.currentVote === 1 || this.currentVote === 2) &&
this.step === 3)
) {
return true;
} else {
return false;
}
},
voteData() {
let voteData = {
text: null,
class: null,
};
switch (this.currentVote) {
case 1:
case 2:
voteData.text = "Плохо";
voteData.class = "negative";
break;
case 3:
voteData.text = "Нормально";
voteData.class = "neutral";
break;
case 4:
voteData.text = "Хорошо";
voteData.class = "positive";
break;
case 5:
voteData.text = "Отлично";
voteData.class = "positive";
break;
}
return voteData;
},
result() {
let result;
let questionId;
switch (this.currentVote) {
case 1:
case 2:
questionId = 1;
result = {
vote: "VOTESTART" + this.currentVote + "VOTEEND",
question_id: questionId,
question_text: this.questions[questionId].text,
answer_id: this.values.questions[questionId],
answer_text:
"ANSWERSTART" +
this.questions[questionId].options.filter(
(item) => item.id === this.values.questions[questionId]
)[0].label +
"ANSWEREND",
comment:
"COMSTART" +
(this.values.questions[questionId] === 4 &&
this.values.comment !== null
? this.values.comment
: "") +
"COMEND",
feedback:
"FEEDSTART" + (this.feedback ? "Да" : "Нет") + "FEEDEND",
client_phone:
"PHONESTART" +
(this.client.phone ? this.client.phone : "") +
"PHONEEND",
client_email:
"EMAILSTART" +
(this.client.email ? this.client.email : "") +
"EMAILEND",
};
break;
case 3:
questionId = 2;
result = {
vote: "VOTESTART" + this.currentVote + "VOTEEND",
question_id: questionId,
question_text: this.questions[questionId].text,
answer_id: this.values.questions[questionId],
answer_text:
"ANSWERSTART" +
this.questions[questionId].options.filter(
(item) => item.id === this.values.questions[questionId]
)[0].label +
"ANSWEREND",
comment:
"COMSTART" +
(this.values.questions[questionId] === 5 &&
this.values.comment !== null
? this.values.comment
: "") +
"COMEND",
feedback:
"FEEDSTART" +
(this.feedback === true ? "Да" : "Нет") +
"FEEDEND",
client_phone:
"PHONESTART" +
(this.client.phone ? this.client.phone : "") +
"PHONEEND",
client_email:
"EMAILSTART" +
(this.client.email ? this.client.email : "") +
"EMAILEND",
};
break;
case 4:
case 5:
result = {
vote: "VOTESTART" + this.currentVote + "VOTEEND",
question_id: null,
question_text: null,
answer_id: null,
answer_text: "ANSWERSTART" + "Без ответа" + " ANSWEREND",
comment:
"COMSTART" +
(this.values.comment !== null ? this.values.comment : "") +
"COMEND",
feedback: "FEEDSTART" + "Нет" + "FEEDEND",
client_phone: "PHONESTARTPHONEEND",
client_email: "EMAILSTARTEMAILEND",
};
break;
}
return result;
},
},
mounted() {
//console.log("Mounted");
},
methods: {
setVote: function () {
let element = event.target;
let vote = element.getAttribute("data-vote");
this.currentVote = +vote;
},
setOption: function () {
let element = event.target;
let question = +element.getAttribute("data-question");
let option = +element.getAttribute("data-option");
this.values.questions[question] = option;
},
setFeedback: function (feedback, next, finish) {
if (feedback === true) {
this.feedback = feedback;
} else if (feedback === false) {
this.feedback = feedback;
}
if (next) {
this.step = this.step + 1;
}
if (finish) {
this.finish();
}
},
next: function () {
this.step = this.step + 1;
},
prev: function () {
if (
(this.currentVote === 1 || this.currentVote === 2) &&
this.step === 4
) {
this.step = this.step - 1;
this.feedback = true;
} else {
this.step = this.step - 1;
}
},
finish: function () {
this.step = this.step + 1;
//console.log(this.result);
//console.log("Finish");
HDE.save(this.currentVote, JSON.stringify(this.result));
//console.log(JSON.stringify(this.result));
},
},
});
</script>