-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLiveTerminal.js
More file actions
88 lines (80 loc) · 4.65 KB
/
LiveTerminal.js
File metadata and controls
88 lines (80 loc) · 4.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
'use client'
import { useState, useEffect, useRef } from "react"
import styles from "./LiveTerminal.module.css"
const COMMANDS = [
{ cmd: "ghz@cluster:~$ vercel list", output: "Projetos ativos: ghzhost-website, ghzhost-future-deploy, nqpb, view-transitions, _redirects" },
{ cmd: "ghz@cluster:~$ kubectl get pods --all-namespaces", output: "NAMESPACE NAME READY STATUS RESTARTS AGE\n default compute-br1-7f9c2 1/1 Running 0 12d\n default storage-br2-6d8e1 1/1 Running 0 12d\n default network-br3-4a5f3 1/1 Running 0 12d\n default cdn-edge-9b3f7 2/2 Running 0 12d" },
{ cmd: "ghz@cluster:~$ docker ps --format 'table {{.ID}} {{.Image}} {{.Status}}'", output: "CONTAINER ID IMAGE STATUS\n a1b2c3d4e5f6 ghzhost/cloud-vps:latest Up 12 days\n b2c3d4e5f6a7 ghzhost/storage-node:latest Up 12 days\n c3d4e5f6a7b8 ghzhost/game-srv:latest Up 12 days\n d4e5f6a7b8c9 ghzhost/cdn-edge:latest Up 12 days" },
{ cmd: "ghz@cluster:~$ uptime", output: "02:03:40 up 8 days, 21:28, 14 users, load average: 9.40, 10.06, 11.35" },
{ cmd: "ghz@cluster:~$ df -h /data", output: "Filesystem Size Used Avail Use% Mounted on\n /dev/sda1 2.0T 1.2T 800G 60% /data" },
{ cmd: "ghz@cluster:~$ free -h", output: "total used free shared buff/cache available\n Mem: 64Gi 42Gi 8Gi 2Gi 12Gi 18Gi\n Swap: 8Gi 1.2Gi 6.8Gi" },
{ cmd: "ghz@cluster:~$ curl -s https://api.vercel.com/v9/projects | jq '.projects[].name'", output: "\"ghzhost-website\"\n\"ghzhost-future-deploy\"\n\"nqpb\"\n\"view-transitions\"\n\"_redirects\"\n\"puppeteer-vercel\"" },
{ cmd: "ghz@cluster:~$ ping -c 1 br2.ghzhost.com", output: "PING br2.ghzhost.com (100.91.206.111) 56(84) bytes of data.\n64 bytes from 100.91.206.111: icmp_seq=1 ttl=64 time=2.34ms\n--- br2.ghzhost.com ping statistics ---\n1 packets transmitted, 1 received, 0% packet loss" },
{ cmd: "ghz@cluster:~$ systemctl status --no-pager", output: "● ghzhost-compute.service — GhzHost Compute Node\n Loaded: loaded (/etc/systemd/system/ghzhost-compute.service; enabled;)\n Active: active (running) since Mon 2026-05-19 04:35:12 UTC\n Main PID: 1247 (node)\n Tasks: 23 (limit: 49148)\n Memory: 1.2G\n CPU: 12h 34m 56s" },
{ cmd: "ghz@cluster:~$ netstat -tulpn | grep LISTEN", output: "tcp 0 0.0.0.0:22 0.0.0.0:* LISTEN 1024/sshd\n tcp 0 0.0.0.0:80 0.0.0.0:* LISTEN 1247/nginx\n tcp 0 0.0.0.0:443 0.0.0.0:* LISTEN 1247/nginx\n tcp 0 127.0.0.1:3000 0.0.0.0:* LISTEN 1247/node" },
]
export default function LiveTerminal() {
const [currentIndex, setCurrentIndex] = useState(0)
const [visibleLines, setVisibleLines] = useState([])
const [isTyping, setIsTyping] = useState(false)
const terminalRef = useRef(null)
useEffect(() => {
const cmd = COMMANDS[currentIndex]
setIsTyping(true)
setVisibleLines([])
let lineIndex = 0
const lines = cmd.output.split("\n")
const typeLine = () => {
if (lineIndex < lines.length) {
setVisibleLines((prev) => [...prev, lines[lineIndex]])
lineIndex++
setTimeout(typeLine, 80 + Math.random() * 120)
} else {
setIsTyping(false)
setTimeout(() => {
setCurrentIndex((prev) => (prev + 1) % COMMANDS.length)
}, 3000)
}
}
const timer = setTimeout(typeLine, 500)
return () => clearTimeout(timer)
}, [currentIndex])
useEffect(() => {
if (terminalRef.current) {
terminalRef.current.scrollTop = terminalRef.current.scrollHeight
}
}, [visibleLines])
return (
<div className={styles.wrapper}>
<div className={styles.terminal} ref={terminalRef}>
<div className={styles.header}>
<div className={styles.dots}>
<span className={`${styles.dot} ${styles.red}`} />
<span className={`${styles.dot} ${styles.yellow}`} />
<span className={`${styles.dot} ${styles.green}`} />
</div>
<span className={styles.title}>ghz@cluster:~ — Terminal Interativo</span>
<span className={styles.status}>
<span className={styles.pulseSmall} />
ONLINE
</span>
</div>
<div className={styles.body}>
<div className={styles.line}>
<span className={styles.prompt}>ghz@cluster:~$</span>
<span className={styles.command}>{COMMANDS[currentIndex].cmd.replace("ghz@cluster:~$ ", "")}</span>
<span className={styles.cursor}>▊</span>
</div>
{visibleLines.map((line, i) => (
<div key={i} className={styles.output}>
{line}
</div>
))}
{!isTyping && (
<div className={styles.blink}>_</div>
)}
</div>
</div>
</div>
)
}