agx-chat-web 1.2.1 → 1.2.2

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 (204) hide show
  1. package/README.md +49 -49
  2. package/package.json +91 -91
  3. package/src/__tests__/app/Messenger/classes/slaCalculations.spec.ts +122 -122
  4. package/src/app/ChatProvider/ChatProvider.tsx +20 -20
  5. package/src/app/Messenger/classes/slaCalculations.ts +197 -197
  6. package/src/app/Messenger/components/ChatButton/ChatButton.tsx +64 -64
  7. package/src/app/Messenger/components/ChatTabs/ChatTabs.less +18 -18
  8. package/src/app/Messenger/components/ChatTabs/ChatTabs.tsx +32 -32
  9. package/src/app/Messenger/components/DocMessage/DocMessage.less +71 -71
  10. package/src/app/Messenger/components/DocMessage/DocMessage.tsx +50 -50
  11. package/src/app/Messenger/components/ImagesContainer/ImagesContainer.less +79 -79
  12. package/src/app/Messenger/components/ImagesContainer/ImagesContainer.tsx +51 -51
  13. package/src/app/Messenger/components/IncomingMessage/IncomingMessage.tsx +170 -170
  14. package/src/app/Messenger/components/InfiniteScroll/InfiniteScroll.tsx +80 -80
  15. package/src/app/Messenger/components/InputFile/InputFile.tsx +147 -147
  16. package/src/app/Messenger/components/InputFile/inputFile.less +59 -59
  17. package/src/app/Messenger/components/MessageBallon/MessageBalloon.tsx +100 -100
  18. package/src/app/Messenger/components/MessengerAvatar/MessengerAvatar.tsx +29 -29
  19. package/src/app/Messenger/components/MessengerThemeWrapper/MessengerThemeWrapper.tsx +62 -62
  20. package/src/app/Messenger/components/RenderFileIcon/RenderFileIcon.tsx +40 -40
  21. package/src/app/Messenger/components/SearchInput/SearchInput.less +45 -45
  22. package/src/app/Messenger/components/SearchInput/SearchInput.tsx +77 -77
  23. package/src/app/Messenger/components/Select/Select.less +22 -22
  24. package/src/app/Messenger/components/Select/Select.tsx +56 -56
  25. package/src/app/Messenger/components/SendMessageForm/SendMessageForm.tsx +254 -254
  26. package/src/app/Messenger/components/SenderMessages/SenderMessages.tsx +91 -91
  27. package/src/app/Messenger/components/SystemMessage/SystemMessage.tsx +25 -25
  28. package/src/app/Messenger/components/TextArea/TextArea.tsx +35 -35
  29. package/src/app/Messenger/components/TextArea/Textarea.less +22 -22
  30. package/src/app/Messenger/components/Tooltip/Tooltip.less +27 -27
  31. package/src/app/Messenger/components/Tooltip/Tooltip.tsx +17 -17
  32. package/src/app/Messenger/hooks/useConversations.tsx +143 -143
  33. package/src/app/Messenger/hooks/useMessages.tsx +49 -49
  34. package/src/app/Messenger/hooks/useThemes.tsx +14 -14
  35. package/src/app/Messenger/icons/AttachFileIcon.tsx +20 -20
  36. package/src/app/Messenger/icons/CSVFileIcon.tsx +26 -26
  37. package/src/app/Messenger/icons/CloseIcon.tsx +20 -20
  38. package/src/app/Messenger/icons/DOCFileIcon.tsx +54 -54
  39. package/src/app/Messenger/icons/DownloadMinimalistIcon.tsx +37 -37
  40. package/src/app/Messenger/icons/EmptyIcon.tsx +20 -20
  41. package/src/app/Messenger/icons/MP4FileIcon.tsx +26 -26
  42. package/src/app/Messenger/icons/MessageIcon.tsx +27 -27
  43. package/src/app/Messenger/icons/PDFFileIcon.tsx +54 -54
  44. package/src/app/Messenger/icons/ReadIcon.tsx +18 -18
  45. package/src/app/Messenger/icons/SearchIcon.tsx +20 -20
  46. package/src/app/Messenger/icons/TimerIcon.tsx +18 -18
  47. package/src/app/Messenger/icons/TrashIcon.tsx +21 -21
  48. package/src/app/Messenger/views/Messenger.less +623 -623
  49. package/src/app/Messenger/views/MessengerList.tsx +170 -170
  50. package/src/app/Messenger/views/MessengerListItem.tsx +178 -178
  51. package/src/app/Messenger/views/MessengerMessages.tsx +414 -414
  52. package/src/app/Messenger/views/NewFormChat.tsx +145 -145
  53. package/src/app/i18n/index.ts +36 -36
  54. package/src/app/i18n/locales/en.json +64 -64
  55. package/src/app/i18n/locales/pt.json +64 -64
  56. package/src/assets/right-arrow.svg +9 -9
  57. package/src/index.ts +23 -23
  58. package/src/react-app-env.d.ts +19 -19
  59. package/src/setupTests.ts +5 -5
  60. package/src/styles/abstracts/animations.less +8 -8
  61. package/src/styles/abstracts/mixins.less +5 -5
  62. package/src/styles/abstracts/variables.less +31 -31
  63. package/src/styles/base/base.less +6 -6
  64. package/src/styles/index.less +5 -5
  65. package/src/types.ts +174 -174
  66. package/dist/agx-chat.esm.js +0 -2
  67. package/dist/agx-chat.esm.js.map +0 -1
  68. package/dist/agx-chat.umd.js +0 -2
  69. package/dist/agx-chat.umd.js.map +0 -1
  70. package/dist/esm/__tests__/app/Messenger/classes/slaCalculations.spec.d.ts +0 -1
  71. package/dist/esm/__tests__/app/Messenger/classes/slaCalculations.spec.js +0 -46
  72. package/dist/esm/__tests__/app/Messenger/classes/slaCalculations.spec.js.map +0 -1
  73. package/dist/esm/app/ChatProvider/ChatProvider.d.ts +0 -7
  74. package/dist/esm/app/ChatProvider/ChatProvider.js +0 -14
  75. package/dist/esm/app/ChatProvider/ChatProvider.js.map +0 -1
  76. package/dist/esm/app/Messenger/classes/slaCalculations.d.ts +0 -30
  77. package/dist/esm/app/Messenger/classes/slaCalculations.js +0 -144
  78. package/dist/esm/app/Messenger/classes/slaCalculations.js.map +0 -1
  79. package/dist/esm/app/Messenger/components/ChatButton/ChatButton.d.ts +0 -14
  80. package/dist/esm/app/Messenger/components/ChatButton/ChatButton.js +0 -31
  81. package/dist/esm/app/Messenger/components/ChatButton/ChatButton.js.map +0 -1
  82. package/dist/esm/app/Messenger/components/ChatTabs/ChatTabs.d.ts +0 -10
  83. package/dist/esm/app/Messenger/components/ChatTabs/ChatTabs.js +0 -15
  84. package/dist/esm/app/Messenger/components/ChatTabs/ChatTabs.js.map +0 -1
  85. package/dist/esm/app/Messenger/components/DocMessage/DocMessage.d.ts +0 -5
  86. package/dist/esm/app/Messenger/components/DocMessage/DocMessage.js +0 -35
  87. package/dist/esm/app/Messenger/components/DocMessage/DocMessage.js.map +0 -1
  88. package/dist/esm/app/Messenger/components/ImagesContainer/ImagesContainer.d.ts +0 -4
  89. package/dist/esm/app/Messenger/components/ImagesContainer/ImagesContainer.js +0 -39
  90. package/dist/esm/app/Messenger/components/ImagesContainer/ImagesContainer.js.map +0 -1
  91. package/dist/esm/app/Messenger/components/IncomingMessage/IncomingMessage.d.ts +0 -7
  92. package/dist/esm/app/Messenger/components/IncomingMessage/IncomingMessage.js +0 -53
  93. package/dist/esm/app/Messenger/components/IncomingMessage/IncomingMessage.js.map +0 -1
  94. package/dist/esm/app/Messenger/components/InfiniteScroll/InfiniteScroll.d.ts +0 -13
  95. package/dist/esm/app/Messenger/components/InfiniteScroll/InfiniteScroll.js +0 -43
  96. package/dist/esm/app/Messenger/components/InfiniteScroll/InfiniteScroll.js.map +0 -1
  97. package/dist/esm/app/Messenger/components/InputFile/InputFile.d.ts +0 -11
  98. package/dist/esm/app/Messenger/components/InputFile/InputFile.js +0 -74
  99. package/dist/esm/app/Messenger/components/InputFile/InputFile.js.map +0 -1
  100. package/dist/esm/app/Messenger/components/MessageBallon/MessageBalloon.d.ts +0 -9
  101. package/dist/esm/app/Messenger/components/MessageBallon/MessageBalloon.js +0 -34
  102. package/dist/esm/app/Messenger/components/MessageBallon/MessageBalloon.js.map +0 -1
  103. package/dist/esm/app/Messenger/components/MessengerAvatar/MessengerAvatar.d.ts +0 -4
  104. package/dist/esm/app/Messenger/components/MessengerAvatar/MessengerAvatar.js +0 -13
  105. package/dist/esm/app/Messenger/components/MessengerAvatar/MessengerAvatar.js.map +0 -1
  106. package/dist/esm/app/Messenger/components/MessengerThemeWrapper/MessengerThemeWrapper.d.ts +0 -41
  107. package/dist/esm/app/Messenger/components/MessengerThemeWrapper/MessengerThemeWrapper.js +0 -40
  108. package/dist/esm/app/Messenger/components/MessengerThemeWrapper/MessengerThemeWrapper.js.map +0 -1
  109. package/dist/esm/app/Messenger/components/RenderFileIcon/RenderFileIcon.d.ts +0 -6
  110. package/dist/esm/app/Messenger/components/RenderFileIcon/RenderFileIcon.js +0 -29
  111. package/dist/esm/app/Messenger/components/RenderFileIcon/RenderFileIcon.js.map +0 -1
  112. package/dist/esm/app/Messenger/components/SearchInput/SearchInput.d.ts +0 -11
  113. package/dist/esm/app/Messenger/components/SearchInput/SearchInput.js +0 -33
  114. package/dist/esm/app/Messenger/components/SearchInput/SearchInput.js.map +0 -1
  115. package/dist/esm/app/Messenger/components/Select/Select.d.ts +0 -14
  116. package/dist/esm/app/Messenger/components/Select/Select.js +0 -16
  117. package/dist/esm/app/Messenger/components/Select/Select.js.map +0 -1
  118. package/dist/esm/app/Messenger/components/SendMessageForm/SendMessageForm.d.ts +0 -13
  119. package/dist/esm/app/Messenger/components/SendMessageForm/SendMessageForm.js +0 -143
  120. package/dist/esm/app/Messenger/components/SendMessageForm/SendMessageForm.js.map +0 -1
  121. package/dist/esm/app/Messenger/components/SenderMessages/SenderMessages.d.ts +0 -4
  122. package/dist/esm/app/Messenger/components/SenderMessages/SenderMessages.js +0 -43
  123. package/dist/esm/app/Messenger/components/SenderMessages/SenderMessages.js.map +0 -1
  124. package/dist/esm/app/Messenger/components/SystemMessage/SystemMessage.d.ts +0 -4
  125. package/dist/esm/app/Messenger/components/SystemMessage/SystemMessage.js +0 -14
  126. package/dist/esm/app/Messenger/components/SystemMessage/SystemMessage.js.map +0 -1
  127. package/dist/esm/app/Messenger/components/TextArea/TextArea.d.ts +0 -9
  128. package/dist/esm/app/Messenger/components/TextArea/TextArea.js +0 -14
  129. package/dist/esm/app/Messenger/components/TextArea/TextArea.js.map +0 -1
  130. package/dist/esm/app/Messenger/components/Tooltip/Tooltip.d.ts +0 -7
  131. package/dist/esm/app/Messenger/components/Tooltip/Tooltip.js +0 -9
  132. package/dist/esm/app/Messenger/components/Tooltip/Tooltip.js.map +0 -1
  133. package/dist/esm/app/Messenger/hooks/useConversations.d.ts +0 -21
  134. package/dist/esm/app/Messenger/hooks/useConversations.js +0 -105
  135. package/dist/esm/app/Messenger/hooks/useConversations.js.map +0 -1
  136. package/dist/esm/app/Messenger/hooks/useMessages.d.ts +0 -9
  137. package/dist/esm/app/Messenger/hooks/useMessages.js +0 -37
  138. package/dist/esm/app/Messenger/hooks/useMessages.js.map +0 -1
  139. package/dist/esm/app/Messenger/hooks/useThemes.d.ts +0 -32
  140. package/dist/esm/app/Messenger/hooks/useThemes.js +0 -11
  141. package/dist/esm/app/Messenger/hooks/useThemes.js.map +0 -1
  142. package/dist/esm/app/Messenger/icons/AttachFileIcon.d.ts +0 -4
  143. package/dist/esm/app/Messenger/icons/AttachFileIcon.js +0 -10
  144. package/dist/esm/app/Messenger/icons/AttachFileIcon.js.map +0 -1
  145. package/dist/esm/app/Messenger/icons/CSVFileIcon.d.ts +0 -4
  146. package/dist/esm/app/Messenger/icons/CSVFileIcon.js +0 -7
  147. package/dist/esm/app/Messenger/icons/CSVFileIcon.js.map +0 -1
  148. package/dist/esm/app/Messenger/icons/CloseIcon.d.ts +0 -2
  149. package/dist/esm/app/Messenger/icons/CloseIcon.js +0 -9
  150. package/dist/esm/app/Messenger/icons/CloseIcon.js.map +0 -1
  151. package/dist/esm/app/Messenger/icons/DOCFileIcon.d.ts +0 -4
  152. package/dist/esm/app/Messenger/icons/DOCFileIcon.js +0 -18
  153. package/dist/esm/app/Messenger/icons/DOCFileIcon.js.map +0 -1
  154. package/dist/esm/app/Messenger/icons/DownloadMinimalistIcon.d.ts +0 -7
  155. package/dist/esm/app/Messenger/icons/DownloadMinimalistIcon.js +0 -12
  156. package/dist/esm/app/Messenger/icons/DownloadMinimalistIcon.js.map +0 -1
  157. package/dist/esm/app/Messenger/icons/EmptyIcon.d.ts +0 -2
  158. package/dist/esm/app/Messenger/icons/EmptyIcon.js +0 -8
  159. package/dist/esm/app/Messenger/icons/EmptyIcon.js.map +0 -1
  160. package/dist/esm/app/Messenger/icons/MP4FileIcon.d.ts +0 -4
  161. package/dist/esm/app/Messenger/icons/MP4FileIcon.js +0 -7
  162. package/dist/esm/app/Messenger/icons/MP4FileIcon.js.map +0 -1
  163. package/dist/esm/app/Messenger/icons/MessageIcon.d.ts +0 -6
  164. package/dist/esm/app/Messenger/icons/MessageIcon.js +0 -12
  165. package/dist/esm/app/Messenger/icons/MessageIcon.js.map +0 -1
  166. package/dist/esm/app/Messenger/icons/PDFFileIcon.d.ts +0 -4
  167. package/dist/esm/app/Messenger/icons/PDFFileIcon.js +0 -18
  168. package/dist/esm/app/Messenger/icons/PDFFileIcon.js.map +0 -1
  169. package/dist/esm/app/Messenger/icons/ReadIcon.d.ts +0 -4
  170. package/dist/esm/app/Messenger/icons/ReadIcon.js +0 -7
  171. package/dist/esm/app/Messenger/icons/ReadIcon.js.map +0 -1
  172. package/dist/esm/app/Messenger/icons/SearchIcon.d.ts +0 -2
  173. package/dist/esm/app/Messenger/icons/SearchIcon.js +0 -8
  174. package/dist/esm/app/Messenger/icons/SearchIcon.js.map +0 -1
  175. package/dist/esm/app/Messenger/icons/TimerIcon.d.ts +0 -4
  176. package/dist/esm/app/Messenger/icons/TimerIcon.js +0 -7
  177. package/dist/esm/app/Messenger/icons/TimerIcon.js.map +0 -1
  178. package/dist/esm/app/Messenger/icons/TrashIcon.d.ts +0 -6
  179. package/dist/esm/app/Messenger/icons/TrashIcon.js +0 -7
  180. package/dist/esm/app/Messenger/icons/TrashIcon.js.map +0 -1
  181. package/dist/esm/app/Messenger/views/MessengerList.d.ts +0 -40
  182. package/dist/esm/app/Messenger/views/MessengerList.js +0 -46
  183. package/dist/esm/app/Messenger/views/MessengerList.js.map +0 -1
  184. package/dist/esm/app/Messenger/views/MessengerListItem.d.ts +0 -12
  185. package/dist/esm/app/Messenger/views/MessengerListItem.js +0 -99
  186. package/dist/esm/app/Messenger/views/MessengerListItem.js.map +0 -1
  187. package/dist/esm/app/Messenger/views/MessengerMessages.d.ts +0 -35
  188. package/dist/esm/app/Messenger/views/MessengerMessages.js +0 -181
  189. package/dist/esm/app/Messenger/views/MessengerMessages.js.map +0 -1
  190. package/dist/esm/app/Messenger/views/NewFormChat.d.ts +0 -13
  191. package/dist/esm/app/Messenger/views/NewFormChat.js +0 -68
  192. package/dist/esm/app/Messenger/views/NewFormChat.js.map +0 -1
  193. package/dist/esm/app/i18n/index.d.ts +0 -3
  194. package/dist/esm/app/i18n/index.js +0 -32
  195. package/dist/esm/app/i18n/index.js.map +0 -1
  196. package/dist/esm/index.d.ts +0 -11
  197. package/dist/esm/index.js +0 -12
  198. package/dist/esm/index.js.map +0 -1
  199. package/dist/esm/setupTests.d.ts +0 -1
  200. package/dist/esm/setupTests.js +0 -6
  201. package/dist/esm/setupTests.js.map +0 -1
  202. package/dist/esm/types.d.ts +0 -140
  203. package/dist/esm/types.js +0 -2
  204. package/dist/esm/types.js.map +0 -1
