import { useState, useEffect, type FC } from 'react'; import { useTranslation } from 'react-i18next'; import { useQuery } from '@tanstack/react-query'; import { useSearchParams } from 'react-router-dom'; import { getLogs, getLogContent, downloadLog, LogFilter } from '../api/logs'; import { FileText, ChevronLeft, ChevronRight, ScrollText } from 'lucide-react'; import { LogTable } from '../components/LogTable'; import { LogFilters } from '../components/LogFilters'; import { PageShell } from '../components/layout/PageShell'; import { Button, Card, Badge, EmptyState, Skeleton, SkeletonList, } from '../components/ui'; const Logs: FC = () => { const { t } = useTranslation(); const [searchParams] = useSearchParams(); const [selectedLog, setSelectedLog] = useState(null); // Filter State const [search, setSearch] = useState(searchParams.get('search') || ''); const [host, setHost] = useState(''); const [status, setStatus] = useState(''); const [level, setLevel] = useState(''); const [sort, setSort] = useState<'asc' | 'desc'>('desc'); const [page, setPage] = useState(0); const limit = 50; const { data: logs, isLoading: isLoadingLogs } = useQuery({ queryKey: ['logs'], queryFn: getLogs, }); // Select first log by default if none selected useEffect(() => { if (!selectedLog && logs && logs.length > 0) { setSelectedLog(logs[0].name); } }, [logs, selectedLog]); const filter: LogFilter = { search, host, status, level, limit, offset: page * limit, sort, }; const { data: logData, isLoading: isLoadingContent, refetch: refetchContent } = useQuery({ queryKey: ['logContent', selectedLog, search, host, status, level, page, sort], queryFn: () => (selectedLog ? getLogContent(selectedLog, filter) : Promise.resolve(null)), enabled: !!selectedLog, }); const handleDownload = () => { if (selectedLog) downloadLog(selectedLog); }; const totalPages = logData ? Math.ceil(logData.total / limit) : 0; return (
{/* Log File List */}

{t('logs.logFiles')}

{isLoadingLogs ? ( ) : logs?.length === 0 ? (
{t('logs.noLogFiles')}
) : (
{logs?.map((log) => ( ))}
)}
{/* Log Content */}
{selectedLog ? ( <> { setSearch(v); setPage(0); }} host={host} onHostChange={(v) => { setHost(v); setPage(0); }} status={status} onStatusChange={(v) => { setStatus(v); setPage(0); }} level={level} onLevelChange={(v) => { setLevel(v); setPage(0); }} sort={sort} onSortChange={(v) => { setSort(v); setPage(0); }} onRefresh={refetchContent} onDownload={handleDownload} isLoading={isLoadingContent} /> {isLoadingContent ? (
{Array.from({ length: 10 }).map((_, i) => ( ))}
) : (
)} {/* Pagination */} {logData && logData.total > 0 && (
{t('logs.showingEntries', { from: logData.offset + 1, to: Math.min(logData.offset + limit, logData.total), total: logData.total })}
{t('logs.pageOf', { current: page + 1, total: totalPages })}
)}
) : ( } title={t('logs.noLogSelected')} description={t('logs.selectLogDescription')} /> )}
); }; export default Logs;