index.tsx 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. import { makeStyles } from "@material-ui/core/styles";
  2. import SendIcon from '@mui/icons-material/Send';
  3. import MicNoneIcon from '@mui/icons-material/MicNone';
  4. import AttachFileIcon from '@mui/icons-material/AttachFile';
  5. import SentimentSatisfiedAltIcon from '@mui/icons-material/SentimentSatisfiedAlt';
  6. import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
  7. import Avatar from '@mui/material/Avatar';
  8. import CloseIcon from '@mui/icons-material/Close';
  9. import { useState } from "react";
  10. import { useSelector } from "react-redux";
  11. import FilesMenu from "../FilesMenu";
  12. import NotDone from "../../../../reusableComponents/NotDone";
  13. import { sentMessageById,sentImgMessageById } from '../../../../../api-data'
  14. import { getChat } from '../../../../../redux/chat/selector'
  15. import { playNotification } from "../../../../../helpers";
  16. import { typingChat } from "../../../../../api-data";
  17. const useStyles = makeStyles({
  18. container: {
  19. display: "flex",
  20. justifyContent: "space-between",
  21. alignContent: 'flex-end',
  22. alignItems:'flex-end',
  23. width: 700,
  24. position: 'fixed',
  25. bottom: 20,
  26. paddingTop:10,
  27. },
  28. inputContainer: {
  29. position:'relative',
  30. minWidth: 634,
  31. maxWidth: 634,
  32. maxHeight:56,
  33. display: 'flex',
  34. flexWrap: 'nowrap',
  35. alignContent: 'center',
  36. alignItems: 'center',
  37. color: '#6b6b6b',
  38. backgroundColor: '#ffffff',
  39. borderRadius: 8,
  40. padding: 10,
  41. marginRight: 10,
  42. "&:after": {
  43. content: "''",
  44. position: "absolute",
  45. width: "0",
  46. height: "0",
  47. borderBottom: "15px solid #ffffff",
  48. borderLeft: "15px solid transparent",
  49. borderRight: "15px solid transparent",
  50. bottom: "0",
  51. right: "-15px"
  52. },
  53. "&:before": {
  54. content: "''",
  55. position: "absolute",
  56. width: "0",
  57. height: "0",
  58. borderBottom: "17px solid #ffffff",
  59. borderLeft: "16px solid transparent",
  60. borderRight: "16px solid transparent",
  61. bottom: "-1px",
  62. right: "-17px"
  63. }
  64. },
  65. textarea: {
  66. minWidth: 550,
  67. maxWidth: 550,
  68. outline: 'none',
  69. border:'none',
  70. padding: '0px 10px',
  71. marginLeft: 8,
  72. marginRight: 8,
  73. overflowY:'auto',
  74. resize: 'none',
  75. height: 'auto',
  76. },
  77. attachIcon: {
  78. transform:'rotate(30deg)',
  79. },
  80. filesMenu: {
  81. background: '#fdfdfd',
  82. position: 'absolute',
  83. width: 355,
  84. maxWidth: '100%',
  85. left: 406,
  86. bottom:64,
  87. zIndex: 10,
  88. visibility: 'visible',
  89. borderRadius: 10,
  90. padding: '4px 6px',
  91. },
  92. emoji: {
  93. background: '#fdfdfd',
  94. position: 'absolute',
  95. width: 350,
  96. height:350,
  97. left: 0,
  98. bottom:64,
  99. zIndex: 10,
  100. visibility: 'visible',
  101. borderRadius: 10,
  102. padding: '0px 6px',
  103. },
  104. avatar: {
  105. '&:hover': {
  106. backgroundColor: 'rgb(41, 139, 231)',
  107. color: '#ffffff',
  108. }
  109. },
  110. avatarArrow: {
  111. left: 120,
  112. bottom:200,
  113. '&:hover': {
  114. backgroundColor: 'rgb(41, 139, 231)',
  115. color: '#ffffff',
  116. }
  117. },
  118. iconCancel: {
  119. position: 'absolute',
  120. left:-45,
  121. display:'flex',
  122. backgroundColor: '#945353',
  123. width: 56,
  124. height: 56,
  125. color: '#6b6b6b',
  126. borderRadius: '50%',
  127. '&:hover': {
  128. backgroundColor: 'rgb(218, 18, 18)',
  129. color: '#ffffff',
  130. }
  131. },
  132. });
  133. interface ISendMessage{
  134. isArrow:boolean,
  135. handleScrollTo:() => void
  136. }
  137. const SendMessage = ({isArrow,handleScrollTo}:ISendMessage) => {
  138. const classes = useStyles();
  139. const { companionId } = useSelector(getChat)
  140. const [value, setValue] = useState<string>('')
  141. const [file, setFile] = useState<any>(null)
  142. const [isOpenMenu, setIsOpenMenu] = useState<boolean>(false)
  143. const [isOpenEmoji, setIsOpenEmoji] = useState<boolean>(false)
  144. const sentMessage = async () => {
  145. setValue('')
  146. setFile(null)
  147. isOpenMenu&&setIsOpenMenu(false)
  148. isOpenEmoji && setIsOpenEmoji(false)
  149. if (value) sentMessageById(companionId, value)
  150. if (file && file.type) {
  151. if (file.type === 'image/png' || file.type === 'image/jpeg') {
  152. const formData: any = new FormData()
  153. formData.append("img", file);
  154. console.log('image')
  155. await sentImgMessageById(companionId, formData)
  156. }
  157. if (file.type === 'audio/mpeg') {
  158. console.log('mp3')
  159. }
  160. if (file.type === 'video/mp4') {
  161. console.log('mp4')
  162. }
  163. }
  164. setTimeout(handleScrollTo, 3000);
  165. playNotification('http://localhost:3000/send.mp3')
  166. }
  167. const handleTextarea = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
  168. isOpenMenu&&setIsOpenMenu(false)
  169. isOpenEmoji && setIsOpenEmoji(false)
  170. setValue(e.target.value)
  171. }
  172. const handleFocusTextarea = () => {
  173. typingChat(companionId,true)
  174. isOpenMenu&&setIsOpenMenu(false)
  175. isOpenEmoji&&setIsOpenEmoji(false)
  176. }
  177. const handleBlurTextarea = () => typingChat(companionId,false)
  178. const handleLeaveInput = (e: any) => {
  179. if (e.clientX > 1450 || e.clientX < 850) {
  180. isOpenMenu&&setIsOpenMenu(false)
  181. isOpenEmoji&&setIsOpenEmoji(false)
  182. }
  183. }
  184. const handleMoveInput = (e: any) => {
  185. if (e.clientX < 1250 && e.clientX > 1200) {
  186. isOpenMenu&&setIsOpenMenu(false)
  187. isOpenEmoji&&setIsOpenEmoji(false)
  188. }
  189. }
  190. const handleKeyPres = (e: any) => {
  191. if(e.code === 'Enter'&& value) sentMessage()
  192. }
  193. const handleEnterFileMenu = () => !isOpenMenu&&setIsOpenMenu(true)
  194. const handleLeaveFileMenu = () => isOpenMenu&&setIsOpenMenu(false)
  195. const handleEnterEmoji = () => !isOpenEmoji&&setIsOpenEmoji(true)
  196. const handleLeaveEmoji = () => isOpenEmoji && setIsOpenEmoji(false)
  197. const handleClearMessage = () => setFile(null)
  198. return (
  199. <div className={classes.container} style={{borderTop:isArrow?'solid 1px #ffffff':'none'}} >
  200. <div onMouseLeave={handleLeaveInput} onMouseMove={handleMoveInput}
  201. onKeyPress={handleKeyPres} className={classes.inputContainer}>
  202. <CloseIcon onClick={handleClearMessage} fontSize="small" className={classes.iconCancel}
  203. sx={{backgroundColor:'#ffffff',width:36,height:36,color:'#949393',display:file?'inline-block':'none'}}/>
  204. <SentimentSatisfiedAltIcon onMouseEnter={handleEnterEmoji}
  205. fontSize='medium' sx={{ color: isOpenEmoji ? 'rgb(41, 139, 231)' : '#6b6b6b' }}/>
  206. <div onMouseLeave={handleLeaveEmoji} style={{display:isOpenEmoji?'block':'none'}} className={classes.emoji}>
  207. <NotDone name='Emoji Bar'/>
  208. </div>
  209. <textarea disabled={file?true:false} value={value} onBlur={handleBlurTextarea} onFocus={handleFocusTextarea} onChange={handleTextarea}
  210. className={classes.textarea} placeholder={file?'Press onto Plane to send or Cross to remove':'Message'} rows={1}></textarea>
  211. <AttachFileIcon onMouseEnter={handleEnterFileMenu} className={classes.attachIcon}
  212. fontSize='medium' sx={{color: isOpenMenu?'rgb(41, 139, 231)':'#6b6b6b'}}/>
  213. <div onMouseLeave={handleLeaveFileMenu} style={{display:isOpenMenu?'block':'none'}} className={classes.filesMenu}>
  214. <FilesMenu setFile={setFile} setValue={setValue} setIsOpenMenu={setIsOpenMenu}/>
  215. </div>
  216. <Avatar onClick={handleScrollTo} className={classes.avatarArrow} sx={{
  217. backgroundColor: '#ffffff',
  218. width: 56, height: 56 ,color: '#6b6b6b',display:isArrow?'flex':'none'}}>
  219. <ArrowDownwardIcon fontSize="medium" />
  220. </Avatar>
  221. </div>
  222. {value || file ?
  223. <Avatar onClick={sentMessage} className={classes.avatar} sx={{
  224. backgroundColor: '#ffffff',
  225. width: 56, height: 56 ,color: 'rgb(41, 139, 231)'}}>
  226. <SendIcon fontSize="medium" />
  227. </Avatar> :
  228. <Avatar className={classes.avatar} sx={{
  229. backgroundColor: '#ffffff',
  230. width: 56, height: 56, color: '#6b6b6b'}}>
  231. <MicNoneIcon fontSize="medium" />
  232. </Avatar>}
  233. </div>
  234. )
  235. }
  236. export default SendMessage