@@ -1,414 +1,414 @@
1
- import React, {
2
- Fragment,
3
- useState,
4
- useRef,
5
- MutableRefObject,
6
- useEffect,
7
- } from 'react'
8
- import ImagesContainer from '../components/ImagesContainer/ImagesContainer'
9
- import MessageBalloon from '../components/MessageBallon/MessageBalloon'
10
-
11
- import MessageIcon from '../icons/MessageIcon'
12
-
13
- import { ICommonProps, IList, IMessages, IOption } from 'types'
14
- import useTheme from '../hooks/useThemes'
15
-
16
- import NewChatForm from './NewFormChat'
17
- import EmptyIcon from '../icons/EmptyIcon'
18
- import SendMessageForm from '../components/SendMessageForm/SendMessageForm'
19
- import InfiniteScroll from '../components/InfiniteScroll/InfiniteScroll'
20
- import { formatFileSize } from '../components/DocMessage/DocMessage'
21
- import { useTranslation } from 'react-i18next'
22
-
23
- interface IScrollableContainer {
24
- loading: boolean
25
- onIntersect: () => Promise<void>
26
- hasNext: boolean
27
- }
28
-
29
- type MessengerView = 'empty' | 'messages' | 'newChat'
30
-
31
- interface IMessengerMessages extends ICommonProps, IScrollableContainer {
32
- header: React.ReactElement
33
- current?: IList
34
- creatorId?: string
35
- allowImages: boolean
36
- tab?: 'list' | 'messages'
37
- messegerView: MessengerView
38
- className?: string
39
- messages: IMessages[]
40
- onSubmit: (value: FormData, callback: () => void) => Promise<void>
41
- cancelNewChat: () => void
42
- formatDate: (date: string | Date) => string | undefined
43
- reasons: Array<IOption>
44
- products: Array<IOption>
45
- submitNewChat: (values: FormData) => void
46
- newChatLoading: boolean
47
- maxFileSize: () => Promise<{ data: { data: { maxFileSize: number } } }>
48
- }
49
-
50
- interface IMessengerForm {
51
- children: React.ReactNode
52
- messegerView: MessengerView
53
- reasons: Array<IOption>
54
- products: Array<IOption>
55
- submitNewChat: (values: FormData) => void
56
- cancelNewChat: () => void
57
- newChatLoading: boolean
58
- maxFileSize: string
59
- loadingResources: boolean
60
- }
61
-
62
- function MessagesContainerView ({
63
- children,
64
- messegerView,
65
- submitNewChat,
66
- cancelNewChat,
67
- reasons,
68
- products,
69
- newChatLoading,
70
- maxFileSize,
71
- loadingResources,
72
- }: IMessengerForm) {
73
- const { theme } = useTheme()
74
- const { t } = useTranslation('messengerMessages')
75
-
76
- if (messegerView === 'empty') {
77
- return (
78
- <div
79
- className='messenger__messages-container--empty'
80
- style={{ backgroundColor: theme?.messengerNotSelectedBg }}
81
- >
82
- <MessageIcon width='72' height='72' />
83
- <p>{t('selectConversation')}</p>
84
- </div>
85
- )
86
- }
87
-
88
- if (messegerView === 'newChat') {
89
- return (
90
- <NewChatForm
91
- reasons={reasons}
92
- products={products}
93
- submitNewChat={submitNewChat}
94
- cancelNewChat={cancelNewChat}
95
- loading={newChatLoading}
96
- maxFileSize={maxFileSize}
97
- loadingResources={loadingResources}
98
- />
99
- )
100
- }
101
-
102
- return <>{children}</>
103
- }
104
-
105
- export function SpinLoading () {
106
- return (
107
- <div className='messenger__messages-loading'>
108
- <div className='messenger__messages-loading--loader' />
109
- </div>
110
- )
111
- }
112
-
113
- function Messages ({
114
- messages,
115
- creatorId,
116
- formatDate,
117
- loading,
118
- }: {
119
- messages: IMessages[]
120
- creatorId?: string
121
- formatDate: (date: string | Date) => string | undefined
122
- loading: boolean
123
- }) {
124
- const { theme } = useTheme()
125
- const { t } = useTranslation('messengerMessages')
126
-
127
- if (!messages || (messages.length === 0 && !loading)) {
128
- return (
129
- <div
130
- className='messenger__message-empty'
131
- style={{ color: theme.emptyMessagesFontColor }}
132
- >
133
- <EmptyIcon />
134
- <p>{t('noMessagesFound')}</p>
135
- </div>
136
- )
137
- }
138
-
139
- return (
140
- <>
141
- {messages.map((item, idx) => {
142
- return (
143
- <Fragment key={`${item.ticketId}_${item.senderId}_${idx}`}>
144
- <MessageBalloon
145
- id={`message_${idx}`}
146
- formatDate={formatDate}
147
- creatorId={creatorId}
148
- item={item}
149
- />
150
- </Fragment>
151
- )
152
- })}
153
- </>
154
- )
155
- }
156
-
157
- const onScrollToBottom = (
158
- scrollContainer: MutableRefObject<HTMLDivElement | null>
159
- ) => {
160
- if (scrollContainer.current) {
161
- scrollContainer.current.scrollTop = Number.MAX_SAFE_INTEGER
162
- }
163
- }
164
-
165
- function MessagesContainer ({
166
- children,
167
- fowardRef,
168
- ...rest
169
- }: {
170
- children: React.ReactNode
171
- fowardRef: MutableRefObject<HTMLDivElement | null>
172
- } & React.DetailedHTMLProps<
173
- React.HTMLAttributes<HTMLDivElement>,
174
- HTMLDivElement
175
- >) {
176
- const { theme } = useTheme()
177
-
178
- return (
179
- <div
180
- {...rest}
181
- ref={fowardRef}
182
- className='messenger__messages-container'
183
- style={{
184
- padding: '1rem',
185
- backgroundColor: theme?.messengerMessagesBg,
186
- border: `1px solid ${theme.borderColor}`,
187
- }}
188
- >
189
- {children}
190
- </div>
191
- )
192
- }
193
-
194
- function ScrollableContainer ({
195
- children,
196
- loading,
197
- onIntersect,
198
- hasNext,
199
- scrollContainerFowardRef,
200
- }: {
201
- children: React.ReactNode
202
- scrollContainerFowardRef: MutableRefObject<HTMLDivElement | null>
203
- } & IScrollableContainer) {
204
- const intersetRootMargin = 300
205
-
206
- const getElementScrollHeight = (divRef: HTMLDivElement | null) => {
207
- if (!divRef) return null
208
- return divRef.scrollHeight
209
- }
210
-
211
- const getElementScrollTop = (divRef: HTMLDivElement | null) => {
212
- if (!divRef) return null
213
- return divRef.scrollTop
214
- }
215
-
216
- const calculateScrollToDecrease = (
217
- elementBeforeIntersetHeight: number,
218
- elementAfterIntersectHeight: number,
219
- intersetRootMargin: number
220
- ) => {
221
- return (
222
- Math.abs(elementAfterIntersectHeight - elementBeforeIntersetHeight) +
223
- intersetRootMargin
224
- )
225
- }
226
-
227
- const isNill = (value: number | null | undefined) => {
228
- return value === null && value === undefined
229
- }
230
-
231
- const onFetchInfiniteScroll = async () => {
232
- const elementBeforeIntersetHeight = getElementScrollHeight(
233
- scrollContainerFowardRef.current
234
- )
235
-
236
- await onIntersect()
237
-
238
- const elementAfterIntersectHeight = getElementScrollHeight(
239
- scrollContainerFowardRef.current
240
- )
241
-
242
- if (
243
- scrollContainerFowardRef.current &&
244
- !isNill(elementBeforeIntersetHeight) &&
245
- !isNill(elementAfterIntersectHeight)
246
- ) {
247
- const currentScrollTop =
248
- getElementScrollTop(scrollContainerFowardRef.current) || 0
249
- scrollContainerFowardRef.current.scrollTop = calculateScrollToDecrease(
250
- elementAfterIntersectHeight as number,
251
- elementBeforeIntersetHeight as number,
252
- currentScrollTop
253
- )
254
- }
255
- }
256
-
257
- useEffect(() => {
258
- onScrollToBottom(scrollContainerFowardRef)
259
- }, [])
260
-
261
- return (
262
- <MessagesContainer fowardRef={scrollContainerFowardRef}>
263
- <InfiniteScroll
264
- root={document.querySelector('.messenger__messages-container')}
265
- loading={loading}
266
- loadingCover={<SpinLoading />}
267
- more={hasNext}
268
- fetch={onFetchInfiniteScroll}
269
- rootMargin={intersetRootMargin}
270
- reverse
271
- >
272
- {children}
273
- </InfiniteScroll>
274
- </MessagesContainer>
275
- )
276
- }
277
-
278
- function MessengerMessages ({
279
- header,
280
- tab,
281
- className = '',
282
- current,
283
- messages,
284
- allowImages,
285
- creatorId,
286
- loading,
287
- onSubmit,
288
- submitNewChat,
289
- cancelNewChat,
290
- reasons,
291
- products,
292
- messegerView,
293
- formatDate,
294
- hasNext,
295
- onIntersect,
296
- newChatLoading,
297
- maxFileSize,
298
- }: IMessengerMessages) {
299
- const { t } = useTranslation('messengerMessages')
300
- const [file, setFile] = useState<File | null>()
301
- const scrollContainerRef = useRef<HTMLDivElement | null>(null)
302
- const [isSending, setIsSending] = useState(false)
303
- const [maxSize, setMaxSize] = useState<string>('')
304
-
305
- const { theme } = useTheme()
306
-
307
- const styleClassnames = {
308
- mobile: tab === 'list' ? 'messenger__mobile-hide' : '',
309
- }
310
-
311
- const updateFile = (file: File | null) => {
312
- setFile(file)
313
- }
314
-
315
- const onSubmitNewMessage = async (
316
- message: FormData,
317
- callback: () => void
318
- ) => {
319
- setIsSending(true)
320
- try {
321
- await onSubmit(message, callback)
322
- onScrollToBottom(scrollContainerRef)
323
- } finally {
324
- setIsSending(false)
325
- }
326
- }
327
-
328
- useEffect(() => {
329
- const fetchMaxFileSize = async () => {
330
- try {
331
- const response = await maxFileSize()
332
- const size = formatFileSize(response.data.data.maxFileSize)
333
- setMaxSize(size)
334
- } catch (error) {
335
- console.error(t('errorSearchingMaxFileSize'), error)
336
- }
337
- }
338
-
339
- fetchMaxFileSize()
340
- }, [maxSize])
341
-
342
- return (
343
- <div
344
- className={`messenger__messages ${className} ${styleClassnames.mobile} `}
345
- >
346
- <MessagesContainerView
347
- newChatLoading={newChatLoading}
348
- reasons={reasons}
349
- products={products}
350
- submitNewChat={submitNewChat}
351
- cancelNewChat={cancelNewChat}
352
- messegerView={messegerView}
353
- maxFileSize={maxSize}
354
- loadingResources={loading}
355
- >
356
- {file ? (
357
- <ImagesContainer file={file} onClose={() => setFile(null)} />
358
- ) : (
359
- <>
360
- <div
361
- className='messenger__messages-header'
362
- style={{
363
- backgroundColor: theme?.headerAndSenderBg,
364
- border: `1px solid ${theme.borderColor}`,
365
- }}
366
- >
367
- {React.cloneElement(header)}
368
- </div>
369
-
370
- {loading && !messages.length ? (
371
- <MessagesContainer fowardRef={scrollContainerRef}>
372
- <SpinLoading />
373
- </MessagesContainer>
374
- ) : (
375
- <ScrollableContainer
376
- scrollContainerFowardRef={scrollContainerRef}
377
- loading={loading}
378
- hasNext={hasNext}
379
- onIntersect={onIntersect}
380
- >
381
- <Messages
382
- formatDate={formatDate}
383
- messages={messages}
384
- creatorId={creatorId}
385
- loading={loading}
386
- />
387
- </ScrollableContainer>
388
- )}
389
- </>
390
- )}
391
-
392
- <div
393
- className='messenger__messages-send'
394
- style={{
395
- backgroundColor: theme?.headerAndSenderBg,
396
- border: `1px solid ${theme.borderColor}`,
397
- }}
398
- >
399
- <SendMessageForm
400
- allowImages={allowImages}
401
- onSubmit={onSubmitNewMessage}
402
- file={file}
403
- updateFile={updateFile}
404
- current={current}
405
- isLoading={isSending}
406
- maxFileSize={maxSize}
407
- />
408
- </div>
409
- </MessagesContainerView>
410
- </div>
411
- )
412
- }
413
-
414
- export default MessengerMessages
1
+ import React, {
2
+ Fragment,
3
+ useState,
4
+ useRef,
5
+ MutableRefObject,
6
+ useEffect,
7
+ } from 'react'
8
+ import ImagesContainer from '../components/ImagesContainer/ImagesContainer'
9
+ import MessageBalloon from '../components/MessageBallon/MessageBalloon'
10
+
11
+ import MessageIcon from '../icons/MessageIcon'
12
+
13
+ import { ICommonProps, IList, IMessages, IOption } from 'types'
14
+ import useTheme from '../hooks/useThemes'
15
+
16
+ import NewChatForm from './NewFormChat'
17
+ import EmptyIcon from '../icons/EmptyIcon'
18
+ import SendMessageForm from '../components/SendMessageForm/SendMessageForm'
19
+ import InfiniteScroll from '../components/InfiniteScroll/InfiniteScroll'
20
+ import { formatFileSize } from '../components/DocMessage/DocMessage'
21
+ import { useTranslation } from 'react-i18next'
22
+
23
+ interface IScrollableContainer {
24
+ loading: boolean
25
+ onIntersect: () => Promise<void>
26
+ hasNext: boolean
27
+ }
28
+
29
+ type MessengerView = 'empty' | 'messages' | 'newChat'
30
+
31
+ interface IMessengerMessages extends ICommonProps, IScrollableContainer {
32
+ header: React.ReactElement
33
+ current?: IList
34
+ creatorId?: string
35
+ allowImages: boolean
36
+ tab?: 'list' | 'messages'
37
+ messegerView: MessengerView
38
+ className?: string
39
+ messages: IMessages[]
40
+ onSubmit: (value: FormData, callback: () => void) => Promise<void>
41
+ cancelNewChat: () => void
42
+ formatDate: (date: string | Date) => string | undefined
43
+ reasons: Array<IOption>
44
+ products: Array<IOption>
45
+ submitNewChat: (values: FormData) => void
46
+ newChatLoading: boolean
47
+ maxFileSize: () => Promise<{ data: { data: { maxFileSize: number } } }>
48
+ }
49
+
50
+ interface IMessengerForm {
51
+ children: React.ReactNode
52
+ messegerView: MessengerView
53
+ reasons: Array<IOption>
54
+ products: Array<IOption>
55
+ submitNewChat: (values: FormData) => void
56
+ cancelNewChat: () => void
57
+ newChatLoading: boolean
58
+ maxFileSize: string
59
+ loadingResources: boolean
60
+ }
61
+
62
+ function MessagesContainerView ({
63
+ children,
64
+ messegerView,
65
+ submitNewChat,
66
+ cancelNewChat,
67
+ reasons,
68
+ products,
69
+ newChatLoading,
70
+ maxFileSize,
71
+ loadingResources,
72
+ }: IMessengerForm) {
73
+ const { theme } = useTheme()
74
+ const { t } = useTranslation('messengerMessages')
75
+
76
+ if (messegerView === 'empty') {
77
+ return (
78
+ <div
79
+ className='messenger__messages-container--empty'
80
+ style={{ backgroundColor: theme?.messengerNotSelectedBg }}
81
+ >
82
+ <MessageIcon width='72' height='72' />
83
+ <p>{t('selectConversation')}</p>
84
+ </div>
85
+ )
86
+ }
87
+
88
+ if (messegerView === 'newChat') {
89
+ return (
90
+ <NewChatForm
91
+ reasons={reasons}
92
+ products={products}
93
+ submitNewChat={submitNewChat}
94
+ cancelNewChat={cancelNewChat}
95
+ loading={newChatLoading}
96
+ maxFileSize={maxFileSize}
97
+ loadingResources={loadingResources}
98
+ />
99
+ )
100
+ }
101
+
102
+ return <>{children}</>
103
+ }
104
+
105
+ export function SpinLoading () {
106
+ return (
107
+ <div className='messenger__messages-loading'>
108
+ <div className='messenger__messages-loading--loader' />
109
+ </div>
110
+ )
111
+ }
112
+
113
+ function Messages ({
114
+ messages,
115
+ creatorId,
116
+ formatDate,
117
+ loading,
118
+ }: {
119
+ messages: IMessages[]
120
+ creatorId?: string
121
+ formatDate: (date: string | Date) => string | undefined
122
+ loading: boolean
123
+ }) {
124
+ const { theme } = useTheme()
125
+ const { t } = useTranslation('messengerMessages')
126
+
127
+ if (!messages || (messages.length === 0 && !loading)) {
128
+ return (
129
+ <div
130
+ className='messenger__message-empty'
131
+ style={{ color: theme.emptyMessagesFontColor }}
132
+ >
133
+ <EmptyIcon />
134
+ <p>{t('noMessagesFound')}</p>
135
+ </div>
136
+ )
137
+ }
138
+
139
+ return (
140
+ <>
141
+ {messages.map((item, idx) => {
142
+ return (
143
+ <Fragment key={`${item.ticketId}_${item.senderId}_${idx}`}>
144
+ <MessageBalloon
145
+ id={`message_${idx}`}
146
+ formatDate={formatDate}
147
+ creatorId={creatorId}
148
+ item={item}
149
+ />
150
+ </Fragment>
151
+ )
152
+ })}
153
+ </>
154
+ )
155
+ }
156
+
157
+ const onScrollToBottom = (
158
+ scrollContainer: MutableRefObject<HTMLDivElement | null>
159
+ ) => {
160
+ if (scrollContainer.current) {
161
+ scrollContainer.current.scrollTop = Number.MAX_SAFE_INTEGER
162
+ }
163
+ }
164
+
165
+ function MessagesContainer ({
166
+ children,
167
+ fowardRef,
168
+ ...rest
169
+ }: {
170
+ children: React.ReactNode
171
+ fowardRef: MutableRefObject<HTMLDivElement | null>
172
+ } & React.DetailedHTMLProps<
173
+ React.HTMLAttributes<HTMLDivElement>,
174
+ HTMLDivElement
175
+ >) {
176
+ const { theme } = useTheme()
177
+
178
+ return (
179
+ <div
180
+ {...rest}
181
+ ref={fowardRef}
182
+ className='messenger__messages-container'
183
+ style={{
184
+ padding: '1rem',
185
+ backgroundColor: theme?.messengerMessagesBg,
186
+ border: `1px solid ${theme.borderColor}`,
187
+ }}
188
+ >
189
+ {children}
190
+ </div>
191
+ )
192
+ }
193
+
194
+ function ScrollableContainer ({
195
+ children,
196
+ loading,
197
+ onIntersect,
198
+ hasNext,
199
+ scrollContainerFowardRef,
200
+ }: {
201
+ children: React.ReactNode
202
+ scrollContainerFowardRef: MutableRefObject<HTMLDivElement | null>
203
+ } & IScrollableContainer) {
204
+ const intersetRootMargin = 300
205
+
206
+ const getElementScrollHeight = (divRef: HTMLDivElement | null) => {
207
+ if (!divRef) return null
208
+ return divRef.scrollHeight
209
+ }
210
+
211
+ const getElementScrollTop = (divRef: HTMLDivElement | null) => {
212
+ if (!divRef) return null
213
+ return divRef.scrollTop
214
+ }
215
+
216
+ const calculateScrollToDecrease = (
217
+ elementBeforeIntersetHeight: number,
218
+ elementAfterIntersectHeight: number,
219
+ intersetRootMargin: number
220
+ ) => {
221
+ return (
222
+ Math.abs(elementAfterIntersectHeight - elementBeforeIntersetHeight) +
223
+ intersetRootMargin
224
+ )
225
+ }
226
+
227
+ const isNill = (value: number | null | undefined) => {
228
+ return value === null && value === undefined
229
+ }
230
+
231
+ const onFetchInfiniteScroll = async () => {
232
+ const elementBeforeIntersetHeight = getElementScrollHeight(
233
+ scrollContainerFowardRef.current
234
+ )
235
+
236
+ await onIntersect()
237
+
238
+ const elementAfterIntersectHeight = getElementScrollHeight(
239
+ scrollContainerFowardRef.current
240
+ )
241
+
242
+ if (
243
+ scrollContainerFowardRef.current &&
244
+ !isNill(elementBeforeIntersetHeight) &&
245
+ !isNill(elementAfterIntersectHeight)
246
+ ) {
247
+ const currentScrollTop =
248
+ getElementScrollTop(scrollContainerFowardRef.current) || 0
249
+ scrollContainerFowardRef.current.scrollTop = calculateScrollToDecrease(
250
+ elementAfterIntersectHeight as number,
251
+ elementBeforeIntersetHeight as number,
252
+ currentScrollTop
253
+ )
254
+ }
255
+ }
256
+
257
+ useEffect(() => {
258
+ onScrollToBottom(scrollContainerFowardRef)
259
+ }, [])
260
+
261
+ return (
262
+ <MessagesContainer fowardRef={scrollContainerFowardRef}>
263
+ <InfiniteScroll
264
+ root={document.querySelector('.messenger__messages-container')}
265
+ loading={loading}
266
+ loadingCover={<SpinLoading />}
267
+ more={hasNext}
268
+ fetch={onFetchInfiniteScroll}
269
+ rootMargin={intersetRootMargin}
270
+ reverse
271
+ >
272
+ {children}
273
+ </InfiniteScroll>
274
+ </MessagesContainer>
275
+ )
276
+ }
277
+
278
+ function MessengerMessages ({
279
+ header,
280
+ tab,
281
+ className = '',
282
+ current,
283
+ messages,
284
+ allowImages,
285
+ creatorId,
286
+ loading,
287
+ onSubmit,
288
+ submitNewChat,
289
+ cancelNewChat,
290
+ reasons,
291
+ products,
292
+ messegerView,
293
+ formatDate,
294
+ hasNext,
295
+ onIntersect,
296
+ newChatLoading,
297
+ maxFileSize,
298
+ }: IMessengerMessages) {
299
+ const { t } = useTranslation('messengerMessages')
300
+ const [file, setFile] = useState<File | null>()
301
+ const scrollContainerRef = useRef<HTMLDivElement | null>(null)
302
+ const [isSending, setIsSending] = useState(false)
303
+ const [maxSize, setMaxSize] = useState<string>('')
304
+
305
+ const { theme } = useTheme()
306
+
307
+ const styleClassnames = {
308
+ mobile: tab === 'list' ? 'messenger__mobile-hide' : '',
309
+ }
310
+
311
+ const updateFile = (file: File | null) => {
312
+ setFile(file)
313
+ }
314
+
315
+ const onSubmitNewMessage = async (
316
+ message: FormData,
317
+ callback: () => void
318
+ ) => {
319
+ setIsSending(true)
320
+ try {
321
+ await onSubmit(message, callback)
322
+ onScrollToBottom(scrollContainerRef)
323
+ } finally {
324
+ setIsSending(false)
325
+ }
326
+ }
327
+
328
+ useEffect(() => {
329
+ const fetchMaxFileSize = async () => {
330
+ try {
331
+ const response = await maxFileSize()
332
+ const size = formatFileSize(response.data.data.maxFileSize)
333
+ setMaxSize(size)
334
+ } catch (error) {
335
+ console.error(t('errorSearchingMaxFileSize'), error)
336
+ }
337
+ }
338
+
339
+ fetchMaxFileSize()
340
+ }, [maxSize])
341
+
342
+ return (
343
+ <div
344
+ className={`messenger__messages ${className} ${styleClassnames.mobile} `}
345
+ >
346
+ <MessagesContainerView
347
+ newChatLoading={newChatLoading}
348
+ reasons={reasons}
349
+ products={products}
350
+ submitNewChat={submitNewChat}
351
+ cancelNewChat={cancelNewChat}
352
+ messegerView={messegerView}
353
+ maxFileSize={maxSize}
354
+ loadingResources={loading}
355
+ >
356
+ {file ? (
357
+ <ImagesContainer file={file} onClose={() => setFile(null)} />
358
+ ) : (
359
+ <>
360
+ <div
361
+ className='messenger__messages-header'
362
+ style={{
363
+ backgroundColor: theme?.headerAndSenderBg,
364
+ border: `1px solid ${theme.borderColor}`,
365
+ }}
366
+ >
367
+ {React.cloneElement(header)}
368
+ </div>
369
+
370
+ {loading && !messages.length ? (
371
+ <MessagesContainer fowardRef={scrollContainerRef}>
372
+ <SpinLoading />
373
+ </MessagesContainer>
374
+ ) : (
375
+ <ScrollableContainer
376
+ scrollContainerFowardRef={scrollContainerRef}
377
+ loading={loading}
378
+ hasNext={hasNext}
379
+ onIntersect={onIntersect}
380
+ >
381
+ <Messages
382
+ formatDate={formatDate}
383
+ messages={messages}
384
+ creatorId={creatorId}
385
+ loading={loading}
386
+ />
387
+ </ScrollableContainer>
388
+ )}
389
+ </>
390
+ )}
391
+
392
+ <div
393
+ className='messenger__messages-send'
394
+ style={{
395
+ backgroundColor: theme?.headerAndSenderBg,
396
+ border: `1px solid ${theme.borderColor}`,
397
+ }}
398
+ >
399
+ <SendMessageForm
400
+ allowImages={allowImages}
401
+ onSubmit={onSubmitNewMessage}
402
+ file={file}
403
+ updateFile={updateFile}
404
+ current={current}
405
+ isLoading={isSending}
406
+ maxFileSize={maxSize}
407
+ />
408
+ </div>
409
+ </MessagesContainerView>
410
+ </div>
411
+ )
412
+ }
413
+
414
+ export default MessengerMessages