@buerokratt-ria/common-gui-components 0.0.1

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.
Files changed (122) hide show
  1. package/.eslintrc.json +18 -0
  2. package/CHANGELOG.md +7 -0
  3. package/MAKING_CHANGES.md +8 -0
  4. package/README.md +49 -0
  5. package/assets/ding.mp3 +0 -0
  6. package/assets/logo-white.svg +29 -0
  7. package/assets/logo.svg +31 -0
  8. package/assets/newMessageSound.mp3 +0 -0
  9. package/constants/config.ts +12 -0
  10. package/constants/index.ts +1 -0
  11. package/context/index.ts +1 -0
  12. package/context/toastContext.tsx +60 -0
  13. package/hooks/index.ts +3 -0
  14. package/hooks/useAudio.tsx +30 -0
  15. package/hooks/useDocumentEscapeListener.tsx +17 -0
  16. package/hooks/useToast.tsx +5 -0
  17. package/i18n.ts +26 -0
  18. package/index.ts +6 -0
  19. package/package.json +122 -0
  20. package/project.json +52 -0
  21. package/services/api.ts +74 -0
  22. package/services/index.ts +3 -0
  23. package/services/sse-service.ts +30 -0
  24. package/services/users.ts +58 -0
  25. package/store/index.ts +253 -0
  26. package/templates/history-page/index.ts +1 -0
  27. package/templates/history-page/src/History.scss +47 -0
  28. package/templates/history-page/src/index.tsx +998 -0
  29. package/templates/history-page/src/unfiyDate.tsx +7 -0
  30. package/translations/en/common.json +467 -0
  31. package/translations/et/common.json +467 -0
  32. package/tsconfig.base.json +21 -0
  33. package/tsconfig.json +17 -0
  34. package/tsconfig.spec.json +19 -0
  35. package/types/authorities.ts +8 -0
  36. package/types/botConfig.ts +7 -0
  37. package/types/chat.ts +126 -0
  38. package/types/customerSupportActivity.ts +5 -0
  39. package/types/deleteChatSettings.ts +9 -0
  40. package/types/emergencyNotice.ts +10 -0
  41. package/types/establishment.ts +4 -0
  42. package/types/index.ts +18 -0
  43. package/types/mainNavigation.ts +11 -0
  44. package/types/message.ts +74 -0
  45. package/types/organizationWorkingTime.ts +27 -0
  46. package/types/router.ts +4 -0
  47. package/types/service.ts +6 -0
  48. package/types/session.ts +7 -0
  49. package/types/skmConfig.ts +8 -0
  50. package/types/user.ts +40 -0
  51. package/types/userInfo.ts +16 -0
  52. package/types/userProfileSettings.ts +10 -0
  53. package/types/widgetConfig.ts +8 -0
  54. package/ui-components/Button/Button.scss +150 -0
  55. package/ui-components/Button/index.tsx +41 -0
  56. package/ui-components/ButtonMessage/ButtonMessage.scss +16 -0
  57. package/ui-components/ButtonMessage/index.tsx +19 -0
  58. package/ui-components/Card/Card.scss +69 -0
  59. package/ui-components/Card/index.tsx +39 -0
  60. package/ui-components/Chat/Chat.scss +447 -0
  61. package/ui-components/Chat/ChatMessage.tsx +270 -0
  62. package/ui-components/Chat/ChatTextArea.scss +110 -0
  63. package/ui-components/Chat/ChatTextArea.tsx +97 -0
  64. package/ui-components/Chat/LoaderOverlay.tsx +39 -0
  65. package/ui-components/Chat/Markdownify.tsx +49 -0
  66. package/ui-components/Chat/PreviewMessage.tsx +39 -0
  67. package/ui-components/Chat/Typing.scss +46 -0
  68. package/ui-components/Chat/index.tsx +1111 -0
  69. package/ui-components/ChatEvent/Chat.scss +40 -0
  70. package/ui-components/ChatEvent/index.tsx +216 -0
  71. package/ui-components/DataTable/CloseIcon.tsx +22 -0
  72. package/ui-components/DataTable/DataTable.scss +188 -0
  73. package/ui-components/DataTable/DeboucedInput.scss +11 -0
  74. package/ui-components/DataTable/DebouncedInput.tsx +54 -0
  75. package/ui-components/DataTable/Filter.tsx +121 -0
  76. package/ui-components/DataTable/index.tsx +432 -0
  77. package/ui-components/Dialog/Dialog.scss +63 -0
  78. package/ui-components/Dialog/index.tsx +44 -0
  79. package/ui-components/Drawer/Drawer.scss +40 -0
  80. package/ui-components/Drawer/index.tsx +42 -0
  81. package/ui-components/FormElements/FormCheckbox/FormCheckbox.scss +57 -0
  82. package/ui-components/FormElements/FormCheckbox/index.tsx +39 -0
  83. package/ui-components/FormElements/FormCheckboxes/FormCheckboxes.scss +63 -0
  84. package/ui-components/FormElements/FormCheckboxes/index.tsx +44 -0
  85. package/ui-components/FormElements/FormDatepicker/FormDatepicker.scss +154 -0
  86. package/ui-components/FormElements/FormDatepicker/index.tsx +123 -0
  87. package/ui-components/FormElements/FormInput/FormInput.scss +90 -0
  88. package/ui-components/FormElements/FormInput/index.tsx +47 -0
  89. package/ui-components/FormElements/FormRadios/FormRadios.scss +72 -0
  90. package/ui-components/FormElements/FormRadios/index.tsx +36 -0
  91. package/ui-components/FormElements/FormSelect/FormMultiselect.tsx +124 -0
  92. package/ui-components/FormElements/FormSelect/FormSelect.scss +121 -0
  93. package/ui-components/FormElements/FormSelect/index.tsx +100 -0
  94. package/ui-components/FormElements/FormTextarea/FormTextarea.scss +109 -0
  95. package/ui-components/FormElements/FormTextarea/index.tsx +154 -0
  96. package/ui-components/FormElements/Switch/Switch.scss +69 -0
  97. package/ui-components/FormElements/Switch/index.tsx +65 -0
  98. package/ui-components/FormElements/SwitchBox/SwitchBox.scss +45 -0
  99. package/ui-components/FormElements/SwitchBox/index.tsx +44 -0
  100. package/ui-components/FormElements/index.tsx +23 -0
  101. package/ui-components/HistoricalChat/ChatMessage.tsx +67 -0
  102. package/ui-components/HistoricalChat/HistoricalChat.scss +225 -0
  103. package/ui-components/HistoricalChat/index.tsx +282 -0
  104. package/ui-components/Icon/Icon.scss +17 -0
  105. package/ui-components/Icon/index.tsx +26 -0
  106. package/ui-components/Label/Label.scss +76 -0
  107. package/ui-components/Label/index.tsx +40 -0
  108. package/ui-components/OptionMessage/OptionMessage.scss +16 -0
  109. package/ui-components/OptionMessage/index.tsx +16 -0
  110. package/ui-components/Toast/Toast.scss +73 -0
  111. package/ui-components/Toast/index.tsx +54 -0
  112. package/ui-components/Tooltip/Tooltip.scss +17 -0
  113. package/ui-components/Tooltip/index.tsx +28 -0
  114. package/ui-components/Track/index.tsx +57 -0
  115. package/ui-components/index.tsx +53 -0
  116. package/utils/constants.ts +19 -0
  117. package/utils/format-bytes.ts +8 -0
  118. package/utils/generateUEID.ts +8 -0
  119. package/utils/local-storage-utils.ts +17 -0
  120. package/utils/parse-utils.ts +23 -0
  121. package/utils/state-management-utils.ts +13 -0
  122. package/vite.config.ts +67 -0
