import React, { useState, useEffect, useRef } from 'react'; import { useTool } from '../context/ToolContext'; import DevChatInput from '../tools/dev_chatbot/ChatInput.jsx'; import { marked } from 'marked'; marked.setOptions({ mangle:false, headerIds:false }); import { fetchOpenAIChat, fetchOpenAIImage, classifyRequest } from '../services/openaiService'; import { API_BASE_URL } from '../config'; // === Chat History Panel 컴포넌트 추가 === function ChatHistoryPanel({ toolId }) { const [open, setOpen] = React.useState(false); const [messages, setMessages] = React.useState([]); // 패널이 열릴 때마다 로컬스토리지에서 메시지 불러오기 React.useEffect(() => { if (!open) return; try { const saved = JSON.parse(localStorage.getItem(`messages_${toolId}`) || '[]'); setMessages(Array.isArray(saved) ? saved : []); } catch { setMessages([]); } }, [toolId, open]); return ( <>
대화 히스토리
); } function FileSidebar() { const [files, setFiles] = useState([]); const loadFiles = async () => { try { const res = await fetch(`${API_BASE_URL}/files`); const data = await res.json(); setFiles(data.files || []); } catch (_) {} }; useEffect(() => { loadFiles(); }, []); const handleDelete = async (fname) => { if (!window.confirm(`${fname} 파일을 삭제하시겠습니까?`)) return; await fetch(`${API_BASE_URL}/file?filename=${encodeURIComponent(fname)}`, { method: 'DELETE' }); loadFiles(); }; const handleUpload = async (e) => { const files = Array.from(e.target.files || []); if (!files.length) return; const formData = new FormData(); files.forEach((f) => formData.append('files', f)); await fetch(`${API_BASE_URL}/upload_pdf`, { method: 'POST', body: formData }); loadFiles(); }; return (
파일 리스트
); } export default function ChatPage() { const { selectedTool } = useTool(); const [messages, setMessages] = useState(() => { try { const toolIdInitial = selectedTool?.id || 'chatgpt'; const saved = JSON.parse(localStorage.getItem(`messages_${toolIdInitial}`) || '[]'); return Array.isArray(saved) ? saved.filter(m=>m.type!=='loading') : []; } catch { return []; } }); const [input, setInput] = useState(''); const [chatModel, setChatModel] = useState('GPT-5'); const inputRef = useRef(null); const chatEndRef = useRef(null); // 기본 카드: ChatGPT (도구 목록에서 제거되었기 때문에 selectedTool 이 없으면 ChatGPT로 동작) const defaultChatTool = { id: 'chatgpt', name: 'ChatGPT', description: '일반 대화 및 모델 선택 기능을 제공합니다.' }; const activeTool = selectedTool || defaultChatTool; // 히스토리 패널용 공통 값 const toolId = selectedTool?.id || 'chatgpt'; const historyPanel = ; useEffect(() => { // 카드 전환 시 해당 카드의 저장된 대화 불러오기 (기본: chatgpt) const toolId = selectedTool?.id || 'chatgpt'; try { const key = `messages_${toolId}`; const saved = JSON.parse(localStorage.getItem(key) || '[]'); setMessages(Array.isArray(saved) ? saved.filter(m=>m.type!=='loading') : []); } catch { setMessages([]); } }, [selectedTool?.id]); useEffect(() => { // scroll to bottom chatEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages]); // 대화 변경 시 로컬스토리지에 저장 (기본: chatgpt) useEffect(() => { const toolId = selectedTool?.id || 'chatgpt'; try { localStorage.setItem(`messages_${toolId}`, JSON.stringify(messages)); } catch {} }, [messages, selectedTool?.id]); // iframe 도구 처리 const iframeTools = { research_qa: 'http://yongin-qa-chatbot.daewoongai.com/', lims_text2sql: 'http://3.38.184.255:8080/', }; if (selectedTool && iframeTools[selectedTool.id]) { return (
{historyPanel}