xmove01

dialogmessages

May 9th, 2023
593
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import USERS from "@/common/data/userDummyData";
  2. import Button, { ButtonGroup } from "@/components/bootstrap/Button";
  3. import Card, { CardActions, CardBody, CardFooter, CardHeader } from "@/components/bootstrap/Card";
  4. import InputGroup from "@/components/bootstrap/forms/InputGroup";
  5. import Textarea from "@/components/bootstrap/forms/Textarea";
  6. import { ChatAvatar, ChatGroup } from "@/components/Chat";
  7. import Icon from "@/components/icon/Icon";
  8. import { IBotDialogMessage } from "@/types/IBot";
  9. import { Field, FieldProps, Form, Formik } from "formik";
  10. import { ChangeEvent, FC, useContext, useEffect, useState } from "react";
  11. import { chatMsgTime, EViewMode } from "../Dialogs";
  12. import InfiniteScroll from "react-infinite-scroll-component";
  13. import './style.scss';
  14. import Input from "@/components/bootstrap/forms/Input";
  15. import Modal, { ModalBody, ModalFooter, ModalHeader } from "@/components/bootstrap/Modal";
  16. import Tooltips from "@/components/bootstrap/Tooltips";
  17. import { useTranslation } from "react-i18next";
  18. import { getLanguages } from "@/lang";
  19. import { IBotDialog } from "@/redux/bots/api";
  20. import ThemeContext from "@/contexts/themeContext";
  21. import classNames from "classnames";
  22. interface IPhotoField {
  23.   photoText: string;
  24.   file: string;
  25. }
  26.  
  27. interface IDialogMessages {
  28.   selectedDialog: IBotDialog | undefined;
  29.   onScrollChat: () => void;
  30.   dialogMessages: IBotDialogMessage[] | undefined;
  31.   isGroup: boolean;
  32.   handleSendMessage: (msg: string) => void;
  33.   handleSendPhoto: (msg: string, file: File, fileType: string) => void;
  34.   handleChangeViewMode: (mode: EViewMode) => void;
  35.   count: number;
  36. }
  37.  
  38. const getFileType = (type: string): string => {
  39.   switch (type) {
  40.     case 'audio': {
  41.       return 'audio';
  42.     }
  43.     case 'video': {
  44.       return 'video';
  45.     }
  46.     case 'image': {
  47.       return 'photo';
  48.     }
  49.     default: {
  50.       return 'file';
  51.     }
  52.   }
  53. }
  54.  
  55. export const DialogMessages: FC<IDialogMessages> = (
  56.   { onScrollChat, dialogMessages, isGroup, handleSendMessage, handleSendPhoto, count, selectedDialog, handleChangeViewMode }
  57. ) => {
  58.   const { t } = useTranslation(getLanguages(['dialogs']));
  59.  
  60.   const [openModal, setOpenModal] = useState<boolean>(false);
  61.   const [file, setFile] = useState<File>();
  62.   const [text, setText] = useState<string>('');
  63.  
  64.   const handleSubmit = () => {
  65.     if (text) {
  66.       handleSendMessage(text);
  67.       setText('');
  68.     }
  69.   }
  70.  
  71.   const { xlDesign, mobileDesign } = useContext(ThemeContext);
  72.  
  73.   return (
  74.     <>
  75.       <Card stretch>
  76.         {Boolean(dialogMessages?.length) &&
  77.           <CardHeader
  78.             className="d-flex flex-row align-items-center justify-content-start gap-3"
  79.             borderSize={1}
  80.           >
  81.             {mobileDesign && (
  82.               <CardActions className="m-0 h-100">
  83.                 <Button
  84.                   isLight
  85.                   color="primary"
  86.                   onClick={() => { handleChangeViewMode(EViewMode.List); }}
  87.                   className="h-100"
  88.                 >
  89.                   <Icon icon='ArrowBack' size='2x' />
  90.                 </Button>
  91.               </CardActions>
  92.             )}
  93.             <CardActions
  94.               className={classNames(
  95.                 { "cursor-pointer": xlDesign }
  96.               )}
  97.               onClick={() => { if (xlDesign) { handleChangeViewMode(EViewMode.Info); } }}
  98.             >
  99.               <div className='d-flex align-items-center'>
  100.                 <ChatAvatar
  101.                   src={selectedDialog?.avatar?.url || USERS.CHLOE.src}
  102.                   className='me-3'
  103.                 />
  104.                 <div className='fw-bold'>
  105.                   {selectedDialog?.name}
  106.                 </div>
  107.               </div>
  108.             </CardActions>
  109.           </CardHeader>
  110.         }
  111.         <CardBody
  112.           className='pt-2 chat-scrollBox overflow-auto'
  113.           id="scrollableDiv"
  114.           style={{
  115.             display: "flex",
  116.             flexDirection: "column-reverse",
  117.             height: "10rem"
  118.           }}
  119.         >
  120.           {!dialogMessages?.length &&
  121.             <div className='d-flex align-items-center justify-content-center w-100 h-100'>
  122.               <p className="fw-bolder fs-3 text-muted">
  123.                 <Icon
  124.                   icon="MarkChatUnread"
  125.                   size='3x'
  126.                   className="me-2"
  127.                 />
  128.                 {t('dialogs.selectDialog')}
  129.               </p>
  130.             </div>
  131.           }
  132.           {dialogMessages && Boolean(dialogMessages?.length) &&
  133.             <InfiniteScroll
  134.               dataLength={dialogMessages?.length || 0}
  135.               next={onScrollChat}
  136.               style={{ display: "flex", flexDirection: "column-reverse" }}
  137.               inverse={true}
  138.               hasMore={dialogMessages.length < count}
  139.               loader={
  140.                 <p className="text-center badge bg-primary text-wrap fs-5">
  141.                   <Icon
  142.                     icon="Downloading"
  143.                     className="me-2"
  144.                   />
  145.                   {t('dialogs.loader')}
  146.                 </p>
  147.               }
  148.               scrollableTarget="scrollableDiv"
  149.             >
  150.               {dialogMessages.map((msg) => (
  151.                 <ChatGroup
  152.                   key={msg.id}
  153.                   type={msg.type}
  154.                   messages={[
  155.                     {
  156.                       id: msg.id,
  157.                       message: msg.content || (!msg.fileLink && msg.type) || '',
  158.                       fileLink: msg.fileLink
  159.                     },
  160.                   ]}
  161.                   user={{
  162.                     src:
  163.                       !msg.botMessage
  164.                         ? msg?.subscriber?.avatar?.url || USERS.CHLOE.src
  165.                         : '',
  166.                     username: msg.subscriber?.username,
  167.                     name: msg.subscriber?.nickname,
  168.                     surname: '',
  169.                   }}
  170.                   isReply={msg.botMessage}
  171.                   isGroup={isGroup}
  172.                   time={msg.updated_at && chatMsgTime(msg.updated_at)}
  173.                 />
  174.               ))}
  175.             </InfiniteScroll>
  176.           }
  177.         </CardBody>
  178.         {Boolean(dialogMessages?.length) &&
  179.           <CardFooter
  180.             className='d-block'
  181.             borderSize={1}
  182.           >
  183.             <InputGroup
  184.               className="msg-input"
  185.             >
  186.               <Textarea
  187.                 rows={2}
  188.                 value={text}
  189.                 onChange={(e: ChangeEvent<HTMLTextAreaElement>) => {
  190.                   //@ts-ignore
  191.                   if (e.nativeEvent.inputType !== "insertLineBreak") {
  192.                     setText(e.target.value);
  193.                   }
  194.                 }}
  195.                 placeholder={t('dialogs.sendMsgPlaceholder')}
  196.                 onKeyDown={(e) => {
  197.                   if (e.code === 'Enter' && e.shiftKey) {
  198.                     setText((prev) => prev + '\n')
  199.                   } else if (e.code === 'Enter') {
  200.                     e.preventDefault();
  201.                     handleSubmit();
  202.                   }
  203.                 }}
  204.               />
  205.               <ButtonGroup>
  206.                 <Tooltips title={t('dialogs.sendFileTooltip')}>
  207.                   <Button
  208.                     icon='AttachFile'
  209.                     size='lg'
  210.                     rounded={0}
  211.                     style={{ height: '100%' }}
  212.                     color='primary'
  213.                     isOutline={true}
  214.                     onClick={() => { setOpenModal(true) }}
  215.                   />
  216.                 </Tooltips>
  217.                 <Tooltips title={t('dialogs.sendBtn')}>
  218.                   <Button
  219.                     color='primary'
  220.                     className="px-3"
  221.                     onClick={() => { handleSubmit(); }}
  222.                   >
  223.                     <Icon icon="Send" size='lg' />
  224.                   </Button>
  225.                 </Tooltips>
  226.               </ButtonGroup>
  227.             </InputGroup>
  228.           </CardFooter>
  229.         }
  230.       </Card>
  231.       <Modal
  232.         isOpen={openModal}
  233.         setIsOpen={setOpenModal}
  234.         isCentered
  235.         isAnimation
  236.       >
  237.         <ModalHeader>
  238.           <p className="fs-3 fw-bolder">
  239.             {t('dialogs.modalHeader')}
  240.           </p>
  241.         </ModalHeader>
  242.  
  243.         <Formik<IPhotoField>
  244.           initialValues={{
  245.             photoText: '',
  246.             file: ''
  247.           }}
  248.           enableReinitialize
  249.           onSubmit={({ photoText }, { resetForm }) => {
  250.             if (file) {
  251.               handleSendPhoto(photoText, file, getFileType(file.type.split('/')[0]));
  252.             }
  253.             resetForm();
  254.             setOpenModal(false);
  255.             setFile(undefined);
  256.           }}
  257.         >
  258.           {({ resetForm }) => (
  259.             <>
  260.               <Form>
  261.                 <ModalBody>
  262.                 <Field id='file' name='file'>
  263.                     {({ field, form }: FieldProps<IPhotoField['file']>) => (
  264.                       <div className="mb-4">
  265.                         <p className="ms-2 fw-bolder">{t('dialogs.modalFile')}</p>
  266.                         <Input
  267.                           type="file"
  268.                           {...field}
  269.                           onChange={(e: React.ChangeEvent<any>) => {
  270.                             form.handleChange(e);
  271.                             setFile(e.target.files[0]);
  272.                           }}
  273.                         />
  274.                       </div>
  275.                     )}
  276.                   </Field>
  277.                   <Field id='photoText' name='photoText'>
  278.                     {({ field }: FieldProps<IPhotoField['photoText']>) => (
  279.                       <div>
  280.                         <p className="ms-2 fw-bolder">{t('dialogs.modalText')}</p>
  281.                         <Textarea {...field} />
  282.                       </div>
  283.                     )}
  284.                   </Field>
  285.                 </ModalBody>
  286.                 <ModalFooter>
  287.                   <ButtonGroup>
  288.                     <Button
  289.                       color="danger"
  290.                       onClick={() => {
  291.                         setOpenModal(false);
  292.                         resetForm();
  293.                         setFile(undefined);
  294.                       }}
  295.                     >
  296.                       {t('dialogs.cancelBtn')}
  297.                     </Button>
  298.                     <Button
  299.                       color="primary"
  300.                       type="submit"
  301.                       isDisable={!file}
  302.                     >
  303.                       {t('dialogs.sendBtn')}
  304.                     </Button>
  305.                   </ButtonGroup>
  306.                 </ModalFooter>
  307.               </Form>
  308.             </>
  309.           )}
  310.         </Formik>
  311.       </Modal>
  312.     </>
  313.   )
  314. }
Advertisement
Add Comment
Please, Sign In to add comment