@@ -3,12 +3,15 @@ import { useShowDataStore } from '#/shared/lib/hooks' import { postChat, putChat, removeChat } from '../api' import { useChatsStore } from '.' import { CreateChatDTO } from '../types' +import { useCurrentChat } from '#/features/chats' export function useChatActions() { const { showMessage } = useShowDataStore() const { chats, setChats } = useChatsStore() + const { setCurrentChat } = useCurrentChat() + const onRenameChat = makePrivateRequest(async (uid: string, title: string) => { const chat = chats.find((x) => x.uid === uid) @@ -29,6 +32,10 @@ export function useChatActions() { if (status !== 204 || !chat) return showMessage('Ошибка при переименовании чата') setChats([...chats.filter((c) => c.uid !== uid)]) + + const actual = useChatsStore.getState().chats + + setCurrentChat(actual[0].uid) }) const onCreateChat = makePrivateRequest(async (dto: CreateChatDTO) => { @@ -38,7 +45,7 @@ export function useChatActions() { const chats = useChatsStore.getState().chats - setChats([...chats, chat]) + setChats([chat, ...chats]) }) return { @@ -7,24 +7,25 @@ border-radius: 13px; padding: 12px 15px; text-transform: none; - align-items: center; - position: relative; + width: 100%; + align-items: center; + position: relative; - &__settings{ - color: var(--air-color); - position: relative; - } + &__settings { + color: var(--air-color); + position: relative; + } &__text { font-weight: 500; font-size: 15px; color: var(--new-ui-gray-color); - width: max-content; + width: max-content; &_active { font-weight: 500; font-size: 15px; - color: var(--air-color); + color: var(--air-color); } } @@ -36,15 +37,12 @@ border: none; border-radius: 13px; padding: 12px 15px; - padding-bottom: 10px; - gap: 12px; + padding-bottom: 10px; + gap: 12px; text-transform: none; background-color: rgba(130, 128, 255, 0.15); - } } - -.chat{ - -} \ No newline at end of file +.chat { +} @@ -1,72 +1,81 @@ import { ChatItemActionsPopup } from '#/features/chat-item-actions' import { useCurrentChat } from '#/features/chats' import { CommonInput } from '#/shared/ui/common-input' -import React, { useRef, useState } from 'react' +import React, { forwardRef, useEffect, useRef, useState } from 'react' import { ChatDTO } from '../types' import styles from './chat-button.module.scss' import RenameSvg from '#/assets/svg/rename.svg?react' import ChatSettingsSvg from '#/assets/svg/chat-settings.svg?react' -import { getPopupById } from '#/shared/ui/popup' +import { PopupTemplateVertical, getPopupById } from '#/shared/ui/popup' import { c } from '#/shared' import { useChatActions } from '../model' import { ChatMobileRename } from '#/features/chat-mobile-rename/ui/chat-mobile-rename-popup' -interface ChatButtonProps extends ChatDTO {} +interface ChatButtonProps extends ChatDTO { + popupVertical?: PopupTemplateVertical +} -export const ChatButton = ({ uid, title }: ChatButtonProps) => { - const { setCurrentChat, currentChat: chat } = useCurrentChat() +export const ChatButton = forwardRef( + ({ uid, title, popupVertical = 'top' }, ref) => { + const { setCurrentChat, currentChat: chat } = useCurrentChat() - const { onRenameChat } = useChatActions() + const { onRenameChat } = useChatActions() - const input = useRef(null) + const input = useRef(null) - const [rename, setRename] = useState(false) + const [rename, setRename] = useState(false) - const popup = getPopupById(uid) + const popup = getPopupById(uid) - return ( - - } - /> - ) : ( -
-

- {title} -

+ useEffect(() => { + if (chat !== uid) popup.setState(false) + }, [chat]) - {uid === chat && ( - - )} - - -
- )} - - ) -} + return ( + + } + /> + ) : ( +
+

+ {title} +

+ + {uid === chat && ( + + )} + + +
+ )} + + ) + } +) @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo } from 'react' +import React, { forwardRef, useEffect, useMemo } from 'react' import { Box, Menu, MenuItem, Slide, Typography } from '@mui/material' import Stack from '@mui/material/Stack' import Image from 'next/image' @@ -14,65 +14,68 @@ import { useThemeAndDevice } from '#/shared/lib/hooks' import AvatarSvg from '#/assets/svg/avatar.svg?react' import DocSvg from '#/assets/svg/doc.svg?react' import MenuSvg from '#/assets/svg/menu.svg?react' -import { CommonTooltip } from '#/shared/ui/tooltip' +import { CommonTooltip, CommonTooltipPosition } from '#/shared/ui/tooltip' import { UserMessageActionsPopup } from '#/features/user-message-actions-popup' import { getPopupById } from '#/shared/ui/popup' export interface BotMessageProps { model: Model message: Message + tooltipPosition?: CommonTooltipPosition } -export function BotMessage({ model, message: { file, ...message } }: BotMessageProps) { - const fileName = useMemo(() => (file ? (file as string).match(/(.+)\/(.+)\?/)![2] : ''), []) +export const BotMessage = forwardRef( + ({ model, tooltipPosition = 'bottom', message: { file, ...message } }, ref) => { + const fileName = useMemo(() => (file ? (file as string).match(/(.+)\/(.+)\?/)![2] : ''), []) - const content = useMemo(() => (file ? fileName : message.content), []) + const content = useMemo(() => (file ? fileName : message.content), []) - const popup = getPopupById(message.uid) + const popup = getPopupById(message.uid) - return ( -
-
- -
-
-
-

{model.title}

-

- {formatDate(message.created_at, { - hour: 'numeric', - minute: 'numeric', - })} -

+ return ( +
+
+
-
-
{ - if (!file) return - window.open(file as string, '_blank') - }} - > - {file && } - +
+
+

{model.title}

+

+ {formatDate(message.created_at, { + hour: 'numeric', + minute: 'numeric', + })} +

-
- - - - +
+
{ + if (!file) return + window.open(file as string, '_blank') + }} + > + {file && } + +
+
+ + + + +
-
- ) -} + ) + } +) @@ -1,9 +1,9 @@ -import React, { memo, useMemo, useState } from 'react' +import React, { forwardRef, memo, useMemo, useState } from 'react' import Image from 'next/image' import { c, formatDate } from '#/shared/lib/helpers' import styles from './user-message.module.scss' -import { CommonTooltip } from '#/shared/ui/tooltip' +import { CommonTooltip, CommonTooltipPosition } from '#/shared/ui/tooltip' import MenuSvg from '#/assets/svg/menu.svg?react' import DocSvg from '#/assets/svg/doc.svg?react' @@ -14,91 +14,91 @@ import { Model } from '#/entities/model-entity' import { useUserMessageActions, useUserMessageImage } from '../model' import { Message } from '../types' -interface IMessagesList { +interface UserMessageProps { message: Message model: Model - // setCurrentSrc: (value: string) => void - // setModal: (value: boolean) => void + tooltipPosition?: CommonTooltipPosition } -export const UserMessage = memo(({ message, model }: IMessagesList) => { - const { loaded, setLoaded, fileIsImage, fileName } = useUserMessageImage(message) +export const UserMessage = memo( + forwardRef(({ message, model, tooltipPosition = 'bottom' }, ref) => { + const { loaded, setLoaded, fileIsImage, fileName } = useUserMessageImage(message) - const { resend } = useUserMessageActions(message) + const { resend } = useUserMessageActions(message) - const popup = getPopupById(message.uid) + const popup = getPopupById(message.uid) - return ( -
-

- {formatDate(message.created_at, { - hour: 'numeric', - minute: 'numeric', - })} -

+ return ( +
+

+ {formatDate(message.created_at, { + hour: 'numeric', + minute: 'numeric', + })} +

-
- {message.file && - (fileIsImage ? ( -
-
- setLoaded(true)} - width={500} - height={500} - src={(message.file as string).split('?type')[0]} - alt={'К сожалению, изображение не загрузилось'} - /> - {!loaded &&
} +
+ {message.file && + (fileIsImage ? ( +
+
+ setLoaded(true)} + width={500} + height={500} + src={(message.file as string).split('?type')[0]} + alt={'К сожалению, изображение не загрузилось'} + /> + {!loaded &&
} +
-
- ) : ( - - ))} - -
-
- + ) : ( + ))} + +
+
+ + + + +
+ + {!message.is_sent && ( + + )} - +

30 ? 'pre-wrap' : 'pre', + }} + > + {message.content} +

