From 827db0a356b0ab4dab352bbb2dbb23f54bd84eac Mon Sep 17 00:00:00 2001 From: snlavaise Date: Wed, 12 Aug 2026 03:22:53 +0000 Subject: [PATCH] feat: Emulador de terminal con cursor para mongosh --- src/sections/SeccionSistema.tsx | 69 ++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/src/sections/SeccionSistema.tsx b/src/sections/SeccionSistema.tsx index 7ce34c9..9cd9202 100644 --- a/src/sections/SeccionSistema.tsx +++ b/src/sections/SeccionSistema.tsx @@ -1,7 +1,7 @@ import { useState, useRef, useEffect } from 'react'; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; -import { Terminal, Download, Upload, FileText, Send, AlertCircle, RefreshCw } from 'lucide-react'; +import { Terminal, Download, Upload, FileText, AlertCircle, RefreshCw } from 'lucide-react'; import { toast } from 'sonner'; export function SeccionSistema() { @@ -12,6 +12,9 @@ export function SeccionSistema() { const [isExecuting, setIsExecuting] = useState(false); const historyCounter = useRef(0); const consoleEndRef = useRef(null); + const inputRef = useRef(null); + const commandHistoryRef = useRef([]); + const historyIndexRef = useRef(-1); const scrollToBottom = () => { consoleEndRef.current?.scrollIntoView({ behavior: 'smooth' }); @@ -19,7 +22,7 @@ export function SeccionSistema() { useEffect(() => { scrollToBottom(); - }, [consoleHistory]); + }, [consoleHistory, mongoshCommand]); const addHistory = (type: 'input' | 'output' | 'error', content: string) => { setConsoleHistory(prev => [...prev, { id: historyCounter.current++, type, content }]); @@ -28,8 +31,14 @@ export function SeccionSistema() { const handleExecuteMongosh = async () => { if (!mongoshCommand.trim()) return; - addHistory('input', mongoshCommand); const commandToRun = mongoshCommand; + addHistory('input', commandToRun); + + if (commandHistoryRef.current[commandHistoryRef.current.length - 1] !== commandToRun) { + commandHistoryRef.current.push(commandToRun); + } + historyIndexRef.current = commandHistoryRef.current.length; + setMongoshCommand(''); setIsExecuting(true); @@ -61,6 +70,23 @@ export function SeccionSistema() { const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { handleExecuteMongosh(); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + if (historyIndexRef.current > 0) { + const newIndex = historyIndexRef.current - 1; + historyIndexRef.current = newIndex; + setMongoshCommand(commandHistoryRef.current[newIndex]); + } + } else if (e.key === 'ArrowDown') { + e.preventDefault(); + if (historyIndexRef.current < commandHistoryRef.current.length - 1) { + const newIndex = historyIndexRef.current + 1; + historyIndexRef.current = newIndex; + setMongoshCommand(commandHistoryRef.current[newIndex]); + } else if (historyIndexRef.current === commandHistoryRef.current.length - 1) { + historyIndexRef.current = commandHistoryRef.current.length; + setMongoshCommand(''); + } } }; @@ -141,39 +167,46 @@ export function SeccionSistema() { -
+
inputRef.current?.focus()} + > {consoleHistory.length === 0 && ( -
Conectado. Esperando comandos... Ej: db.pacientes.find()
+
Conectado. Esperando comandos... Ej: db.pacientes.find()
)} {consoleHistory.map((item) => ( -
+
{item.type === 'input' && {'>'}} {item.type === 'output' && {'<-'}} {item.type === 'error' && {'!'}} -
{item.content}
+
{item.content}
))} -
-
- -
+ +
+ {'>'} + {mongoshCommand} + +
+ +
+ setMongoshCommand(e.target.value)} onKeyDown={handleKeyDown} disabled={isExecuting} + autoComplete="off" + spellCheck="false" /> -
+
- Soporta asincronía. Variables globales: `db`, `ObjectId`. Las promesas se resuelven automáticamente. + Soporta asincronía. Variables globales: `db`, `ObjectId`. Flechas arriba/abajo para navegar el historial.