Spaces:
Running
Running
| import React from 'react'; | |
| import Modal from 'react-modal'; | |
| import { GoX } from 'react-icons/go'; | |
| import { LlmPrompt } from '@/api/llmPrompts/types'; | |
| import { useQuery } from '@tanstack/react-query'; | |
| import { fetchLlmPromptById, fetchDefaultLlmPrompt } from '@/api/llmPrompts/llmPromptApi'; | |
| import './LlmPromptModal.scss'; | |
| interface LlmPromptModalProps { | |
| isOpen: boolean; | |
| onRequestClose: () => void; | |
| prompt: LlmPrompt | null; | |
| onSave: (prompt: LlmPrompt | Omit<LlmPrompt, 'id' | 'created_at'>) => Promise<void>; | |
| isEditMode: boolean; | |
| } | |
| const customStyles = { | |
| content: { | |
| top: '40%', | |
| left: '50%', | |
| right: 'auto', | |
| bottom: 'auto', | |
| transform: 'translate(-50%, -50%)', | |
| borderRadius: '15px', | |
| maxWidth: '100%', | |
| overflow: 'hidden', | |
| }, | |
| }; | |
| const LlmPromptModal: React.FC<LlmPromptModalProps> = ({ | |
| isOpen, | |
| onRequestClose, | |
| prompt, | |
| onSave, | |
| isEditMode, | |
| }) => { | |
| const [formData, setFormData] = React.useState<LlmPrompt | Omit<LlmPrompt, 'id' | 'created_at'>>(() => ({ | |
| is_default: false, | |
| name: 'Промпт ' + Date.now().toLocaleString(), | |
| text: "", | |
| type: 'system' | |
| })); | |
| // Запрос промпта для редактирования | |
| const { data: serverPrompt, isLoading: isPromptLoading } = useQuery({ | |
| queryKey: ['llmPrompt', prompt?.id], | |
| queryFn: () => fetchLlmPromptById(prompt!.id), | |
| enabled: isOpen && isEditMode && !!prompt?.id, | |
| }); | |
| // Запрос дефолтного промпта для создания | |
| const { data: defaultPrompt, isLoading: isDefaultLoading } = useQuery({ | |
| queryKey: ['defaultLlmPrompt'], | |
| queryFn: fetchDefaultLlmPrompt, | |
| enabled: isOpen && !isEditMode, // Запрашиваем только при создании | |
| }); | |
| React.useEffect(() => { | |
| if (isOpen) { | |
| if (isEditMode && serverPrompt) { | |
| setFormData(serverPrompt); // Данные с сервера для редактирования | |
| } else if (!isEditMode && defaultPrompt) { | |
| setFormData(defaultPrompt); // Дефолтная запись с сервера для создания | |
| } else if (!isEditMode && !defaultPrompt && !isDefaultLoading) { | |
| setFormData({ // Если дефолтной записи нет и загрузка завершена | |
| is_default: true, | |
| name: 'Промпт ' + Date.now().toLocaleString(), | |
| text: "", | |
| type: 'system' | |
| }); | |
| } | |
| } | |
| }, [isOpen, isEditMode, serverPrompt, defaultPrompt, isDefaultLoading]); | |
| const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { | |
| const { name, value } = e.target; | |
| setFormData(prev => ({ | |
| ...prev, | |
| [name]: | |
| name === 'is_default' ? (e.target as HTMLInputElement).checked : | |
| name === 'text' || name === 'name' ? value : | |
| parseFloat(value) || 0, | |
| })); | |
| }; | |
| const handleSubmit = async (e: React.FormEvent) => { | |
| e.preventDefault(); | |
| try { | |
| await onSave(formData); | |
| onRequestClose(); | |
| } catch (err) { | |
| console.error('Save failed:', err); | |
| } | |
| }; | |
| if (isPromptLoading && isEditMode) { | |
| return <div>Loading prompt...</div>; | |
| } | |
| if (isDefaultLoading && !isEditMode) { | |
| return <div>Loading default prompt...</div>; | |
| } | |
| return ( | |
| <Modal | |
| isOpen={isOpen} | |
| onRequestClose={onRequestClose} | |
| style={customStyles} | |
| overlayClassName="modal-overlay" | |
| > | |
| <div className="modal-content"> | |
| <div className="label"> | |
| <h3 className="name">{isEditMode ? 'Редактирование промпта' : 'Новый промпт'}</h3> | |
| <button className="close-button" onClick={onRequestClose}> | |
| <GoX style={{ height: '25px', width: '25px' }} /> | |
| </button> | |
| </div> | |
| <form onSubmit={handleSubmit}> | |
| {isEditMode && 'id' in formData && ( | |
| <label> | |
| <span>ID:</span> | |
| <input type="text" value={formData.id} disabled /> | |
| </label> | |
| )} | |
| <label> | |
| <span>Задать по-умолчанию:</span> | |
| <input | |
| type="checkbox" | |
| name="is_default" | |
| checked={formData.is_default} | |
| onChange={handleChange} | |
| /> | |
| </label> | |
| <label> | |
| <span>Название:</span> | |
| <input | |
| type="text" | |
| name="name" | |
| value={formData.name} | |
| onChange={handleChange} | |
| /> | |
| </label> | |
| <label> | |
| <span>Текст:</span> | |
| <textarea | |
| name="text" | |
| value={formData.text || ''} | |
| onChange={handleChange} | |
| /> | |
| </label> | |
| <div className="button-group"> | |
| <button type="submit">{isEditMode ? 'Сохранить' : 'Создать'}</button> | |
| </div> | |
| </form> | |
| </div> | |
| </Modal> | |
| ); | |
| }; | |
| export default LlmPromptModal; |