Spaces:
Paused
Paused
| "use client"; | |
| import { useState, useRef, useEffect } from "react"; | |
| type TerminalLine = { | |
| type: "user" | "system" | "error"; | |
| text: string; | |
| }; | |
| export default function Terminal() { | |
| const [history, setHistory] = useState<TerminalLine[]>([ | |
| { type: "system", text: "Next.js Terminal [v1.0.0]" }, | |
| { type: "system", text: "Connected to Hugging Face Docker Space..." }, | |
| { type: "system", text: "Type 'ls' to see files or 'python3 scripts/logic.py' to run logic." } | |
| ]); | |
| const [input, setInput] = useState(""); | |
| const [loading, setLoading] = useState(false); | |
| const scrollRef = useRef<HTMLDivElement>(null); | |
| // Auto-scroll to bottom when history changes | |
| useEffect(() => { | |
| if (scrollRef.current) { | |
| scrollRef.current.scrollTop = scrollRef.current.scrollHeight; | |
| } | |
| }, [history]); | |
| const executeCommand = async (e: React.FormEvent) => { | |
| e.preventDefault(); | |
| if (!input.trim()) return; | |
| const cmd = input; | |
| setInput(""); | |
| setLoading(true); | |
| // Add user command to history | |
| setHistory((prev) => [...prev, { type: "user", text: `> ${cmd}` }]); | |
| try { | |
| const res = await fetch("/api/run", { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ command: cmd }), | |
| }); | |
| const data = await res.json(); | |
| setHistory((prev) => [ | |
| ...prev, | |
| { type: data.type === "error" ? "error" : "system", text: data.output } | |
| ]); | |
| } catch (err) { | |
| setHistory((prev) => [...prev, { type: "error", text: "Failed to connect to API" }]); | |
| } | |
| setLoading(false); | |
| }; | |
| return ( | |
| <div style={{ | |
| backgroundColor: "#0d1117", | |
| color: "#00ff00", | |
| height: "100vh", | |
| padding: "20px", | |
| fontFamily: "Courier New, monospace", | |
| display: "flex", | |
| flexDirection: "column" | |
| }}> | |
| {/* Output Area */} | |
| <div | |
| ref={scrollRef} | |
| style={{ flex: 1, overflowY: "auto", whiteSpace: "pre-wrap", marginBottom: "10px" }} | |
| > | |
| {history.map((line, i) => ( | |
| <div key={i} style={{ | |
| color: line.type === "user" ? "white" : line.type === "error" ? "red" : "#00ff00", | |
| marginBottom: "4px" | |
| }}> | |
| {line.text} | |
| </div> | |
| ))} | |
| {loading && <div style={{ color: "yellow" }}>Running...</div>} | |
| </div> | |
| {/* Input Area */} | |
| <form onSubmit={executeCommand} style={{ display: "flex", borderTop: "1px solid #333", paddingTop: "10px" }}> | |
| <span style={{ color: "#00ff00", marginRight: "10px" }}>$</span> | |
| <input | |
| autoFocus | |
| type="text" | |
| value={input} | |
| onChange={(e) => setInput(e.target.value)} | |
| placeholder="Enter shell command..." | |
| style={{ | |
| flex: 1, | |
| background: "transparent", | |
| border: "none", | |
| color: "white", | |
| outline: "none", | |
| fontFamily: "inherit" | |
| }} | |
| /> | |
| </form> | |
| </div> | |
| ); | |
| } |