@quidgest/chatbot 0.0.8 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .q-chatbot{width:100%;padding:1rem;display:flex;flex-direction:column;height:100%}.q-chatbot input{line-height:1.5rem}.q-chatbot .q-input-group .i-text__field{border-radius:0;flex:1}.q-chatbot__content{background-color:#fff;border:1px solid #eaebec;height:100%;width:100%;display:flex;gap:.75rem;flex-direction:column;overflow:hidden}.q-chatbot__footer-container{padding:.8rem}.q-chatbot__send-container{padding-bottom:.25rem;display:flex;justify-content:flex-end}.q-chatbot__send-container .q-chatbot__send{border-radius:1rem}.q-chatbot__footer{position:sticky;padding:0 .5rem;border:1px solid #eaebec;border-radius:.25rem;bottom:0;width:100%;display:flex;flex-direction:column;gap:.25rem}.q-chatbot__footer .q-chatbot__input{min-height:50px;max-height:100px;border-bottom:1px solid #eaebec;overflow-y:auto}.q-chatbot__footer .q-text-area{max-height:100%;overflow-y:auto}.q-chatbot__footer .q-text-area .q-field__control{border:none}.q-chatbot__messages-container{display:flex;flex-direction:column;flex-grow:1;padding:0 1rem 2rem;gap:1.5rem;overflow-y:auto}.q-chatbot__messages-wrapper{display:flex;max-width:100%;gap:.2rem}.q-chatbot__tools{display:flex;flex-direction:row;justify-content:end;max-width:100%}.q-chatbot__message-wrapper{display:flex;flex-direction:column;gap:.2rem}.q-chatbot__message-container{display:flex;flex-direction:row;align-items:center;gap:.5rem}.q-chatbot__messages-wrapper_right{justify-content:flex-end}.q-chatbot__profile{border-radius:50%;height:2rem;width:2rem}.q-chatbot__message{min-width:4rem;display:flex;align-items:center;padding:.3rem .5rem;background-color:#eaebec;white-space:normal;min-height:2rem}.q-chatbot__messages-wrapper_right .q-chatbot__message{background-color:#018bd233}.q-chatbot__sender{white-space:nowrap;color:#7c858d;font-size:.7rem}@keyframes dotPulse{0%{opacity:.5}50%{opacity:1}to{opacity:.5}}
1
+ .svg-icon[data-v-695796d5]{display:inline-flex;width:16px;height:14px}.svg-icon[data-v-695796d5] svg{width:100%;height:100%}.q-chatbot{width:100%;padding:1rem;display:flex;flex-direction:column;height:100%}.q-chatbot input{line-height:1.5rem}.q-chatbot .q-input-group .i-text__field{border-radius:0;flex:1}.q-chatbot__content{background-color:#fff;border:1px solid #eaebec;height:100%;width:100%;display:flex;gap:.75rem;flex-direction:column;overflow:hidden}.q-chatbot__footer-container{padding:.8rem}.q-chatbot__send-container{padding-bottom:.25rem;display:flex;justify-content:space-between;width:100%}.q-chatbot__send-container .q-chatbot__send,.q-chatbot__send-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__send-container .spacer{flex-grow:1}.q-chatbot__footer{position:sticky;padding:0 .5rem;border:1px solid #eaebec;border-radius:.25rem;bottom:0;width:100%;display:flex;flex-direction:column;gap:.25rem}.q-chatbot__footer-disabled{background-color:rgb(var(--q-theme-neutral-light-rgb)/.25);cursor:not-allowed}.q-chatbot__footer .q-chatbot__input{min-height:50px;max-height:100px;border-bottom:1px solid #eaebec;overflow-y:auto}.q-chatbot__footer .q-text-area{max-height:100%;overflow-y:auto}.q-chatbot__footer .q-text-area .q-field__control{border:none}.q-chatbot__upload-container{display:flex;justify-content:flex-start;padding:.25rem 0}.q-chatbot__upload-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__messages-container{display:flex;flex-direction:column;flex-grow:1;padding:0 1rem 2rem;gap:1.5rem;overflow-y:auto}.q-chatbot__messages-wrapper{display:flex;max-width:100%;gap:.2rem}.q-chatbot__tools{display:flex;flex-direction:row;justify-content:end;max-width:100%}.q-chatbot__message-wrapper{display:flex;flex-direction:column;gap:.2rem}.q-chatbot__message-container{display:flex;flex-direction:column;gap:.25rem}.q-chatbot__messages-wrapper_right{justify-content:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-container{align-items:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-wrapper{display:flex;align-items:flex-end}.q-chatbot__profile.q-icon__img{border-radius:50%;height:2rem;width:2rem}.q-chatbot__message{display:flex;align-items:center;padding:.3rem .5rem;background-color:#eaebec;width:fit-content;white-space:normal;min-height:2rem;word-wrap:break-word;word-break:break-word;border-radius:0 .5rem .5rem}.q-chatbot__messages-wrapper_right .q-chatbot__message{background-color:#018bd233;border-radius:.5rem 0 .5rem .5rem}.q-chatbot__sender{white-space:nowrap;color:#7c858d;font-size:.7rem}.q-chatbot__retry-button{align-items:center;display:flex}.q-chatbot__image-preview{position:relative;display:inline-block}.q-chatbot__image-preview img{max-height:100px;width:auto;border-radius:8px;margin:10px 0}.q-chatbot__remove-image{position:absolute;top:5px;right:5px;background-color:#00000080;color:#fff;border-radius:50%;padding:5px;cursor:pointer;font-size:12px;border:none}.hidden-input{display:none}.pulsing-dots{display:flex;align-items:center;justify-content:center;gap:.1rem}.dot{font-size:20px;line-height:1;animation:pulse 1s infinite;color:var(--q-theme-primary)}@keyframes pulse{0%,to{transform:scale(.8);opacity:.6}50%{transform:scale(1);opacity:1}}
@@ -0,0 +1,14 @@
1
+ import { ResourceStrings } from './texts.type';
2
+
3
+ export type ChatBotProps = {
4
+ apiEndpoint?: string;
5
+ controllerEndpoint?: string;
6
+ texts?: ResourceStrings;
7
+ username: string;
8
+ projectPath: string;
9
+ userImage?: string;
10
+ chatbotImage?: string;
11
+ dateFormat?: string;
12
+ mode?: ChatBotMode;
13
+ };
14
+ export type ChatBotMode = 'chat' | 'agent';
@@ -2,9 +2,15 @@ export type ChatBotMessage = {
2
2
  id: number;
3
3
  message: string;
4
4
  date: Date;
5
- sender: 'bot' | 'user';
5
+ sender: ChatBotMessageSender;
6
+ sessionID: string;
7
+ imagePreviewUrl?: string;
8
+ isWelcomeMessage?: boolean;
6
9
  };
7
10
  export type ChatBotMessageContent = {
8
11
  content: string;
9
12
  type: string;
13
+ sessionID: string;
14
+ imageUrl?: string;
10
15
  };
16
+ export type ChatBotMessageSender = 'bot' | 'user';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quidgest/chatbot",
3
3
  "private": false,
4
- "version": "0.0.8",
4
+ "version": "0.1.0",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
7
7
  "main": "dist/index.cjs",
@@ -32,23 +32,24 @@
32
32
  "lint:fix": "eslint . --fix && prettier --write --list-different src"
33
33
  },
34
34
  "dependencies": {
35
- "axios": "^1.6.7"
35
+ "axios": "^1.6.7",
36
+ "uuid": "^11.0.5"
36
37
  },
37
38
  "devDependencies": {
38
- "@types/node": "^20.11.13",
39
- "@vitejs/plugin-vue": "^4.5.2",
40
- "eslint": "^9.8.0",
39
+ "@types/node": "^20.16.1",
40
+ "@vitejs/plugin-vue": "^4.6.2",
41
+ "eslint": "^9.9.0",
41
42
  "eslint-plugin-prettier": "^5.2.1",
42
43
  "prettier": "^3.3.3",
43
- "rimraf": "^5.0.5",
44
- "sass": "^1.70.0",
45
- "typescript": "^5.2.2",
46
- "vite": "^5.0.8",
47
- "vite-plugin-dts": "^3.7.3",
48
- "vue-tsc": "^1.8.25"
44
+ "rimraf": "^5.0.10",
45
+ "sass": "^1.77.8",
46
+ "typescript": "^5.5.4",
47
+ "vite": "^5.4.2",
48
+ "vite-plugin-dts": "^3.9.1",
49
+ "vue-tsc": "^1.8.27"
49
50
  },
50
51
  "peerDependencies": {
51
- "@quidgest/ui": "^0.14.17",
52
+ "@quidgest/ui": "^0.14.19",
52
53
  "vue": "3.5.13"
53
54
  }
54
55
  }