- - {!message.is_sent && ( - - )} - -

30 ? 'pre-wrap' : 'pre', - }} - > - {message.content} -

-
- ) -}) + ) + }) +) @@ -73,8 +73,9 @@ export default function BotParamsMap({}: BotParamsMap) { title={name} description={description} value={infrerenceValues[key]} - withoutTooltip={!description || description.length == 0} setValue={(value) => setInferenceValueByKey(key, value)} + withoutTooltip={!description || description.length == 0} + onlyNumber={type == 'int'} /> ) } @@ -4,7 +4,7 @@ import { Device } from '#/shared/lib/types/entities' import { getImagesGalery } from '#/widgets/messages' import { useMediaQuery } from '@mui/material' import { useSession } from 'next-auth/react' -import { createRef, useEffect, useRef, useState } from 'react' +import { createRef, useEffect, useMemo, useRef, useState } from 'react' import { LimitSize, Limit } from '../types' import { useRouter } from 'next/router' import { useShowDataStore } from '#/shared/lib/hooks/use-show-data' @@ -36,9 +36,14 @@ export function useChatBotPagination() { const { data } = useSession() + const messagesWithRefs = useMemo( + () => messages.map((m) => ({ ...m, ref: createRef() })), + [messages] + ) + // TODO: Подумать как написать лучше useEffect(() => { - setMessages([]) + setMessages([]) offset.current = 0 setLoaded(false) fetchMessages() @@ -136,6 +141,7 @@ export function useChatBotPagination() { setMessages, fetchMessages, scrollContainer, + messagesWithRefs, refScroll, loaded, } @@ -1,4 +1,4 @@ -import { PopupTemplate, getPopupById } from '#/shared/ui/popup' +import { PopupTemplate, PopupTemplateProps, getPopupById } from '#/shared/ui/popup' import React, { Dispatch, SetStateAction, useMemo } from 'react' import styles from './chat-item-actions-popup.module.scss' import Rename2Svg from '#/assets/svg/rename-2.svg?react' @@ -6,12 +6,12 @@ import TrashSvg from '#/assets/svg/trash.svg?react' import { useChatActions } from '#/entities/chat' import { useMediaQuery } from 'react-responsive' -export interface ChatItemActionsPopupProps { +export interface ChatItemActionsPopupProps extends PopupTemplateProps { id: string setRename: Dispatch> } -export const ChatItemActionsPopup = ({ id, setRename }: ChatItemActionsPopupProps) => { +export const ChatItemActionsPopup = ({ id, setRename, ...props }: ChatItemActionsPopupProps) => { const { onRemoveChat } = useChatActions() const isMobile = useMediaQuery({ query: '(max-width: 1000px)' }) @@ -27,6 +27,7 @@ export const ChatItemActionsPopup = ({ id, setRename }: ChatItemActionsPopupProp horizontal='right' className={styles.container} id={id} + {...props} >