/** * Live Terminal Component Template * * Features: * - Auto-scrolling log feed * - Color-coded log levels * - Timestamp display * - Customizable appearance */ import React, { useState, useEffect, useRef } from 'react'; import { Terminal as TerminalIcon } from 'lucide-react'; // ============================================ // TYPES // ============================================ export interface LogEntry { id: string; timestamp: string; level: 'INFO' | 'WARN' | 'ERROR' | 'DEBUG' | 'SEC' | 'SYS'; message: string; } export interface TerminalProps { // Appearance height?: string; accentColor?: string; showHeader?: boolean; title?: string; // Behavior maxLogs?: number; autoScroll?: boolean; // Data logs?: LogEntry[]; logTemplates?: Omit[]; updateInterval?: number; // ms, only used with templates } // ============================================ // DEFAULT LOG TEMPLATES // ============================================ const DEFAULT_LOG_TEMPLATES: Omit[] = [ { level: 'SYS', message: 'System health check: OK' }, { level: 'INFO', message: 'Request processed in 3.2ms' }, { level: 'WARN', message: 'Memory usage approaching threshold' }, { level: 'DEBUG', message: 'Cache invalidation complete' }, { level: 'SEC', message: 'Authentication token refreshed' }, { level: 'INFO', message: 'Database connection pool: 12/20' }, { level: 'SYS', message: 'Garbage collection: 8ms pause' }, { level: 'WARN', message: 'Rate limit approaching for API key' }, ]; // ============================================ // LEVEL COLORS // ============================================ const LEVEL_COLORS: Record = { INFO: 'text-cyan-400', WARN: 'text-yellow-400', ERROR: 'text-red-400', DEBUG: 'text-zinc-500', SEC: 'text-orange-400', SYS: 'text-purple-400', }; // ============================================ // TERMINAL HOOK // ============================================ export const useTerminal = ( templates: Omit[] = DEFAULT_LOG_TEMPLATES, interval: number = 1500, maxLogs: number = 50 ) => { const [logs, setLogs] = useState([]); useEffect(() => { const timer = setInterval(() => { const template = templates[Math.floor(Math.random() * templates.length)]; const newLog: LogEntry = { id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, timestamp: new Date().toISOString().split('T')[1].split('.')[0], ...template, }; setLogs(prev => [...prev.slice(-maxLogs + 1), newLog]); }, interval); return () => clearInterval(timer); }, [templates, interval, maxLogs]); return logs; }; // ============================================ // TERMINAL COMPONENT // ============================================ export const Terminal: React.FC = ({ height = 'h-72', accentColor = '#ff4d00', showHeader = true, title = 'System Logs', maxLogs = 50, autoScroll = true, logs: externalLogs, logTemplates = DEFAULT_LOG_TEMPLATES, updateInterval = 1500, }) => { const scrollRef = useRef(null); const internalLogs = useTerminal(logTemplates, updateInterval, maxLogs); // Use external logs if provided, otherwise use internal const logs = externalLogs ?? internalLogs; // Auto-scroll to bottom useEffect(() => { if (autoScroll && scrollRef.current) { scrollRef.current.scrollTop = scrollRef.current.scrollHeight; } }, [logs, autoScroll]); return (
{/* Header */} {showHeader && (
{title}
LIVE
)} {/* Log content */}
{logs.map(log => (
{log.timestamp} [{log.level}] {log.message}
))} {/* Cursor blink */}
>
); }; // ============================================ // COMPACT TERMINAL (for dashboards) // ============================================ export const CompactTerminal: React.FC<{ logs: LogEntry[]; maxVisible?: number; }> = ({ logs, maxVisible = 5 }) => { const visibleLogs = logs.slice(-maxVisible); return (
{visibleLogs.map(log => (
[{log.level}] {log.message}
))}
); }; export default Terminal;