Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import USERS from "@/common/data/userDummyData";
- import Button, { ButtonGroup } from "@/components/bootstrap/Button";
- import Card, { CardActions, CardBody, CardFooter, CardHeader } from "@/components/bootstrap/Card";
- import InputGroup from "@/components/bootstrap/forms/InputGroup";
- import Textarea from "@/components/bootstrap/forms/Textarea";
- import { ChatAvatar, ChatGroup } from "@/components/Chat";
- import Icon from "@/components/icon/Icon";
- import { IBotDialogMessage } from "@/types/IBot";
- import { Field, FieldProps, Form, Formik } from "formik";
- import { ChangeEvent, FC, useContext, useEffect, useState } from "react";
- import { chatMsgTime, EViewMode } from "../Dialogs";
- import InfiniteScroll from "react-infinite-scroll-component";
- import './style.scss';
- import Input from "@/components/bootstrap/forms/Input";
- import Modal, { ModalBody, ModalFooter, ModalHeader } from "@/components/bootstrap/Modal";
- import Tooltips from "@/components/bootstrap/Tooltips";
- import { useTranslation } from "react-i18next";
- import { getLanguages } from "@/lang";
- import { IBotDialog } from "@/redux/bots/api";
- import ThemeContext from "@/contexts/themeContext";
- import classNames from "classnames";
- interface IPhotoField {
- photoText: string;
- file: string;
- }
- interface IDialogMessages {
- selectedDialog: IBotDialog | undefined;
- onScrollChat: () => void;
- dialogMessages: IBotDialogMessage[] | undefined;
- isGroup: boolean;
- handleSendMessage: (msg: string) => void;
- handleSendPhoto: (msg: string, file: File, fileType: string) => void;
- handleChangeViewMode: (mode: EViewMode) => void;
- count: number;
- }
- const getFileType = (type: string): string => {
- switch (type) {
- case 'audio': {
- return 'audio';
- }
- case 'video': {
- return 'video';
- }
- case 'image': {
- return 'photo';
- }
- default: {
- return 'file';
- }
- }
- }
- export const DialogMessages: FC<IDialogMessages> = (
- { onScrollChat, dialogMessages, isGroup, handleSendMessage, handleSendPhoto, count, selectedDialog, handleChangeViewMode }
- ) => {
- const { t } = useTranslation(getLanguages(['dialogs']));
- const [openModal, setOpenModal] = useState<boolean>(false);
- const [file, setFile] = useState<File>();
- const [text, setText] = useState<string>('');
- const handleSubmit = () => {
- if (text) {
- handleSendMessage(text);
- setText('');
- }
- }
- const { xlDesign, mobileDesign } = useContext(ThemeContext);
- return (
- <>
- <Card stretch>
- {Boolean(dialogMessages?.length) &&
- <CardHeader
- className="d-flex flex-row align-items-center justify-content-start gap-3"
- borderSize={1}
- >
- {mobileDesign && (
- <CardActions className="m-0 h-100">
- <Button
- isLight
- color="primary"
- onClick={() => { handleChangeViewMode(EViewMode.List); }}
- className="h-100"
- >
- <Icon icon='ArrowBack' size='2x' />
- </Button>
- </CardActions>
- )}
- <CardActions
- className={classNames(
- { "cursor-pointer": xlDesign }
- )}
- onClick={() => { if (xlDesign) { handleChangeViewMode(EViewMode.Info); } }}
- >
- <div className='d-flex align-items-center'>
- <ChatAvatar
- src={selectedDialog?.avatar?.url || USERS.CHLOE.src}
- className='me-3'
- />
- <div className='fw-bold'>
- {selectedDialog?.name}
- </div>
- </div>
- </CardActions>
- </CardHeader>
- }
- <CardBody
- className='pt-2 chat-scrollBox overflow-auto'
- id="scrollableDiv"
- style={{
- display: "flex",
- flexDirection: "column-reverse",
- height: "10rem"
- }}
- >
- {!dialogMessages?.length &&
- <div className='d-flex align-items-center justify-content-center w-100 h-100'>
- <p className="fw-bolder fs-3 text-muted">
- <Icon
- icon="MarkChatUnread"
- size='3x'
- className="me-2"
- />
- {t('dialogs.selectDialog')}
- </p>
- </div>
- }
- {dialogMessages && Boolean(dialogMessages?.length) &&
- <InfiniteScroll
- dataLength={dialogMessages?.length || 0}
- next={onScrollChat}
- style={{ display: "flex", flexDirection: "column-reverse" }}
- inverse={true}
- hasMore={dialogMessages.length < count}
- loader={
- <p className="text-center badge bg-primary text-wrap fs-5">
- <Icon
- icon="Downloading"
- className="me-2"
- />
- {t('dialogs.loader')}
- </p>
- }
- scrollableTarget="scrollableDiv"
- >
- {dialogMessages.map((msg) => (
- <ChatGroup
- key={msg.id}
- type={msg.type}
- messages={[
- {
- id: msg.id,
- message: msg.content || (!msg.fileLink && msg.type) || '',
- fileLink: msg.fileLink
- },
- ]}
- user={{
- src:
- !msg.botMessage
- ? msg?.subscriber?.avatar?.url || USERS.CHLOE.src
- : '',
- username: msg.subscriber?.username,
- name: msg.subscriber?.nickname,
- surname: '',
- }}
- isReply={msg.botMessage}
- isGroup={isGroup}
- time={msg.updated_at && chatMsgTime(msg.updated_at)}
- />
- ))}
- </InfiniteScroll>
- }
- </CardBody>
- {Boolean(dialogMessages?.length) &&
- <CardFooter
- className='d-block'
- borderSize={1}
- >
- <InputGroup
- className="msg-input"
- >
- <Textarea
- rows={2}
- value={text}
- onChange={(e: ChangeEvent<HTMLTextAreaElement>) => {
- //@ts-ignore
- if (e.nativeEvent.inputType !== "insertLineBreak") {
- setText(e.target.value);
- }
- }}
- placeholder={t('dialogs.sendMsgPlaceholder')}
- onKeyDown={(e) => {
- if (e.code === 'Enter' && e.shiftKey) {
- setText((prev) => prev + '\n')
- } else if (e.code === 'Enter') {
- e.preventDefault();
- handleSubmit();
- }
- }}
- />
- <ButtonGroup>
- <Tooltips title={t('dialogs.sendFileTooltip')}>
- <Button
- icon='AttachFile'
- size='lg'
- rounded={0}
- style={{ height: '100%' }}
- color='primary'
- isOutline={true}
- onClick={() => { setOpenModal(true) }}
- />
- </Tooltips>
- <Tooltips title={t('dialogs.sendBtn')}>
- <Button
- color='primary'
- className="px-3"
- onClick={() => { handleSubmit(); }}
- >
- <Icon icon="Send" size='lg' />
- </Button>
- </Tooltips>
- </ButtonGroup>
- </InputGroup>
- </CardFooter>
- }
- </Card>
- <Modal
- isOpen={openModal}
- setIsOpen={setOpenModal}
- isCentered
- isAnimation
- >
- <ModalHeader>
- <p className="fs-3 fw-bolder">
- {t('dialogs.modalHeader')}
- </p>
- </ModalHeader>
- <Formik<IPhotoField>
- initialValues={{
- photoText: '',
- file: ''
- }}
- enableReinitialize
- onSubmit={({ photoText }, { resetForm }) => {
- if (file) {
- handleSendPhoto(photoText, file, getFileType(file.type.split('/')[0]));
- }
- resetForm();
- setOpenModal(false);
- setFile(undefined);
- }}
- >
- {({ resetForm }) => (
- <>
- <Form>
- <ModalBody>
- <Field id='file' name='file'>
- {({ field, form }: FieldProps<IPhotoField['file']>) => (
- <div className="mb-4">
- <p className="ms-2 fw-bolder">{t('dialogs.modalFile')}</p>
- <Input
- type="file"
- {...field}
- onChange={(e: React.ChangeEvent<any>) => {
- form.handleChange(e);
- setFile(e.target.files[0]);
- }}
- />
- </div>
- )}
- </Field>
- <Field id='photoText' name='photoText'>
- {({ field }: FieldProps<IPhotoField['photoText']>) => (
- <div>
- <p className="ms-2 fw-bolder">{t('dialogs.modalText')}</p>
- <Textarea {...field} />
- </div>
- )}
- </Field>
- </ModalBody>
- <ModalFooter>
- <ButtonGroup>
- <Button
- color="danger"
- onClick={() => {
- setOpenModal(false);
- resetForm();
- setFile(undefined);
- }}
- >
- {t('dialogs.cancelBtn')}
- </Button>
- <Button
- color="primary"
- type="submit"
- isDisable={!file}
- >
- {t('dialogs.sendBtn')}
- </Button>
- </ButtonGroup>
- </ModalFooter>
- </Form>
- </>
- )}
- </Formik>
- </Modal>
- </>
- )
- }
Advertisement
Add Comment
Please, Sign In to add comment