import React, { useEffect, useRef, useState } from "react"; import { useAppStore } from "../../stores/useAppStore"; import { aiProcessor } from "../../utils/aiProcessor"; interface PromptInputProps { value: string; onChange?: (e: React.ChangeEvent) => void; onExecute?: () => void; disabled?: boolean; maxLength?: number; onHistoryToggle?: () => void; historyCount?: number; } /** * 에디트 화면 하단 고정 프롬프트 입력창 컴포넌트 * - 이미지 참고: 입력창, Execute 버튼, 안내문구, 글자수 카운트, 하단 고정 * - 유니버 시트에서 셀 선택 시 자동으로 셀 주소 삽입 기능 포함 * - 선택된 셀 정보 실시간 표시 및 시각적 피드백 제공 * - 현재 선택된 셀 정보 상태바 표시 * - AI 프로세서 연동으로 전송하기 버튼 기능 구현 */ const PromptInput: React.FC = ({ value, onChange, onExecute, disabled: _disabled = true, maxLength = 500, onHistoryToggle, historyCount, }) => { const textareaRef = useRef(null); const [, setShowCellInsertFeedback] = useState(false); const [, setLastInsertedCell] = useState(null); const [, setCurrentSelectedCell] = useState(null); const [, setProcessingMessage] = useState(""); const cellAddressToInsert = useAppStore((state) => state.cellAddressToInsert); const setCellAddressToInsert = useAppStore( (state) => state.setCellAddressToInsert, ); const isProcessing = useAppStore((state) => state.isProcessing); /** * 현재 선택된 셀 추적 */ useEffect(() => { if (cellAddressToInsert) { setCurrentSelectedCell(cellAddressToInsert); } }, [cellAddressToInsert]); /** * 전송하기 버튼 클릭 핸들러 - 상위 컴포넌트 onExecute 사용 또는 기본 로직 */ const handleExecute = async () => { if (!value.trim()) { alert("프롬프트를 입력해주세요."); return; } if (isProcessing || aiProcessor.isCurrentlyProcessing()) { alert("이미 처리 중입니다. 잠시 후 다시 시도해주세요."); return; } // 상위 컴포넌트에서 onExecute를 전달받은 경우 해당 함수 사용 if (onExecute) { console.log("🚀 상위 컴포넌트 onExecute 함수 호출"); await onExecute(); return; } // 폴백: 기본 AI 프로세서 직접 호출 setProcessingMessage("AI가 요청을 처리하고 있습니다..."); try { console.log("🚀 전송하기 버튼 클릭 - 프롬프트:", value); // AI 프로세서에 프롬프트 전송 (테스트 모드) const result = await aiProcessor.processPrompt(value, true); console.log("🎉 AI 처리 결과:", result); if (result.success) { setProcessingMessage(`✅ 완료: ${result.message}`); // 성공 시 프롬프트 입력창 초기화 (선택사항) if (onChange && textareaRef.current) { textareaRef.current.value = ""; const syntheticEvent = { target: textareaRef.current, currentTarget: textareaRef.current, } as React.ChangeEvent; onChange(syntheticEvent); } // 3초 후 메시지 숨김 setTimeout(() => { setProcessingMessage(""); }, 3000); } else { setProcessingMessage(`❌ 실패: ${result.message}`); // 에러 메시지는 5초 후 숨김 setTimeout(() => { setProcessingMessage(""); }, 5000); } } catch (error) { console.error("❌ AI 프로세싱 오류:", error); setProcessingMessage("❌ 처리 중 오류가 발생했습니다."); setTimeout(() => { setProcessingMessage(""); }, 5000); } }; /** * 셀 주소 삽입 효과 * cellAddressToInsert가 변경되면 textarea의 현재 커서 위치에 해당 주소를 삽입 */ useEffect(() => { if (cellAddressToInsert && textareaRef.current && onChange) { console.log(`🎯 PromptInput: 셀 주소 "${cellAddressToInsert}" 삽입 시작`); const textarea = textareaRef.current; const start = textarea.selectionStart; const end = textarea.selectionEnd; const currentValue = textarea.value; console.log( `📍 PromptInput: 현재 커서 위치 ${start}-${end}, 현재 값: "${currentValue}"`, ); // 현재 커서 위치에 셀 주소 삽입 const newValue = currentValue.slice(0, start) + cellAddressToInsert + currentValue.slice(end); console.log(`✏️ PromptInput: 새 값: "${newValue}"`); // textarea 값 업데이트 textarea.value = newValue; // 커서 위치를 삽입된 텍스트 뒤로 이동 const newCursorPosition = start + cellAddressToInsert.length; textarea.selectionStart = textarea.selectionEnd = newCursorPosition; // 상위 컴포넌트의 onChange 콜백 호출 (상태 동기화) const syntheticEvent = { target: textarea, currentTarget: textarea, } as React.ChangeEvent; onChange(syntheticEvent); // 포커스를 textarea로 이동 textarea.focus(); // 시각적 피드백 표시 setLastInsertedCell(cellAddressToInsert); setShowCellInsertFeedback(true); // 2초 후 피드백 숨김 setTimeout(() => { setShowCellInsertFeedback(false); }, 2000); console.log(`✅ PromptInput: 셀 주소 "${cellAddressToInsert}" 삽입 완료`); // 셀 주소 삽입 상태 초기화 (중복 삽입 방지) setCellAddressToInsert(null); } }, [cellAddressToInsert, onChange, setCellAddressToInsert]); return (