'use client'; import { useEffect, useRef, useState } from 'react'; import { Card, CardContent } from '@/components/ui/card'; import { cn } from '@/lib/utils/cn'; interface LogViewerProps { logs: string; isLoading?: boolean; autoScroll?: boolean; searchTerm?: string; } export function LogViewer({ logs, isLoading, autoScroll = true, searchTerm = '' }: LogViewerProps) { const scrollRef = useRef(null); const [userHasScrolled, setUserHasScrolled] = useState(false); // Auto-scroll to bottom when logs update (if enabled and user hasn't manually scrolled) useEffect(() => { if (autoScroll && !userHasScrolled && scrollRef.current) { scrollRef.current.scrollTop = scrollRef.current.scrollHeight; } }, [logs, autoScroll, userHasScrolled]); // Detect user scroll const handleScroll = () => { if (!scrollRef.current) return; const { scrollTop, scrollHeight, clientHeight } = scrollRef.current; const isAtBottom = Math.abs(scrollHeight - clientHeight - scrollTop) < 10; setUserHasScrolled(!isAtBottom); }; // Highlight search term const highlightSearchTerm = (text: string) => { if (!searchTerm) return text; const regex = new RegExp(`(${searchTerm})`, 'gi'); const parts = text.split(regex); return parts.map((part, i) => regex.test(part) ? ( {part} ) : ( part ) ); }; // Syntax highlighting for log levels const formatLogLine = (line: string, index: number) => { const errorRegex = /(ERROR|FATAL|CRITICAL)/i; const warnRegex = /(WARN|WARNING)/i; const infoRegex = /(INFO|DEBUG)/i; let className = ''; if (errorRegex.test(line)) { className = 'text-destructive'; } else if (warnRegex.test(line)) { className = 'text-warning'; } else if (infoRegex.test(line)) { className = 'text-accent'; } return (
{highlightSearchTerm(line)}
); }; const logLines = logs.split('\n').filter((line) => { if (!searchTerm) return true; return line.toLowerCase().includes(searchTerm.toLowerCase()); }); return (
{isLoading ? (
) : logLines.length === 0 ? (
{searchTerm ? 'No logs matching search term' : 'No logs available'}
) : (
{logLines.map((line, index) => formatLogLine(line, index))}
)} {!autoScroll && userHasScrolled && ( )}
); }