import React, { useState, useEffect, useRef } from "react"; import QueryInput from "./QueryInput"; import QueryResult from "./QueryResult"; import LoadingResult from "./LoadingResult"; import { querySchema } from "../api"; export default function SchemaQueryView({ selectedDataset, schemaInfo, onQuerySuccess, activeQuestion, addToast }) { const [queryHistory, setQueryHistory] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const historyEndRef = useRef(null); // Suggested questions in JOIN-heavy schema mode const suggestions = [ "Which customers spent the most total?", "Show top 5 products by revenue", "What is the average order value by payment method?", "Which products have the most reviews?", "Show monthly order counts and revenue" ]; // 1. Clear history when selected dataset changes useEffect(() => { setQueryHistory([]); setError(null); setLoading(false); }, [selectedDataset]); // 2. Scroll to bottom when history grows useEffect(() => { if (historyEndRef.current) { historyEndRef.current.scrollIntoView({ behavior: "smooth" }); } }, [queryHistory]); // 3. Register global keyboard shortcut Ctrl+K to focus query input from anywhere useEffect(() => { const handleGlobalKeyDown = (e) => { if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "k") { e.preventDefault(); const inputEl = document.querySelector(".query-input"); if (inputEl) { inputEl.focus(); inputEl.select(); // Highlight any existing text inside } } }; window.addEventListener("keydown", handleGlobalKeyDown); return () => window.removeEventListener("keydown", handleGlobalKeyDown); }, []); // 4. Trigger query from external prop (like sidebar recent queries) useEffect(() => { if (activeQuestion && activeQuestion.text && activeQuestion.timestamp) { handleQuerySubmit(activeQuestion.text); } }, [activeQuestion]); const handleQuerySubmit = async (questionText) => { setError(null); setLoading(true); const pendingId = "pending_" + Date.now(); const pendingEntry = { id: pendingId, question: questionText, timestamp: new Date(), isPending: true }; setQueryHistory((prev) => [...prev, pendingEntry]); try { console.log(`[SchemaQueryView] Executing query: '${questionText}' on '${selectedDataset.db_name}'`); const res = await querySchema(questionText, selectedDataset.db_name); // Update entry with real execution results setQueryHistory((prev) => prev.map((item) => item.id === pendingId ? { ...res, id: pendingId, timestamp: pendingEntry.timestamp } : item ) ); setLoading(false); addToast("Relational query completed", "success"); if (onQuerySuccess) { onQuerySuccess(); } } catch (err) { console.error("[SchemaQueryView] Relational query pipeline error:", err); setError(err.message || "Failed to execute query."); setLoading(false); addToast("Query failed: " + err.message, "error"); // Remove loading block setQueryHistory((prev) => prev.filter((item) => item.id !== pendingId)); } }; const getLastQuestion = () => { if (queryHistory.length === 0) return null; const completedQueries = queryHistory.filter(h => !h.isPending); if (completedQueries.length === 0) return null; return completedQueries[completedQueries.length - 1].question; }; const tablesCount = selectedDataset.total_tables || (selectedDataset.tables ? selectedDataset.tables.length : 0); const relsCount = selectedDataset.relationships ? selectedDataset.relationships.length : 0; return (