@@ -0,0 +1,447 @@
1
+ @import 'src/styles/tools/spacing';
2
+ @import 'src/styles/tools/color';
3
+ @import 'src/styles/settings/variables/other';
4
+ @import 'src/styles/settings/variables/typography';
5
+
6
+ .active-chat {
7
+ $self: &;
8
+ display: flex;
9
+ justify-content: flex-end;
10
+ position: relative;
11
+ height: 100%;
12
+
13
+ &__body {
14
+ flex: 1;
15
+ display: flex;
16
+ flex-direction: column;
17
+ height: 100%;
18
+ position: absolute;
19
+ top: 0;
20
+ bottom: 0;
21
+ left: 0;
22
+ right: 288px;
23
+ }
24
+
25
+ &__header {
26
+ padding: get-spacing(haapsalu);
27
+ background-color: get-color(extra-light);
28
+ border-bottom: 1px solid get-color(black-coral-2);
29
+ }
30
+
31
+ &__group-wrapper {
32
+ flex: 1;
33
+ padding: get-spacing(haapsalu) get-spacing(haapsalu) 0;
34
+ overflow: auto;
35
+ overflow-anchor: none;
36
+
37
+ #anchor {
38
+ overflow-anchor: auto;
39
+ height: 1px;
40
+ margin-top: 16px;
41
+ }
42
+ }
43
+
44
+ &__toolbar {
45
+ background-color: get-color(extra-light);
46
+ border-top: 1px solid get-color(black-coral-2);
47
+ padding: get-spacing(paldiski);
48
+ position: relative;
49
+ }
50
+
51
+ &__toolbar-actions {
52
+ display: flex;
53
+ gap: 8px;
54
+ position: relative;
55
+ right: 12px;
56
+ left: 5px;
57
+ top: 0px;
58
+ bottom: 8px;
59
+ flex-flow: wrap;
60
+
61
+ .btn {
62
+ padding-left: 20px;
63
+ padding-right: 20px;
64
+ padding-top: 9.5px;
65
+ padding-bottom: 9.5px;
66
+ border-radius: 15px;
67
+ }
68
+ }
69
+
70
+ &__side {
71
+ flex: 0 0 288px;
72
+ height: 100%;
73
+ overflow: auto;
74
+ border-left: 1px solid get-color(black-coral-2);
75
+ display: flex;
76
+ flex-direction: column;
77
+ justify-content: start;
78
+
79
+ .btn {
80
+ justify-content: center;
81
+ }
82
+ }
83
+
84
+ &__side-actions,
85
+ &__side-meta {
86
+ display: flex;
87
+ flex-direction: column;
88
+ gap: 4px;
89
+ padding: get-spacing(haapsalu);
90
+
91
+ .csa-away {
92
+ font-size: $veera-font-size-80;
93
+ line-height: $veera-line-height-500;
94
+ color: get-color(black-coral-12);
95
+ }
96
+ }
97
+
98
+ &__side-meta {
99
+ font-size: $veera-font-size-80;
100
+ line-height: $veera-line-height-500;
101
+ color: get-color(black-coral-12);
102
+ }
103
+
104
+ &__group {
105
+ display: flex;
106
+ flex-direction: column;
107
+ gap: 4px;
108
+ padding-left: 56px;
109
+ position: relative;
110
+
111
+ &:not(:last-child) {
112
+ margin-bottom: 8px;
113
+ }
114
+
115
+ &--event {
116
+ padding-left: 0;
117
+ #{$self} {
118
+ &__event-message {
119
+ display: flex;
120
+ position: relative;
121
+ isolation: isolate;
122
+ padding: 6px 0;
123
+
124
+ p {
125
+ color: get-color(black-coral-12);
126
+ font-size: $veera-font-size-80;
127
+ line-height: $veera-line-height-500;
128
+ padding: 4px 8px 4px 0;
129
+ background-color: get-color(white);
130
+ }
131
+
132
+ &::after {
133
+ content: '';
134
+ display: block;
135
+ height: 1px;
136
+ background-color: get-color(black-coral-2);
137
+ position: absolute;
138
+ top: 50%;
139
+ left: 56px;
140
+ right: 0;
141
+ transform: translateY(-50%);
142
+ z-index: -1;
143
+ }
144
+ }
145
+ }
146
+ }
147
+
148
+ &--buerokratt,
149
+ &--chatbot {
150
+ #{$self} {
151
+ &__group-initials {
152
+ background-color: get-color(sapphire-blue-10);
153
+ left: 0;
154
+ }
155
+
156
+ &__group-name {
157
+ color: get-color(sapphire-blue-10);
158
+ text-align: left;
159
+ margin-left: 0;
160
+ font-size: $veera-font-size-100;
161
+ }
162
+
163
+ &__messages {
164
+ display: flex;
165
+ flex-direction: column;
166
+ gap: 4px;
167
+ align-items: flex-start;
168
+ }
169
+
170
+ &__message-text {
171
+ background-color: get-color(sapphire-blue-10);
172
+ color: get-color(white);
173
+
174
+ :any-link {
175
+ background: url('../../static/icons/link-external-blue.svg')
176
+ no-repeat right center;
177
+ padding-right: 1.25em;
178
+ color: blue;
179
+ text-decoration: underline;
180
+ }
181
+
182
+ &:hover {
183
+ background-color: get-color(sapphire-blue-13);
184
+ }
185
+ }
186
+ }
187
+ }
188
+
189
+ &--backoffice-user {
190
+ #{$self} {
191
+ &__group-initials {
192
+ background-color: get-color(black-coral-10);
193
+ color: get-color(white);
194
+ left: 0;
195
+ }
196
+
197
+ &__group-name {
198
+ text-align: left;
199
+ margin-left: 0;
200
+ font-size: $veera-font-size-100;
201
+ }
202
+
203
+ &__messages {
204
+ display: flex;
205
+ flex-direction: column;
206
+ gap: 4px;
207
+ align-items: flex-start;
208
+ }
209
+
210
+ &__message-text {
211
+ background-color: get-color(black-coral-10);
212
+ color: get-color(white);
213
+
214
+ :any-link {
215
+ background: url('../../static/icons/link-external-white.svg')
216
+ no-repeat right center;
217
+ padding-right: 1.25em;
218
+ color: white;
219
+ text-decoration: underline;
220
+ }
221
+
222
+ &:hover {
223
+ background-color: #535665;
224
+ }
225
+ }
226
+
227
+ &__selection-icon {
228
+ background-color: get-color(black-coral-20);
229
+ }
230
+ }
231
+ }
232
+ }
233
+
234
+ &__group-initials {
235
+ display: flex;
236
+ align-items: center;
237
+ justify-content: center;
238
+ width: 40px;
239
+ height: 40px;
240
+ background-color: get-color(black-coral-1);
241
+ border-radius: 50%;
242
+ font-size: $veera-font-size-80;
243
+ line-height: $veera-line-height-500;
244
+ font-weight: $veera-font-weight-delta;
245
+ color: get-color(black-coral-6);
246
+ position: absolute;
247
+ right: 0;
248
+ top: 0;
249
+ }
250
+
251
+ &__group-name {
252
+ font-size: $veera-font-size-100;
253
+ line-height: $veera-line-height-500;
254
+ font-weight: $veera-font-weight-delta;
255
+ text-transform: capitalize;
256
+ margin-left: 10rem;
257
+ margin-right: 3rem;
258
+ text-align: right;
259
+ padding-top: 10px;
260
+ }
261
+
262
+ &__messages {
263
+ display: flex;
264
+ flex-direction: column;
265
+ gap: 4px;
266
+ align-items: flex-end;
267
+ }
268
+
269
+ &__messageContainer {
270
+ display: flex;
271
+ flex-direction: column;
272
+ gap: 4px;
273
+ align-items: flex-start;
274
+ }
275
+
276
+ &__message {
277
+ display: flex;
278
+ align-items: center;
279
+ gap: 8px;
280
+ position: relative;
281
+
282
+ &--selected {
283
+ #{$self}__message-text {
284
+ box-shadow: inset 0 0 0 1px get-color(black-coral-20);
285
+ }
286
+ }
287
+ }
288
+
289
+ &__selection-icon {
290
+ display: flex;
291
+ align-items: center;
292
+ justify-content: center;
293
+ width: 12px;
294
+ height: 12px;
295
+ background-color: get-color(black-coral-10);
296
+ border-radius: 50%;
297
+ color: get-color(white);
298
+ font-size: 8px;
299
+ line-height: 1;
300
+ position: absolute;
301
+ top: 50%;
302
+ left: -6px;
303
+ transform: translateY(-50%);
304
+ }
305
+
306
+ &__edit-icon {
307
+ height: 25px;
308
+ margin-left: 5px;
309
+ width: 20px;
310
+ }
311
+
312
+ &__message-text {
313
+ display: flex;
314
+ align-items: center;
315
+ padding: 4px 8px;
316
+ background-color: get-color(black-coral-0);
317
+ border-radius: 8px 8px 8px 4px;
318
+ font-size: $veera-font-size-100;
319
+ line-height: $veera-line-height-500;
320
+ transition: all 0.25s ease-out;
321
+ cursor: pointer;
322
+ word-break: break-word;
323
+ white-space: pre-wrap;
324
+
325
+ &:hover {
326
+ background-color: get-color(black-coral-1);
327
+ }
328
+
329
+ :any-link {
330
+ background: url('../../static/icons/link-external-blue.svg') no-repeat
331
+ right center;
332
+ padding-right: 1.25em;
333
+ color: blue;
334
+ text-decoration: underline;
335
+ }
336
+ }
337
+
338
+ &__message-preview {
339
+ display: flex;
340
+ align-items: center;
341
+ padding: 4px 8px;
342
+ border-radius: 8px 8px 8px 4px;
343
+ font-size: $veera-font-size-100;
344
+ line-height: $veera-line-height-500;
345
+ transition: all 0.25s ease-out;
346
+ cursor: pointer;
347
+
348
+ color: #4472c4;
349
+ background-color: #e7f3ff;
350
+ }
351
+
352
+ &__message-date {
353
+ color: get-color(black-coral-6);
354
+ font-size: 11px;
355
+ line-height: 20px;
356
+ -webkit-user-select: none;
357
+ -ms-user-select: none;
358
+ user-select: none;
359
+ }
360
+
361
+ &__message-status {
362
+ color: get-color(black-coral-6);
363
+ font-size: 11px;
364
+ line-height: 15px;
365
+ -webkit-user-select: none;
366
+ -ms-user-select: none;
367
+ user-select: none;
368
+
369
+ &::before {
370
+ // css base64 ::before checkmark
371
+ content: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iMTAiIHZpZXdCb3g9IjAgMCAxMiAxMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMuODYzMzkgNy41ODMzNkwxLjA4MzM5IDQuODAzMzZMMC4xMzY3MTkgNS43NDMzNkwzLjg2MzM5IDkuNDcwMDNMMTEuODYzNCAxLjQ3MDAzTDEwLjkyMzQgMC41MzAwMjlMMy44NjMzOSA3LjU4MzM2WiIgZmlsbD0iIzk3OTlBNCIvPgo8L3N2Zz4K');
372
+ display: inline-block;
373
+ width: 16px;
374
+ height: 16px;
375
+ }
376
+ }
377
+ }
378
+
379
+ .edit-toolbar {
380
+ display: grid;
381
+ grid-template-columns: 2fr 1fr;
382
+ grid-template-rows: auto auto;
383
+ gap: 10px;
384
+
385
+ &__header {
386
+ align-items: center;
387
+ display: flex;
388
+ grid-column: 1;
389
+ grid-row: 1;
390
+ }
391
+
392
+ &__textarea {
393
+ grid-column: 1;
394
+ grid-row: 2;
395
+ }
396
+
397
+ &__edit-actions {
398
+ display: flex;
399
+ grid-column: 2;
400
+ grid-row: 2;
401
+ gap: 10px;
402
+ justify-content: flex-end;
403
+ }
404
+ }
405
+
406
+ .title {
407
+ font-size: 13px;
408
+ color: get-color(black-coral-6);
409
+ padding-top: 2px;
410
+ }
411
+
412
+ .reset {
413
+ margin: 0;
414
+ padding: 0;
415
+ line-height: 1.3;
416
+ }
417
+
418
+ .reset h1,
419
+ .reset h2,
420
+ .reset h3,
421
+ .reset h4,
422
+ .reset h5,
423
+ .reset h6 {
424
+ margin: 0;
425
+ padding: 0;
426
+ }
427
+
428
+ .reset p {
429
+ margin: 0 0 0.5rem;
430
+ padding: 0;
431
+ }
432
+
433
+ .reset ul,
434
+ .reset ol {
435
+ margin: 0 0 1rem;
436
+ padding-left: 1.5rem;
437
+ }
438
+
439
+ .reset li {
440
+ margin: 0;
441
+ padding: 0;
442
+ }
443
+
444
+ .reset a {
445
+ text-decoration: none;
446
+ color: inherit;
447
+ }
@@ -0,0 +1,270 @@
1
+ import React, { FC, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { format } from 'date-fns';
3
+ import clsx from 'clsx';
4
+ import {
5
+ MdCheck,
6
+ MdClose,
7
+ MdOutlineCreate,
8
+ MdOutlineCheck,
9
+ } from 'react-icons/md';
10
+ import { Message } from '../../types/message';
11
+ import { CHAT_EVENTS, MessageStatus } from '../../types/chat';
12
+ import Markdownify from './Markdownify';
13
+ import { useTranslation } from 'react-i18next';
14
+ import './Typing.scss';
15
+ import { parseButtons, parseOptions } from '../../utils/parse-utils';
16
+ import ButtonMessage from '../ButtonMessage';
17
+ import OptionMessage from '../OptionMessage';
18
+ import Track from '../Track';
19
+ import Icon from '../Icon';
20
+ import { HiOutlinePencil } from 'react-icons/hi';
21
+ import Button from '../Button';
22
+ import FormTextarea from '../FormElements/FormTextarea';
23
+ import { apiDev } from '../../services';
24
+ import { useToast } from '../../hooks';
25
+ import { useMutation } from '@tanstack/react-query';
26
+ import { AxiosError } from 'axios';
27
+
28
+ type ChatMessageProps = {
29
+ message: Message;
30
+ onSelect: (message: Message) => void;
31
+ selected: boolean;
32
+ editableMessage?: boolean;
33
+ };
34
+
35
+ const ChatMessage: FC<ChatMessageProps> = ({
36
+ message,
37
+ onSelect,
38
+ selected,
39
+ editableMessage,
40
+ }) => {
41
+ const { t } = useTranslation();
42
+
43
+ const buttons = useMemo(() => parseButtons(message), [message.buttons]);
44
+ const options = useMemo(() => parseOptions(message), [message.options]);
45
+ const [isEditing, setIsEditing] = useState(false);
46
+ const [content, setContent] = useState(message.content ?? '');
47
+ const [inputContent, setInputContent] = useState(content);
48
+ const [messageHeight, setMessageHeight] = useState(0);
49
+ const messageRef = useRef<HTMLButtonElement>(null);
50
+ const toast = useToast();
51
+
52
+ useEffect(() => {
53
+ setMessageHeight(messageRef?.current?.clientHeight ?? 0);
54
+ });
55
+
56
+ const approveMessage = useMutation({
57
+ mutationFn: (data: { chatId: string; messageId: string }) => {
58
+ return apiDev.post(`chats/messages/approve-validation`, {
59
+ chatId: data.chatId,
60
+ messageId: data.messageId,
61
+ });
62
+ },
63
+ onSuccess: async () => {
64
+ toast.open({
65
+ type: 'success',
66
+ title: t('global.notification'),
67
+ message: t('chat.validations.messageApproved'),
68
+ });
69
+ return true;
70
+ },
71
+ onError: (error: AxiosError) => {
72
+ toast.open({
73
+ type: 'error',
74
+ title: t('global.notificationError'),
75
+ message: error.message,
76
+ });
77
+ return false;
78
+ },
79
+ });
80
+
81
+ return (
82
+ <div className={clsx('active-chat__messageContainer')}>
83
+ <div
84
+ className={clsx('active-chat__message', {
85
+ 'active-chat__message--selected': selected,
86
+ })}
87
+ >
88
+ {(message.event === CHAT_EVENTS.GREETING ||
89
+ message.event === CHAT_EVENTS.WAITING_VALIDATION ||
90
+ message.event === CHAT_EVENTS.APPROVED_VALIDATION ||
91
+ !message.event) && (
92
+ <>
93
+ <button
94
+ className={clsx('active-chat__message-text')}
95
+ ref={messageRef}
96
+ onClick={() => onSelect(message)}
97
+ >
98
+ <Track direction={isEditing ? 'vertical' : 'horizontal'}>
99
+ {message.event === CHAT_EVENTS.WAITING_VALIDATION &&
100
+ isEditing && (
101
+ <FormTextarea
102
+ name={''}
103
+ label={''}
104
+ minRows={1}
105
+ maxRows={-1}
106
+ maxLength={-1}
107
+ style={{
108
+ backgroundColor: 'transparent',
109
+ border: 'none',
110
+ width: '400px',
111
+ }}
112
+ defaultValue={content}
113
+ onChange={(e) => {
114
+ setInputContent(e.target.value);
115
+ }}
116
+ onClick={(e) => {
117
+ e.stopPropagation();
118
+ }}
119
+ autoFocus
120
+ />
121
+ )}
122
+ {!isEditing && <Markdownify message={content} />}
123
+ {!message.content && options.length > 0 && 'ok'}
124
+ {editableMessage && !isEditing && (
125
+ <MdOutlineCreate className="active-chat__edit-icon" />
126
+ )}
127
+ {message.event === CHAT_EVENTS.WAITING_VALIDATION && (
128
+ <button
129
+ style={{
130
+ color: 'white',
131
+ alignSelf: 'end',
132
+ paddingTop: '0.3rem',
133
+ }}
134
+ onClick={(event) => {
135
+ event.stopPropagation();
136
+ setMessageHeight(messageRef?.current?.clientHeight ?? 0);
137
+ setIsEditing(true);
138
+ }}
139
+ >
140
+ <Icon
141
+ icon={<HiOutlinePencil fontSize={18} />}
142
+ size="medium"
143
+ />
144
+ </button>
145
+ )}
146
+ </Track>
147
+ </button>
148
+ <Track
149
+ direction="horizontal"
150
+ style={{
151
+ height: messageHeight,
152
+ justifyContent: 'center',
153
+ }}
154
+ >
155
+ <div>
156
+ <time
157
+ dateTime={message.created}
158
+ className="active-chat__message-date"
159
+ style={{ alignSelf: 'center' }}
160
+ >
161
+ {format(new Date(message.created), 'HH:mm:ss')}
162
+ </time>
163
+ </div>
164
+ {message.event === CHAT_EVENTS.WAITING_VALIDATION &&
165
+ isEditing && (
166
+ <Track
167
+ style={{
168
+ position: 'absolute',
169
+ bottom: 0,
170
+ }}
171
+ gap={2}
172
+ >
173
+ <Icon
174
+ style={{ cursor: 'pointer' }}
175
+ icon={
176
+ <MdCheck
177
+ fontSize={22}
178
+ color="#308653"
179
+ onClick={async () => {
180
+ if (inputContent.length === 0) return;
181
+ try {
182
+ await apiDev.post('chats/messages/edit', {
183
+ chatId: message.chatId,
184
+ messageId: message.id ?? '',
185
+ content: inputContent,
186
+ });
187
+ setIsEditing(false);
188
+ setContent(inputContent);
189
+ toast.open({
190
+ type: 'success',
191
+ title: t('global.notification'),
192
+ message: t('chat.validations.messageChanged'),
193
+ });
194
+ } catch (_) {
195
+ toast.open({
196
+ type: 'error',
197
+ title: t('global.notificationError'),
198
+ message: t(
199
+ 'chat.validations.messageChangeFailed'
200
+ ),
201
+ });
202
+ }
203
+ }}
204
+ />
205
+ }
206
+ size="medium"
207
+ />
208
+ <Icon
209
+ style={{ cursor: 'pointer' }}
210
+ icon={
211
+ <MdClose
212
+ fontSize={22}
213
+ color="#D73E3E"
214
+ onClick={() => {
215
+ setIsEditing(false);
216
+ setInputContent(content ?? '');
217
+ }}
218
+ />
219
+ }
220
+ size="medium"
221
+ />
222
+ </Track>
223
+ )}
224
+ </Track>
225
+ {selected && (
226
+ <div className="active-chat__selection-icon">
227
+ <MdOutlineCheck />
228
+ </div>
229
+ )}
230
+ </>
231
+ )}
232
+ </div>
233
+ {message.event === CHAT_EVENTS.WAITING_VALIDATION && (
234
+ <Button
235
+ appearance="success"
236
+ style={{
237
+ borderRadius: '50px',
238
+ marginTop: '5px',
239
+ marginLeft: '-55px',
240
+ paddingLeft: '40px',
241
+ paddingRight: '40px',
242
+ display: 'absolute',
243
+ right: '10',
244
+ }}
245
+ onClick={() => {
246
+ approveMessage.mutate({
247
+ chatId: message.chatId,
248
+ messageId: message.id ?? '',
249
+ });
250
+ }}
251
+ >
252
+ {t('chat.validations.confirmAnswer')}
253
+ </Button>
254
+ )}
255
+ {buttons.length > 0 && <ButtonMessage buttons={buttons} />}
256
+ {options.length > 0 && <OptionMessage options={options} />}
257
+ {message.event === CHAT_EVENTS.READ ? (
258
+ <span className="active-chat__message-status">
259
+ {t('global.read')}
260
+ <time dateTime={message.authorTimestamp}>
261
+ {' '}
262
+ {format(new Date(message.authorTimestamp), 'HH:mm:ss')}
263
+ </time>
264
+ </span>
265
+ ) : null}{' '}
266
+ </div>
267
+ );
268
+ };
269
+
270
+ export default ChatMessage;