/
anv
/
hackathon
Обзор
Документация
Войти
/
anv
/
hackathon
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/components/PromptForm/PromptForm.tsx
159 строк
6 KB
ANV
add error alert
25 мар 2025, 07:51
25 мар 2025, 07:51
673a03a
Код
Авторство
О чём код?
import React, {useEffect, useRef, useState} from 'react'; import {Alert, Button, Icon, Loader, TextArea, Theme} from '@gravity-ui/uikit'; import styles from './PromptForm.module.scss'; import {ArrowUp, Copy} from '@gravity-ui/icons'; import {Message} from '../types'; import {SSH_REPO_URL} from '../constants'; interface Props { chatTitle?: string; theme: Theme; messages: Message[]; onSendMessage: (message: Message, repoUrl: string) => void; isChatFetching: boolean; isChatsFetching: boolean; isMessagesFetching: boolean; } export const PromptForm: React.FC<Props> = ({ theme, messages, onSendMessage, isChatFetching, isChatsFetching, isMessagesFetching, }) => { const repo = SSH_REPO_URL; const [prompt, setPrompt] = useState(''); const messagesEndRef = useRef<HTMLDivElement>(null); const [hoveredMessage, setHoveredMessage] = useState<number | null>(null); const [isShowAlert, setIsShowAlert] = useState(false); const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { setPrompt(e.target.value); }; const handleSendMessage = () => { if (prompt) { const userMessage: Message = {type: 'user', content: prompt}; onSendMessage(userMessage, repo); setPrompt(''); } }; const copyToClipboard = (content: string) => { navigator.clipboard.writeText(content).then(() => { setIsShowAlert(true); setTimeout(() => { setIsShowAlert(false); }, 3000); }); }; const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSendMessage(); } }; useEffect(() => { if (messagesEndRef.current) { messagesEndRef.current.scrollIntoView({behavior: 'smooth'}); } }, [messages]); return ( <> {isShowAlert && ( <Alert theme="success" title="Скопировано в буфер обмена" className={styles.alert} /> )} <div className={styles.container}> <div className={styles.block}> <div className={styles.chatArea}> <div className={styles.messages}> {messages.map((message, index) => ( <div key={index} className={ message.type === 'user' ? styles.userMessageWrapper : undefined } onMouseEnter={() => setHoveredMessage(index)} onMouseLeave={() => setHoveredMessage(null)} > {message.type === 'user' && hoveredMessage === index && ( <div className={styles.icon} onClick={() => copyToClipboard(message.content)} > <Icon data={Copy} size={16} className={styles.copyIcon} /> </div> )} <div className={ message.type === 'user' ? styles.userMessage : styles.botMessage } > {message.content} </div> </div> ))} {isMessagesFetching ? <Loader size="l" /> : null} <div ref={messagesEndRef} /> </div> </div> </div> </div> <div className={styles.inputArea} style={{backgroundColor: theme === 'dark' ? '#2d2b2c' : '#f0f0f0'}} > <div className={styles.inputs}> <TextArea value={prompt} onChange={handleInputChange} placeholder="Введи промпт..." size="xl" maxRows={4} onKeyDown={handleKeyDown} disabled={isChatFetching || isChatsFetching || isMessagesFetching} /> <TextArea value={repo} onChange={handleInputChange} placeholder="Введи ссылку на репозиторий" size="l" maxRows={4} disabled={true} /> </div> <Button view="action" selected size="l" onClick={handleSendMessage} loading={isChatFetching || isChatsFetching || isMessagesFetching} pin="circle-circle" > <Icon data={ArrowUp} size={18} /> </Button> </div> </> ); };