agx-chat-web 0.4.9
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/README.md +9 -0
- package/dist/agx-chat.js +3 -0
- package/dist/agx-chat.js.LICENSE.txt +303 -0
- package/dist/agx-chat.js.map +1 -0
- package/dist/agx-chat.min.js +3 -0
- package/dist/agx-chat.min.js.LICENSE.txt +303 -0
- package/dist/agx-chat.min.js.map +1 -0
- package/dist/esm/__tests__/app/Messenger/classes/slaCalculations.spec.d.ts +1 -0
- package/dist/esm/__tests__/app/Messenger/classes/slaCalculations.spec.js +46 -0
- package/dist/esm/__tests__/app/Messenger/classes/slaCalculations.spec.js.map +1 -0
- package/dist/esm/app/Messenger/classes/slaCalculations.d.ts +30 -0
- package/dist/esm/app/Messenger/classes/slaCalculations.js +142 -0
- package/dist/esm/app/Messenger/classes/slaCalculations.js.map +1 -0
- package/dist/esm/app/Messenger/components/ChatButton/ChatButton.d.ts +14 -0
- package/dist/esm/app/Messenger/components/ChatButton/ChatButton.js +31 -0
- package/dist/esm/app/Messenger/components/ChatButton/ChatButton.js.map +1 -0
- package/dist/esm/app/Messenger/components/ChatTabs/ChatTabs.d.ts +9 -0
- package/dist/esm/app/Messenger/components/ChatTabs/ChatTabs.js +15 -0
- package/dist/esm/app/Messenger/components/ChatTabs/ChatTabs.js.map +1 -0
- package/dist/esm/app/Messenger/components/ImagesContainer/ImagesContainer.d.ts +3 -0
- package/dist/esm/app/Messenger/components/ImagesContainer/ImagesContainer.js +24 -0
- package/dist/esm/app/Messenger/components/ImagesContainer/ImagesContainer.js.map +1 -0
- package/dist/esm/app/Messenger/components/IncomingMessage/IncomingMessage.d.ts +3 -0
- package/dist/esm/app/Messenger/components/IncomingMessage/IncomingMessage.js +33 -0
- package/dist/esm/app/Messenger/components/IncomingMessage/IncomingMessage.js.map +1 -0
- package/dist/esm/app/Messenger/components/InfiniteScroll/InfiniteScroll.d.ts +11 -0
- package/dist/esm/app/Messenger/components/InfiniteScroll/InfiniteScroll.js +37 -0
- package/dist/esm/app/Messenger/components/InfiniteScroll/InfiniteScroll.js.map +1 -0
- package/dist/esm/app/Messenger/components/InputFile/InputFile.d.ts +8 -0
- package/dist/esm/app/Messenger/components/InputFile/InputFile.js +59 -0
- package/dist/esm/app/Messenger/components/InputFile/InputFile.js.map +1 -0
- package/dist/esm/app/Messenger/components/MessageBallon/MessageBalloon.d.ts +8 -0
- package/dist/esm/app/Messenger/components/MessageBallon/MessageBalloon.js +32 -0
- package/dist/esm/app/Messenger/components/MessageBallon/MessageBalloon.js.map +1 -0
- package/dist/esm/app/Messenger/components/MessengerAvatar/MessengerAvatar.d.ts +3 -0
- package/dist/esm/app/Messenger/components/MessengerAvatar/MessengerAvatar.js +13 -0
- package/dist/esm/app/Messenger/components/MessengerAvatar/MessengerAvatar.js.map +1 -0
- package/dist/esm/app/Messenger/components/MessengerThemeWrapper/MessengerThemeWrapper.d.ts +40 -0
- package/dist/esm/app/Messenger/components/MessengerThemeWrapper/MessengerThemeWrapper.js +39 -0
- package/dist/esm/app/Messenger/components/MessengerThemeWrapper/MessengerThemeWrapper.js.map +1 -0
- package/dist/esm/app/Messenger/components/SearchInput/SearchInput.d.ts +10 -0
- package/dist/esm/app/Messenger/components/SearchInput/SearchInput.js +32 -0
- package/dist/esm/app/Messenger/components/SearchInput/SearchInput.js.map +1 -0
- package/dist/esm/app/Messenger/components/Select/Select.d.ts +13 -0
- package/dist/esm/app/Messenger/components/Select/Select.js +16 -0
- package/dist/esm/app/Messenger/components/Select/Select.js.map +1 -0
- package/dist/esm/app/Messenger/components/SenderMessages/SenderMessages.d.ts +3 -0
- package/dist/esm/app/Messenger/components/SenderMessages/SenderMessages.js +32 -0
- package/dist/esm/app/Messenger/components/SenderMessages/SenderMessages.js.map +1 -0
- package/dist/esm/app/Messenger/components/SystemMessage/SystemMessage.d.ts +3 -0
- package/dist/esm/app/Messenger/components/SystemMessage/SystemMessage.js +14 -0
- package/dist/esm/app/Messenger/components/SystemMessage/SystemMessage.js.map +1 -0
- package/dist/esm/app/Messenger/components/TextArea/TextArea.d.ts +8 -0
- package/dist/esm/app/Messenger/components/TextArea/TextArea.js +14 -0
- package/dist/esm/app/Messenger/components/TextArea/TextArea.js.map +1 -0
- package/dist/esm/app/Messenger/hooks/useConversations.d.ts +11 -0
- package/dist/esm/app/Messenger/hooks/useConversations.js +59 -0
- package/dist/esm/app/Messenger/hooks/useConversations.js.map +1 -0
- package/dist/esm/app/Messenger/hooks/useThemes.d.ts +31 -0
- package/dist/esm/app/Messenger/hooks/useThemes.js +11 -0
- package/dist/esm/app/Messenger/hooks/useThemes.js.map +1 -0
- package/dist/esm/app/Messenger/icons/AttachFileIcon.d.ts +3 -0
- package/dist/esm/app/Messenger/icons/AttachFileIcon.js +10 -0
- package/dist/esm/app/Messenger/icons/AttachFileIcon.js.map +1 -0
- package/dist/esm/app/Messenger/icons/CloseIcon.d.ts +1 -0
- package/dist/esm/app/Messenger/icons/CloseIcon.js +9 -0
- package/dist/esm/app/Messenger/icons/CloseIcon.js.map +1 -0
- package/dist/esm/app/Messenger/icons/EmptyIcon.d.ts +1 -0
- package/dist/esm/app/Messenger/icons/EmptyIcon.js +8 -0
- package/dist/esm/app/Messenger/icons/EmptyIcon.js.map +1 -0
- package/dist/esm/app/Messenger/icons/MessageIcon.d.ts +5 -0
- package/dist/esm/app/Messenger/icons/MessageIcon.js +12 -0
- package/dist/esm/app/Messenger/icons/MessageIcon.js.map +1 -0
- package/dist/esm/app/Messenger/icons/ReadIcon.d.ts +3 -0
- package/dist/esm/app/Messenger/icons/ReadIcon.js +7 -0
- package/dist/esm/app/Messenger/icons/ReadIcon.js.map +1 -0
- package/dist/esm/app/Messenger/icons/SearchIcon.d.ts +1 -0
- package/dist/esm/app/Messenger/icons/SearchIcon.js +8 -0
- package/dist/esm/app/Messenger/icons/SearchIcon.js.map +1 -0
- package/dist/esm/app/Messenger/icons/TimerIcon.d.ts +1 -0
- package/dist/esm/app/Messenger/icons/TimerIcon.js +6 -0
- package/dist/esm/app/Messenger/icons/TimerIcon.js.map +1 -0
- package/dist/esm/app/Messenger/icons/TrashIcon.d.ts +5 -0
- package/dist/esm/app/Messenger/icons/TrashIcon.js +7 -0
- package/dist/esm/app/Messenger/icons/TrashIcon.js.map +1 -0
- package/dist/esm/app/Messenger/views/MessengerList.d.ts +39 -0
- package/dist/esm/app/Messenger/views/MessengerList.js +50 -0
- package/dist/esm/app/Messenger/views/MessengerList.js.map +1 -0
- package/dist/esm/app/Messenger/views/MessengerListItem.d.ts +11 -0
- package/dist/esm/app/Messenger/views/MessengerListItem.js +87 -0
- package/dist/esm/app/Messenger/views/MessengerListItem.js.map +1 -0
- package/dist/esm/app/Messenger/views/MessengerMessages.d.ts +23 -0
- package/dist/esm/app/Messenger/views/MessengerMessages.js +133 -0
- package/dist/esm/app/Messenger/views/MessengerMessages.js.map +1 -0
- package/dist/esm/app/Messenger/views/NewFormChat.d.ts +10 -0
- package/dist/esm/app/Messenger/views/NewFormChat.js +64 -0
- package/dist/esm/app/Messenger/views/NewFormChat.js.map +1 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/setupTests.d.ts +1 -0
- package/dist/esm/setupTests.js +6 -0
- package/dist/esm/setupTests.js.map +1 -0
- package/dist/esm/types.d.ts +134 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +67 -0
- package/src/__tests__/app/Messenger/classes/slaCalculations.spec.ts +115 -0
- package/src/app/Messenger/classes/slaCalculations.ts +165 -0
- package/src/app/Messenger/components/ChatButton/ChatButton.tsx +63 -0
- package/src/app/Messenger/components/ChatTabs/ChatTabs.less +18 -0
- package/src/app/Messenger/components/ChatTabs/ChatTabs.tsx +32 -0
- package/src/app/Messenger/components/ImagesContainer/ImagesContainer.less +64 -0
- package/src/app/Messenger/components/ImagesContainer/ImagesContainer.tsx +40 -0
- package/src/app/Messenger/components/IncomingMessage/IncomingMessage.tsx +59 -0
- package/src/app/Messenger/components/InfiniteScroll/InfiniteScroll.tsx +52 -0
- package/src/app/Messenger/components/InputFile/InputFile.tsx +106 -0
- package/src/app/Messenger/components/InputFile/inputFile.less +52 -0
- package/src/app/Messenger/components/MessageBallon/MessageBalloon.tsx +88 -0
- package/src/app/Messenger/components/MessengerAvatar/MessengerAvatar.tsx +21 -0
- package/src/app/Messenger/components/MessengerThemeWrapper/MessengerThemeWrapper.tsx +58 -0
- package/src/app/Messenger/components/SearchInput/SearchInput.less +45 -0
- package/src/app/Messenger/components/SearchInput/SearchInput.tsx +68 -0
- package/src/app/Messenger/components/Select/Select.less +22 -0
- package/src/app/Messenger/components/Select/Select.tsx +41 -0
- package/src/app/Messenger/components/SenderMessages/SenderMessages.tsx +52 -0
- package/src/app/Messenger/components/SystemMessage/SystemMessage.tsx +23 -0
- package/src/app/Messenger/components/TextArea/TextArea.tsx +31 -0
- package/src/app/Messenger/components/TextArea/Textarea.less +22 -0
- package/src/app/Messenger/hooks/useConversations.tsx +80 -0
- package/src/app/Messenger/hooks/useThemes.tsx +14 -0
- package/src/app/Messenger/icons/AttachFileIcon.tsx +11 -0
- package/src/app/Messenger/icons/CloseIcon.tsx +11 -0
- package/src/app/Messenger/icons/EmptyIcon.tsx +11 -0
- package/src/app/Messenger/icons/MessageIcon.tsx +18 -0
- package/src/app/Messenger/icons/ReadIcon.tsx +9 -0
- package/src/app/Messenger/icons/SearchIcon.tsx +12 -0
- package/src/app/Messenger/icons/TimerIcon.tsx +10 -0
- package/src/app/Messenger/icons/TrashIcon.tsx +13 -0
- package/src/app/Messenger/views/Messenger.less +610 -0
- package/src/app/Messenger/views/MessengerList.tsx +172 -0
- package/src/app/Messenger/views/MessengerListItem.tsx +136 -0
- package/src/app/Messenger/views/MessengerMessages.tsx +287 -0
- package/src/app/Messenger/views/NewFormChat.tsx +126 -0
- package/src/assets/right-arrow.svg +10 -0
- package/src/index.ts +17 -0
- package/src/react-app-env.d.ts +16 -0
- package/src/setupTests.ts +5 -0
- package/src/styles/abstracts/animations.less +8 -0
- package/src/styles/abstracts/mixins.less +5 -0
- package/src/styles/abstracts/variables.less +25 -0
- package/src/styles/base/base.less +6 -0
- package/src/styles/index.less +6 -0
- package/src/types.ts +166 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import TrashIcon from '../../icons/TrashIcon'
|
|
2
|
+
import React, { useMemo } from 'react'
|
|
3
|
+
import useTheme from '../../hooks/useThemes'
|
|
4
|
+
|
|
5
|
+
interface IProps {
|
|
6
|
+
fileList: File[]
|
|
7
|
+
onUpdateFile: (files: File) => void
|
|
8
|
+
label: string
|
|
9
|
+
onRemoveFile: (files: File) => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function InputFile ({ fileList, onUpdateFile, label, onRemoveFile }: IProps) {
|
|
13
|
+
const { theme } = useTheme()
|
|
14
|
+
|
|
15
|
+
const validateFileType = useMemo(() => ( allowedTypes: string[], file?: File) => {
|
|
16
|
+
if (file?.type) {
|
|
17
|
+
return allowedTypes.includes(file?.type)
|
|
18
|
+
}
|
|
19
|
+
return false
|
|
20
|
+
}, [])
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
const onUpload = () => {
|
|
25
|
+
const input = document.querySelector(".file-input__input") as HTMLElement
|
|
26
|
+
input?.click()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
31
|
+
const file = e?.target?.files?.[0]
|
|
32
|
+
|
|
33
|
+
const isAllowedType = validateFileType(['image/png', 'image/jpeg'], file,)
|
|
34
|
+
if (!isAllowedType) {
|
|
35
|
+
console.error('Escolha uma imagem de extensão JPG ou PNG')
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (file) onUpdateFile(file)
|
|
40
|
+
return true
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const removeItem = (file: File) => {
|
|
44
|
+
if (fileList.some((item) => item === file)) {
|
|
45
|
+
onRemoveFile(file)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<>
|
|
52
|
+
<div className='file-input'>
|
|
53
|
+
<label style={{ color: theme.newChatFormTexts}} htmlFor="" className='file-input__label'>{label}</label>
|
|
54
|
+
<div className="file-input__container"
|
|
55
|
+
style={{
|
|
56
|
+
backgroundColor: theme.inputBg,
|
|
57
|
+
color: theme.newChatFormTexts
|
|
58
|
+
}}>
|
|
59
|
+
<input
|
|
60
|
+
className='file-input__input'
|
|
61
|
+
type="file"
|
|
62
|
+
id="docpicker"
|
|
63
|
+
hidden
|
|
64
|
+
accept=".jpg, .jpeg, .png"
|
|
65
|
+
onChange={(event) => onChange(event)}
|
|
66
|
+
/>
|
|
67
|
+
<h4>Escolha o arquivo</h4>
|
|
68
|
+
<button
|
|
69
|
+
className='file-input__button'
|
|
70
|
+
type="button"
|
|
71
|
+
onClick={onUpload}
|
|
72
|
+
style={
|
|
73
|
+
{
|
|
74
|
+
background: theme?.buttonPrimary,
|
|
75
|
+
color: theme?.buttonPrimaryText
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
>
|
|
79
|
+
Escolher arquivo
|
|
80
|
+
</button>
|
|
81
|
+
<p>São aceitas imagens no formato .png ou .jpg</p>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
<div>
|
|
85
|
+
{fileList && fileList.map((item) => {
|
|
86
|
+
return <div className="file-input__list" key={item.name}
|
|
87
|
+
style={{
|
|
88
|
+
backgroundColor: theme.inputBg,
|
|
89
|
+
color: theme.newChatFormTexts
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
{item.name}
|
|
93
|
+
<button
|
|
94
|
+
className="file-input__delete"
|
|
95
|
+
onClick={() => removeItem(item)}
|
|
96
|
+
>
|
|
97
|
+
<TrashIcon color={theme.newChatFormDeleteFileButton || 'red'} />
|
|
98
|
+
</button>
|
|
99
|
+
</div>
|
|
100
|
+
})}
|
|
101
|
+
</div>
|
|
102
|
+
</>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export default InputFile
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
.file-input {
|
|
2
|
+
margin-bottom: 1rem;
|
|
3
|
+
width: 100%;
|
|
4
|
+
|
|
5
|
+
&__label {
|
|
6
|
+
color: @title-form-color;
|
|
7
|
+
font-weight: bold;
|
|
8
|
+
margin: 0.5rem;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&__container {
|
|
12
|
+
align-items: center;
|
|
13
|
+
background-color: white;
|
|
14
|
+
border-radius: 10px;
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
justify-content: center;
|
|
18
|
+
margin-top: 0.5rem;
|
|
19
|
+
padding: 1rem;
|
|
20
|
+
width: 100%;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&__button {
|
|
24
|
+
border: none;
|
|
25
|
+
border-radius: 30px;
|
|
26
|
+
color: white;
|
|
27
|
+
cursor: pointer;
|
|
28
|
+
font-size: 1rem;
|
|
29
|
+
font-weight: bold;
|
|
30
|
+
margin: 0.5rem 1rem;
|
|
31
|
+
padding: 0.5rem;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&__list {
|
|
35
|
+
align-items: center;
|
|
36
|
+
background-color: white;
|
|
37
|
+
border-radius: 10px;
|
|
38
|
+
display: flex;
|
|
39
|
+
justify-content: space-between;
|
|
40
|
+
margin: 0.5rem 0;
|
|
41
|
+
padding: 0.5rem;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
&__delete {
|
|
45
|
+
align-items: center;
|
|
46
|
+
background: transparent;
|
|
47
|
+
border: none;
|
|
48
|
+
cursor: pointer;
|
|
49
|
+
display:flex;
|
|
50
|
+
justify-content: center;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Iimages, IMessages } from "types"
|
|
3
|
+
import IncomingMessage from "../IncomingMessage/IncomingMessage"
|
|
4
|
+
import SenderMessages from "../SenderMessages/SenderMessages"
|
|
5
|
+
import SystemMessage from '../SystemMessage/SystemMessage'
|
|
6
|
+
|
|
7
|
+
function MessageBalloon({ item, creatorId, formatDate, id }: {
|
|
8
|
+
item: IMessages,
|
|
9
|
+
creatorId?: string,
|
|
10
|
+
formatDate: (date: string | Date) => string | undefined,
|
|
11
|
+
id: string
|
|
12
|
+
}) {
|
|
13
|
+
if (item.isSystemMessage) {
|
|
14
|
+
return (
|
|
15
|
+
<SystemMessage
|
|
16
|
+
formatDate={formatDate}
|
|
17
|
+
date={item.createdAt}
|
|
18
|
+
message={item.content}
|
|
19
|
+
id={item.senderId}
|
|
20
|
+
user={{ name: 'System' }}
|
|
21
|
+
/>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (item.sender.uniqueCode && !item.isSystemMessage && (item.sender.uniqueCode === creatorId)) {
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
<SenderMessages
|
|
29
|
+
id={id}
|
|
30
|
+
formatDate={formatDate}
|
|
31
|
+
message={item.content}
|
|
32
|
+
date={item.createdAt}
|
|
33
|
+
read={item.everybodyHasRead}
|
|
34
|
+
hasFile={item.hasFile}
|
|
35
|
+
file={item.file}
|
|
36
|
+
/>
|
|
37
|
+
{item.images && item.images.map((image: Iimages, index: number) =>
|
|
38
|
+
<SenderMessages
|
|
39
|
+
key={image.key}
|
|
40
|
+
id={`${id}image-${index}`}
|
|
41
|
+
formatDate={formatDate}
|
|
42
|
+
date={item.createdAt}
|
|
43
|
+
file={image}
|
|
44
|
+
message=''
|
|
45
|
+
hasFile={true}
|
|
46
|
+
read={item.everybodyHasRead}
|
|
47
|
+
/>
|
|
48
|
+
)}
|
|
49
|
+
</>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<>
|
|
55
|
+
<IncomingMessage
|
|
56
|
+
id={id}
|
|
57
|
+
formatDate={formatDate}
|
|
58
|
+
date={item.createdAt}
|
|
59
|
+
message={item.content}
|
|
60
|
+
hasFile={item.hasFile}
|
|
61
|
+
isSystemMessage={item.isSystemMessage}
|
|
62
|
+
file={item.file}
|
|
63
|
+
user={{
|
|
64
|
+
avatar: item.sender?.image,
|
|
65
|
+
name: item.sender.username
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
68
|
+
|
|
69
|
+
{item.images && item.images.map((image: Iimages, index: number) =>
|
|
70
|
+
<IncomingMessage
|
|
71
|
+
key={image.key}
|
|
72
|
+
id={`${id}image-${index}`}
|
|
73
|
+
formatDate={formatDate}
|
|
74
|
+
date={item.createdAt}
|
|
75
|
+
file={image}
|
|
76
|
+
message=''
|
|
77
|
+
hasFile={true}
|
|
78
|
+
user={{
|
|
79
|
+
avatar: item.sender?.image,
|
|
80
|
+
name: item.sender.username
|
|
81
|
+
}}
|
|
82
|
+
/>
|
|
83
|
+
)}
|
|
84
|
+
</>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default MessageBalloon
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import useTheme from '../../hooks/useThemes'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { IMesssengerAvatar } from 'types'
|
|
4
|
+
|
|
5
|
+
function MessengerAvatar({ image, children, className = '' }: IMesssengerAvatar) {
|
|
6
|
+
const { theme } = useTheme()
|
|
7
|
+
return (
|
|
8
|
+
<figure
|
|
9
|
+
style={{
|
|
10
|
+
background: theme.messengerIncomerColor
|
|
11
|
+
}}
|
|
12
|
+
className={`${className} messenger__aside-list-item--avatar`}
|
|
13
|
+
>
|
|
14
|
+
{image
|
|
15
|
+
? (<img loading="lazy" alt='imagem de um avatar de usuário' src={image} />)
|
|
16
|
+
: children}
|
|
17
|
+
</figure>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default MessengerAvatar
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React, { createContext, ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
const defaultThemeVariables = {
|
|
4
|
+
asideBg: '#eee',
|
|
5
|
+
asideFontColor: 'white',
|
|
6
|
+
messengerMessagesBg: '#eeeeee',
|
|
7
|
+
headerAndSenderBg: '#232831',
|
|
8
|
+
buttonPrimary: '#25D366',
|
|
9
|
+
buttonPrimaryText: '#707070',
|
|
10
|
+
buttonsDisabled: '#94989D',
|
|
11
|
+
uploadFileIconColor: '#8696a0',
|
|
12
|
+
messengerNotSelectedBg: '#DDDDDD',
|
|
13
|
+
newChatFormBg: '',
|
|
14
|
+
newChatFormRadius: '0 20px 20px 0' ,
|
|
15
|
+
newChatFormTexts: '#000',
|
|
16
|
+
newChatFormDeleteFileButton: '#DD4E4E',
|
|
17
|
+
disclaimerPrimaryColor: '#4791FF',
|
|
18
|
+
disclaimerSecondaryColor: '#4791FF',
|
|
19
|
+
disclaimerTextColor: '#000',
|
|
20
|
+
messengerSenderColor: '#00A73E',
|
|
21
|
+
messengerIncomerColor: "#707070",
|
|
22
|
+
messengerSystemColor: "#2A313A",
|
|
23
|
+
borderColor: '#AAAAAA',
|
|
24
|
+
inputBg:'white',
|
|
25
|
+
chatInputBorder: '',
|
|
26
|
+
listItemHover: '',
|
|
27
|
+
active: '',
|
|
28
|
+
activeTabBorter: '#25D366',
|
|
29
|
+
emptyMessagesFontColor: '#000'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type ThemeVariables = typeof defaultThemeVariables
|
|
33
|
+
|
|
34
|
+
type ThemeContextContent = {
|
|
35
|
+
theme: Partial<ThemeVariables>
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const MessageThemeContext = createContext<ThemeContextContent>(
|
|
39
|
+
{} as unknown as ThemeContextContent
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
type Props = {
|
|
43
|
+
children: ReactNode
|
|
44
|
+
theme?: Partial<ThemeVariables>
|
|
45
|
+
}
|
|
46
|
+
const MessageThemeWrapper = ({ children, theme = defaultThemeVariables }: Props) => {
|
|
47
|
+
const config = {
|
|
48
|
+
theme
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<MessageThemeContext.Provider value={config}>
|
|
53
|
+
{children}
|
|
54
|
+
</MessageThemeContext.Provider>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default MessageThemeWrapper
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
.input-search {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
width: 100%;
|
|
6
|
+
margin: 1rem 0;
|
|
7
|
+
position: relative;
|
|
8
|
+
|
|
9
|
+
&__select {
|
|
10
|
+
border-radius: 30px 0 0 30px;
|
|
11
|
+
padding: 11px;
|
|
12
|
+
background: transparent;
|
|
13
|
+
margin-left: 1rem;
|
|
14
|
+
width: 30%;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
&__option {
|
|
18
|
+
color: black;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&__search {
|
|
22
|
+
width: 70%;
|
|
23
|
+
margin-right: 1rem;
|
|
24
|
+
border-radius: 0 30px 30px 0;
|
|
25
|
+
padding: 10px;
|
|
26
|
+
color: white;
|
|
27
|
+
border: white 1px solid;
|
|
28
|
+
background: transparent;
|
|
29
|
+
position: relative;
|
|
30
|
+
|
|
31
|
+
&::placeholder {
|
|
32
|
+
color: white;
|
|
33
|
+
opacity: 60%;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&__icon {
|
|
38
|
+
border: none;
|
|
39
|
+
background: transparent;
|
|
40
|
+
position: absolute;
|
|
41
|
+
right: 2rem;
|
|
42
|
+
display: flex;
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import SearchIcon from '../../icons/SearchIcon'
|
|
2
|
+
import React, { useState } from 'react'
|
|
3
|
+
import useTheme from '../../hooks/useThemes'
|
|
4
|
+
|
|
5
|
+
interface IProps {
|
|
6
|
+
searchChat: (value: string, key: string)=> void
|
|
7
|
+
searchKeys:{label: string, value: string}[]
|
|
8
|
+
loadingSearch: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
function SearchInput({searchChat, searchKeys, loadingSearch}: IProps) {
|
|
13
|
+
const [searchKey, setSearchKey] = useState<string>(searchKeys[0].value)
|
|
14
|
+
const [searchValue, setSearchValue] = useState<string>('')
|
|
15
|
+
const {theme} = useTheme()
|
|
16
|
+
|
|
17
|
+
const onSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
18
|
+
setSearchValue(event.target.value)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const handleKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
22
|
+
if (event.key === 'Enter') {
|
|
23
|
+
searchChat(searchValue, searchKey)
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="input-search" >
|
|
29
|
+
<select className="input-search__select" onChange={(e)=> setSearchKey(e.target.value)}
|
|
30
|
+
style={{
|
|
31
|
+
color: theme.asideFontColor,
|
|
32
|
+
border: `${theme.asideFontColor} 1px solid`
|
|
33
|
+
}}
|
|
34
|
+
|
|
35
|
+
>
|
|
36
|
+
{searchKeys.map((item, index)=>
|
|
37
|
+
<option className="input-search__option" key={index} value={item.value}>
|
|
38
|
+
{item.label}
|
|
39
|
+
</option>
|
|
40
|
+
)}
|
|
41
|
+
</select>
|
|
42
|
+
|
|
43
|
+
<input
|
|
44
|
+
className='input-search__search'
|
|
45
|
+
placeholder='Pesquisar conversa...'
|
|
46
|
+
onChange={onSearch}
|
|
47
|
+
onKeyDown={handleKeyPress}
|
|
48
|
+
style={{
|
|
49
|
+
color: theme.asideFontColor,
|
|
50
|
+
border: `${theme.asideFontColor} 1px solid`
|
|
51
|
+
}}
|
|
52
|
+
/>
|
|
53
|
+
|
|
54
|
+
<button
|
|
55
|
+
className="input-search__icon"
|
|
56
|
+
onClick={() => searchChat(searchValue, searchKey)}
|
|
57
|
+
>
|
|
58
|
+
{loadingSearch ? (
|
|
59
|
+
<div className="messenger__messages-loading">
|
|
60
|
+
<div className="messenger__messages-loading--loader" />
|
|
61
|
+
</div>
|
|
62
|
+
) : <SearchIcon />}
|
|
63
|
+
</button>
|
|
64
|
+
</div>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default SearchInput
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.form-select {
|
|
2
|
+
margin-bottom: 1rem;
|
|
3
|
+
width: 100%;
|
|
4
|
+
|
|
5
|
+
&__label {
|
|
6
|
+
color: @title-form-color;
|
|
7
|
+
font-weight: bold;
|
|
8
|
+
margin: 0.5rem;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&__input {
|
|
12
|
+
border: 1.5px solid hsl(0, 0%, 80%);
|
|
13
|
+
border-radius: 4px;
|
|
14
|
+
margin-top: 0.5rem;
|
|
15
|
+
padding: 8px 8px;
|
|
16
|
+
width: 100%;
|
|
17
|
+
|
|
18
|
+
&:focus {
|
|
19
|
+
outline: #2684FF 2px solid !important;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import useTheme from '../../hooks/useThemes'
|
|
3
|
+
interface IProps {
|
|
4
|
+
options: {
|
|
5
|
+
label: string,
|
|
6
|
+
value: string
|
|
7
|
+
}[],
|
|
8
|
+
label: string
|
|
9
|
+
onChange: (value: string) => void
|
|
10
|
+
name: string
|
|
11
|
+
placeholder: string
|
|
12
|
+
value: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function SelectNew({ options, name, placeholder, label, onChange, value }: IProps) {
|
|
16
|
+
const { theme } = useTheme()
|
|
17
|
+
return (
|
|
18
|
+
<div className="form-select">
|
|
19
|
+
<label htmlFor={name} className="form-select__label"
|
|
20
|
+
style={{ color: theme.newChatFormTexts}}
|
|
21
|
+
>{label}</label >
|
|
22
|
+
<select
|
|
23
|
+
name={name}
|
|
24
|
+
placeholder={placeholder}
|
|
25
|
+
className="form-select__input"
|
|
26
|
+
onChange={(e) => onChange(e.target.value)}
|
|
27
|
+
value={value}
|
|
28
|
+
style={{
|
|
29
|
+
backgroundColor: theme.inputBg,
|
|
30
|
+
color: theme.newChatFormTexts
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
{options.map(motivo =>
|
|
34
|
+
<option key={motivo.value} value={motivo.value}>{motivo.label}</option>
|
|
35
|
+
)}
|
|
36
|
+
</select>
|
|
37
|
+
</div>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default SelectNew
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import useTheme from '../../hooks/useThemes'
|
|
2
|
+
import React, { useCallback, useState } from 'react'
|
|
3
|
+
import { IMessagesBalloon } from "types"
|
|
4
|
+
import ReadIcon from "../../icons/ReadIcon"
|
|
5
|
+
import ReactSimpleImageViewer from '../../../../../node_modules/react-simple-image-viewer'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
function SenderMessages({ date, message, read, hasFile, file, formatDate, id }: IMessagesBalloon) {
|
|
9
|
+
const [currentImage, setCurrentImage] = useState(0);
|
|
10
|
+
const [isViewerOpen, setIsViewerOpen] = useState(false);
|
|
11
|
+
const { theme } = useTheme()
|
|
12
|
+
|
|
13
|
+
const openImageViewer = useCallback((index) => {
|
|
14
|
+
setCurrentImage(index);
|
|
15
|
+
setIsViewerOpen(true);
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
const closeImageViewer = () => {
|
|
19
|
+
setCurrentImage(0);
|
|
20
|
+
setIsViewerOpen(false);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<div className="messenger__messages-row--sender" >
|
|
25
|
+
<div className="messenger__messages-sender" id={id} style={{ background: theme?.messengerSenderColor }}>
|
|
26
|
+
<span>
|
|
27
|
+
{hasFile && (
|
|
28
|
+
<div className="messenger__message--file">
|
|
29
|
+
<img src={file?.location} width={200} alt="imagem na mensagem" onClick={() => openImageViewer(currentImage)} />
|
|
30
|
+
</div>
|
|
31
|
+
)}
|
|
32
|
+
<p className="messenger__message">{message}</p>
|
|
33
|
+
<div className="messenger__message--bottom">
|
|
34
|
+
<p className="messenger__message--date">{formatDate(date) ?? new Date(date).toString()}</p>
|
|
35
|
+
<ReadIcon fill={read ? '#00efff' : 'white'} />
|
|
36
|
+
</div>
|
|
37
|
+
</span>
|
|
38
|
+
</div>
|
|
39
|
+
{file && isViewerOpen &&
|
|
40
|
+
<ReactSimpleImageViewer
|
|
41
|
+
src={[file.location]}
|
|
42
|
+
currentIndex={0}
|
|
43
|
+
disableScroll={false}
|
|
44
|
+
closeOnClickOutside={true}
|
|
45
|
+
onClose={closeImageViewer}
|
|
46
|
+
/>
|
|
47
|
+
}
|
|
48
|
+
</div>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default SenderMessages
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import useTheme from '../../hooks/useThemes'
|
|
3
|
+
import { IInconmingMessage } from 'types'
|
|
4
|
+
|
|
5
|
+
function SystemMessage ({ date, message, formatDate, id }: IInconmingMessage) {
|
|
6
|
+
const {theme} = useTheme()
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div
|
|
10
|
+
className="messenger__messages-row--system"
|
|
11
|
+
id={id}
|
|
12
|
+
>
|
|
13
|
+
<div className="messenger__messages-received messenger__messages-received--system" style={{background: theme?.messengerSystemColor}}>
|
|
14
|
+
<span>
|
|
15
|
+
<p className="messenger__message">{message}</p>
|
|
16
|
+
<p className="messenger__message--date">{formatDate(date) ?? new Date(date).toString()}</p>
|
|
17
|
+
</span>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default SystemMessage
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import useTheme from '../../hooks/useThemes'
|
|
3
|
+
interface IProps {
|
|
4
|
+
label: string
|
|
5
|
+
onChange: (value: string) => void
|
|
6
|
+
name: string
|
|
7
|
+
placeholder: string,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function Textarea({ name, placeholder, label, onChange }: IProps) {
|
|
11
|
+
const { theme } = useTheme()
|
|
12
|
+
return (
|
|
13
|
+
<div className='text-area'>
|
|
14
|
+
<label htmlFor={name} className="text-area__label"
|
|
15
|
+
style={{ color: theme.newChatFormTexts}} >{label}</label >
|
|
16
|
+
<textarea
|
|
17
|
+
style={{
|
|
18
|
+
backgroundColor: theme.inputBg,
|
|
19
|
+
color: theme.newChatFormTexts
|
|
20
|
+
}}
|
|
21
|
+
name={name}
|
|
22
|
+
placeholder={placeholder}
|
|
23
|
+
className="text-area__input"
|
|
24
|
+
onChange={(e) => onChange(e.target.value)}
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default Textarea
|
|
31
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.text-area {
|
|
2
|
+
margin-bottom: 1rem;
|
|
3
|
+
width: 100%;
|
|
4
|
+
|
|
5
|
+
&__label {
|
|
6
|
+
color: @title-form-color;
|
|
7
|
+
font-weight: bold;
|
|
8
|
+
margin: 0.5rem;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&__input {
|
|
12
|
+
border: 1.5px solid hsl(0, 0%, 80%);
|
|
13
|
+
border-radius: 4px;
|
|
14
|
+
margin-top: 0.5rem;
|
|
15
|
+
padding: 4px 8px;
|
|
16
|
+
width: 100%;
|
|
17
|
+
|
|
18
|
+
&:focus {
|
|
19
|
+
outline: #2684FF 2px solid !important;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|