@@ -0,0 +1,7 @@
1
+ <svg
2
+ xmlns="http://www.w3.org/2000/svg"
3
+ viewBox="0 0 24 24">
4
+ <path
5
+ fill="currentColor"
6
+ d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
7
+ </svg>
@@ -35,13 +35,22 @@
35
35
  &__send-container {
36
36
  padding-bottom: .25rem;
37
37
  display: flex;
38
- justify-content: flex-end;
38
+ justify-content: space-between;
39
+ width: 100%;
39
40
 
40
41
  & .q-chatbot__send {
41
42
  border-radius: 1rem;
42
43
  }
44
+
45
+ & .q-chatbot__upload {
46
+ border-radius: 1rem;
47
+ }
48
+
49
+ & .spacer {
50
+ flex-grow: 1;
51
+ }
43
52
  }
44
-
53
+
45
54
  &__footer {
46
55
  position: sticky;
47
56
  padding: 0 .5rem;
@@ -52,23 +61,39 @@
52
61
  display: flex;
53
62
  flex-direction: column;
54
63
  gap: .25rem;
55
-
64
+
65
+ &-disabled {
66
+ background-color: rgb(var(--q-theme-neutral-light-rgb) / 0.25);
67
+ cursor: not-allowed;
68
+ }
69
+
56
70
  & .q-chatbot__input {
57
- min-height: 50px;
58
- max-height: 100px;
59
- border-bottom: 1px solid #eaebec;
60
- overflow-y: auto;
71
+ min-height: 50px;
72
+ max-height: 100px;
73
+ border-bottom: 1px solid #eaebec;
74
+ overflow-y: auto;
61
75
  }
62
-
76
+
63
77
  & .q-text-area {
64
78
  max-height: 100%;
65
79
  overflow-y: auto;
66
-
80
+
67
81
  & .q-field__control {
68
82
  border: none;
69
83
  }
70
84
  }
71
- }
85
+ }
86
+
87
+ &__upload-container {
88
+ display: flex;
89
+ justify-content: flex-start;
90
+ padding: .25rem 0;
91
+
92
+ & .q-chatbot__upload {
93
+ border-radius: 1rem;
94
+ }
95
+ }
96
+
72
97
  &__messages-container {
73
98
  display: flex;
74
99
  flex-direction: column;
@@ -103,33 +128,45 @@
103
128
 
104
129
  &__message-container {
105
130
  display: flex;
106
- flex-direction: row;
107
- align-items: center;
108
- gap: 0.5rem;
131
+ flex-direction: column;
132
+ gap: 0.25rem;
109
133
  }
110
134
 
111
135
  &__messages-wrapper_right {
112
136
  justify-content: flex-end;
137
+
138
+ .q-chatbot__message-container {
139
+ align-items: flex-end;
140
+ }
141
+
142
+ .q-chatbot__message-wrapper {
143
+ display: flex;
144
+ align-items: flex-end;
145
+ }
113
146
  }
114
147
 
115
- &__profile {
148
+ &__profile.q-icon__img {
116
149
  border-radius: 50%;
117
150
  height: 2rem;
118
151
  width: 2rem;
119
152
  }
120
153
 
121
154
  &__message {
122
- min-width: 4rem;
123
155
  display: flex;
124
156
  align-items: center;
125
157
  padding: 0.3rem 0.5rem;
126
158
  background-color: #eaebec;
159
+ width: fit-content;
127
160
  white-space: normal;
128
161
  min-height: 2rem;
162
+ word-wrap: break-word;
163
+ word-break: break-word;
164
+ border-radius: 0 0.5rem 0.5rem 0.5rem;
129
165
  }
130
166
 
131
167
  &__messages-wrapper_right .q-chatbot__message {
132
168
  background-color: rgba(#018bd2, 20%);
169
+ border-radius: 0.5rem 0 0.5rem 0.5rem;
133
170
  }
134
171
 
135
172
  &__sender {
@@ -137,16 +174,63 @@
137
174
  color: #7c858d;
138
175
  font-size: 0.7rem;
139
176
  }
140
- }
141
177
 
142
- @keyframes dotPulse {
143
- 0% {
144
- opacity: 0.5;
178
+ &__retry-button {
179
+ align-items: center;
180
+ display: flex;
145
181
  }
146
- 50% {
147
- opacity: 1;
182
+
183
+ &__image-preview {
184
+ position: relative;
185
+ display: inline-block;
186
+
187
+ img {
188
+ max-height: 100px;
189
+ width: auto;
190
+ border-radius: 8px;
191
+ margin: 10px 0;
192
+ }
148
193
  }
149
- 100% {
150
- opacity: 0.5;
194
+
195
+ &__remove-image {
196
+ position: absolute;
197
+ top: 5px;
198
+ right: 5px;
199
+ background-color: rgba(0, 0, 0, 0.5);
200
+ color: white;
201
+ border-radius: 50%;
202
+ padding: 5px;
203
+ cursor: pointer;
204
+ font-size: 12px;
205
+ border: none;
151
206
  }
152
207
  }
208
+
209
+ .hidden-input {
210
+ display: none;
211
+ }
212
+
213
+ .pulsing-dots {
214
+ display: flex;
215
+ align-items: center;
216
+ justify-content: center;
217
+ gap: 0.1rem;
218
+ }
219
+
220
+ .dot {
221
+ font-size: 20px;
222
+ line-height: 1;
223
+ animation: pulse 1s infinite;
224
+ color: var(--q-theme-primary);
225
+ }
226
+
227
+ @keyframes pulse {
228
+ 0%, 100% {
229
+ transform: scale(0.8);
230
+ opacity: 0.6;
231
+ }
232
+ 50% {
233
+ transform: scale(1);
234
+ opacity: 1;
235
+ }
236
+ }
@@ -0,0 +1,9 @@
1
+ <svg
2
+ id="Layer_1"
3
+ class="q-icon q-icon__svg"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ viewBox="0 0 21.86 19.87">
6
+ <path
7
+ fill="currentColor"
8
+ d="M17.89,11.92h3.97V0h-3.97M13.91,0H4.97c-.82,0-1.53.5-1.83,1.21L.14,8.22c-.09.23-.14.47-.14.73v1.99c0,1.1.89,1.99,1.99,1.99h6.27l-.94,4.54c-.02.1-.03.2-.03.31,0,.42.17.78.44,1.05l1.05,1.05,6.54-6.55c.37-.36.59-.85.59-1.4V1.99c0-1.1-.89-1.99-1.99-1.99Z" />
9
+ </svg>
@@ -0,0 +1,9 @@
1
+ <svg
2
+ id="Layer_1"
3
+ class="q-icon q-icon__svg"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ viewBox="0 0 21.7 19.73">
6
+ <path
7
+ fill="currentColor"
8
+ d="M21.7,8.88c0-1.09-.89-1.97-1.97-1.97h-6.23l.95-4.51c.02-.1.03-.21.03-.32,0-.4-.17-.78-.43-1.05l-1.05-1.04-6.49,6.49c-.36.36-.58.86-.58,1.4v9.86c0,1.09.88,1.97,1.97,1.97h8.88c.82,0,1.52-.49,1.82-1.2l2.98-6.95c.09-.23.14-.46.14-.72v-1.97M0,19.73h3.95V7.89H0v11.84Z" />
9
+ </svg>
Binary file
@@ -1,13 +1,115 @@
1
+ <template>
2
+ <div class="q-chatbot__message-container">
3
+ <!-- Chatbot Image -->
4
+ <q-icon
5
+ type="img"
6
+ :icon="messageImage"
7
+ :alt="props.texts.senderImage"
8
+ class="q-chatbot__profile" />
9
+
10
+ <div class="q-chatbot__message-wrapper">
11
+ <div
12
+ v-if="props.imagePreviewUrl && props.imagePreviewUrl.length > 0"
13
+ class="q-chatbot__image-preview">
14
+ <img
15
+ :src="props.imagePreviewUrl"
16
+ :alt="props.texts.imagePreview" />
17
+ </div>
18
+ <!-- Message body -->
19
+ <div class="q-chatbot__message">
20
+ <!-- When loading is true, show bouncing dots animation -->
21
+ <pulse-dots v-if="loading" />
22
+ <template v-else>
23
+ <div
24
+ class="q-chatbot__text"
25
+ v-if="props.sender === 'bot'"
26
+ v-html="props.message"></div>
27
+ <div
28
+ class="q-chatbot__text"
29
+ v-else>
30
+ {{ props.message }}
31
+ </div>
32
+ </template>
33
+ </div>
34
+ <q-dialog
35
+ v-model="showDialog"
36
+ :buttons="commentButtons"
37
+ :text="props.texts.commentDialogTitle">
38
+ <template #body.append>
39
+ <q-text-field
40
+ v-model="feedbackComment"
41
+ :maxLength="150"
42
+ size="large"
43
+ :placeholder="props.texts.commentPlaceholder" />
44
+ </template>
45
+ </q-dialog>
46
+
47
+ <!-- Thumbs up and down buttons, only for bot messages -->
48
+ <div
49
+ v-if="isBotMessageAndNotDefault"
50
+ class="q-chatbot__feedback-buttons">
51
+ <q-button-group>
52
+ <q-button
53
+ :title="props.texts.goodResponse"
54
+ borderless
55
+ :disabled="loading"
56
+ b-style="secondary"
57
+ @click="openFeedbackDialog(1)">
58
+ <span v-html="thumbUpSvg" class="svg-icon"></span>
59
+ </q-button>
60
+ <q-button
61
+ :title="props.texts.badResponse"
62
+ borderless
63
+ :disabled="loading"
64
+ b-style="secondary"
65
+ @click="openFeedbackDialog(0)">
66
+ <span v-html="thumbDownSvg" class="svg-icon"></span>
67
+ </q-button>
68
+ <q-button
69
+ :title="props.texts.copyResponse"
70
+ borderless
71
+ :disabled="loading"
72
+ b-style="secondary"
73
+ @click="copyResponse">
74
+ <span v-html="copySvg" class="svg-icon"></span>
75
+ </q-button>
76
+ </q-button-group>
77
+ </div>
78
+ <div class="q-chatbot__sender">
79
+ {{ messageDate }}
80
+ </div>
81
+ </div>
82
+ </div>
83
+ </template>
84
+
1
85
  <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import ChatBotIcon from '@/assets/chatbot.png'
4
- import { QLineLoader } from '@quidgest/ui/components'
86
+ import { computed, ref } from 'vue'
87
+ import {
88
+ QButton,
89
+ QIcon,
90
+ QDialog,
91
+ QTextField
92
+ } from '@quidgest/ui/components'
93
+ import PulseDots from '@/components/PulseDots.vue'
94
+ import type { ChatBotMessageSender } from '@/types/message.type'
95
+ import { ResourceStrings } from '@/types/texts.type'
96
+ import Axios from 'axios'
97
+
98
+ // Importando o conteúdo dos arquivos SVG como strings
99
+ import thumbUpSvgFile from '@/assets/thumbUp.svg?raw'
100
+ import thumbDownSvgFile from '@/assets/thumbDown.svg?raw'
101
+ import copySvgFile from '@/assets/copy.svg?raw'
102
+
103
+ // Armazenando o conteúdo SVG como strings
104
+ const thumbUpSvg = thumbUpSvgFile;
105
+ const thumbDownSvg = thumbDownSvgFile;
106
+ const copySvg = copySvgFile;
5
107
 
6
108
  export interface CBMessageProps {
7
109
  /*
8
110
  * Sender of the message
9
111
  */
10
- sender?: 'bot' | 'user'
112
+ sender?: ChatBotMessageSender
11
113
 
12
114
  /*
13
115
  * Message to be displayed
@@ -28,27 +130,105 @@
28
130
  * Project locale
29
131
  */
30
132
  dateFormat?: string
133
+
134
+ /**
135
+ * Image preview URL
136
+ */
137
+ imagePreviewUrl?: string
138
+
139
+ /**
140
+ * Default chatBot texts
141
+ */
142
+ texts?: ResourceStrings
143
+
144
+ /**
145
+ * Default api endpoint
146
+ */
147
+ apiEndpoint?: String
148
+
149
+ /**
150
+ * Session ID
151
+ */
152
+ sessionID?: String
153
+
154
+ /**
155
+ * User image
156
+ */
157
+ userImage: string
158
+
159
+ /**
160
+ * Chatbot image
161
+ */
162
+ chatbotImage: string
163
+
164
+ /**
165
+ * Flag to mark welcome messages
166
+ */
167
+ isWelcomeMessage?: boolean
31
168
  }
32
169
 
33
170
  const props = withDefaults(defineProps<CBMessageProps>(), {
34
171
  sender: 'user',
35
- date: () => new Date()
172
+ userImage: undefined,
173
+ date: () => new Date(),
174
+ texts: () => ({
175
+ commentDialogTitle: 'Would you like to add a comment?',
176
+ commentPlaceholder: 'Type your comment here (optional)...',
177
+ goodResponse: 'Good response',
178
+ badResponse: 'Bad response',
179
+ copyResponse: 'Copy response',
180
+ submitButton: 'Submit',
181
+ cancelButton: 'Cancel',
182
+ senderImage: 'Sender Image',
183
+ imagePreview: 'Image preview'
184
+ })
36
185
  })
37
186
 
187
+ const showDialog = ref(false)
188
+ const feedbackComment = ref('')
189
+ const currentFeedback = ref<number | null>(null)
190
+ const commentButtons = [
191
+ {
192
+ id: 'confirm-btn',
193
+ action: submitFeedback,
194
+ props: {
195
+ label: props.texts.submitButton,
196
+ 'b-style': 'primary'
197
+ }
198
+ },
199
+ {
200
+ id: 'cancel-btn',
201
+ props: {
202
+ label: props.texts.cancelButton,
203
+ 'b-style': 'danger'
204
+ }
205
+ }
206
+ ]
207
+
38
208
  const senderName = computed(() => {
39
209
  return props.sender === 'bot' ? 'GenioBot' : 'You'
40
210
  })
41
211
 
212
+ const isBotMessageAndNotDefault = computed(() => {
213
+ return props.sender === 'bot' &&
214
+ !Object.values(props.texts || {}).includes(props.message || '') &&
215
+ !props.isWelcomeMessage
216
+ })
217
+
42
218
  const getLocaleDate = computed(() => {
43
219
  if (!props.dateFormat) return props.date.toLocaleString()
44
220
 
45
221
  return formatDate(props.date, props.dateFormat)
46
222
  })
47
223
 
48
- const messageHeader = computed(() => {
224
+ const messageDate = computed(() => {
49
225
  return `${senderName.value} ${getLocaleDate.value}`
50
226
  })
51
227
 
228
+ const messageImage = computed(() =>
229
+ props.sender === 'bot' ? props.chatbotImage : props.userImage
230
+ )
231
+
52
232
  function formatDate(date: Date, format: string) {
53
233
  const day = date.getDate().toString().padStart(2, '0')
54
234
  const month = (date.getMonth() + 1).toString().padStart(2, '0')
@@ -65,40 +245,55 @@
65
245
  .replace('mm', minutes)
66
246
  .replace('ss', seconds)
67
247
  }
68
- </script>
69
248
 
70
- <template>
71
- <div class="q-chatbot__message-container">
72
- <!-- Chatbot Image -->
73
- <img
74
- v-if="props.sender === 'bot'"
75
- :src="ChatBotIcon"
76
- alt="Chatbot"
77
- class="q-chatbot__profile" />
249
+ function openFeedbackDialog(feedback: number) {
250
+ showDialog.value = true
251
+ feedbackComment.value = ''
252
+ currentFeedback.value = feedback
253
+ }
78
254
 
79
- <div class="q-chatbot__message-wrapper">
80
- <!-- Message header -->
81
- <div
82
- v-if="!loading"
83
- class="q-chatbot__sender">
84
- {{ messageHeader }}
85
- </div>
255
+ function submitFeedback() {
256
+ if (currentFeedback.value != null) {
257
+ handleFeedback(currentFeedback.value, feedbackComment.value)
258
+ }
259
+ }
260
+ function handleFeedback(feedback: number, comment: string) {
261
+ Axios.post(props.apiEndpoint + '/prompt/feedback', {
262
+ messageSessionID: props.sessionID,
263
+ feedbackValue: feedback,
264
+ feedbackComment: comment
265
+ }).catch((error) => {
266
+ console.error('Error sending message feedback: ', error)
267
+ })
268
+ }
86
269
 
87
- <!-- Message body -->
88
- <div class="q-chatbot__message">
89
- <QLineLoader v-if="loading" />
90
- <template v-else>
91
- <div
92
- class="q-chatbot__text"
93
- v-if="props.sender == 'bot'"
94
- v-html="props.message"></div>
95
- <div
96
- class="q-chatbot__text"
97
- v-else>
98
- {{ props.message }}
99
- </div>
100
- </template>
101
- </div>
102
- </div>
103
- </div>
104
- </template>
270
+ function copyResponse() {
271
+ if (!props.message) return
272
+
273
+ navigator.clipboard
274
+ .writeText(props.message)
275
+ .then(() => {
276
+ console.log('Message copied to clipboard')
277
+ })
278
+ .catch((error) => {
279
+ console.error(
280
+ 'Failed to copy message to clipboard: ',
281
+ error
282
+ )
283
+ })
284
+ }
285
+ </script>
286
+
287
+ <style scoped>
288
+
289
+ .svg-icon {
290
+ display: inline-flex;
291
+ width: 16px;
292
+ height: 14px;
293
+ }
294
+
295
+ .svg-icon :deep(svg) {
296
+ width: 100%;
297
+ height: 100%;
298
+ }
299
+ </style>