import React, { useState, useRef, useEffect, useMemo } from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { IconFilter, IconChevronDown, IconNetwork } from '@tabler/icons'; import { updateNetworkFilter, toggleAllNetworkFilters, setSelectedRequest } from 'providers/ReduxStore/slices/logs'; import StyledWrapper from './StyledWrapper'; const MethodBadge = ({ method }) => { const getMethodColor = (method) => { switch (method?.toUpperCase()) { case 'GET': return '#10b981'; case 'POST': return '#8b5cf6'; case 'PUT': return '#f59e0b'; case 'DELETE': return '#ef4444'; case 'PATCH': return '#06b6d4'; case 'HEAD': return '#6b7280'; case 'OPTIONS': return '#84cc16'; default: return '#6b7280'; } }; return ( {method?.toUpperCase() || 'GET'} ); }; const StatusBadge = ({ status, statusCode }) => { const getStatusColor = (code) => { if (code >= 200 && code < 300) return '#10b981'; if (code >= 300 && code < 400) return '#f59e0b'; if (code >= 400 && code < 500) return '#ef4444'; if (code >= 500) return '#dc2626'; return '#6b7280'; }; const displayStatus = statusCode || status; return ( {displayStatus} ); }; const NetworkFilterDropdown = ({ filters, requestCounts, onFilterToggle, onToggleAll }) => { const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); const allFiltersEnabled = Object.values(filters).every((f) => f); const activeFilters = Object.entries(filters).filter(([_, enabled]) => enabled); useEffect(() => { const handleClickOutside = (event) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { setIsOpen(false); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); return (
{isOpen && (
Filter by Method
{Object.keys(filters).map((method) => ( ))}
)}
); }; const RequestRow = ({ request, isSelected, onClick }) => { const { data } = request; const { request: req, response: res, timestamp } = data; const formatTime = (timestamp) => { const date = new Date(timestamp); return date.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }); }; const formatDuration = (duration) => { if (!duration) return '-'; if (duration < 1000) return `${Math.round(duration)}ms`; return `${(duration / 1000).toFixed(2)}s`; }; const formatSize = (size) => { if (!size) return '-'; if (size < 1024) return `${size}B`; if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)}KB`; return `${(size / (1024 * 1024)).toFixed(1)}MB`; }; const getUrl = () => { return req?.url || 'Unknown URL'; }; const getDomain = () => { try { const url = new URL(getUrl()); return url.hostname; } catch { return getUrl(); } }; const getPath = () => { try { const url = new URL(getUrl()); return url.pathname + url.search; } catch { return getUrl(); } }; return (
{getDomain()}
{getPath()}
{formatTime(timestamp)}
{formatDuration(res?.duration)}
{formatSize(res?.size)}
); }; const NetworkTab = () => { const dispatch = useDispatch(); const { networkFilters, selectedRequest } = useSelector((state) => state.logs); const collections = useSelector((state) => state.collections.collections); const allRequests = useMemo(() => { const requests = []; collections.forEach((collection) => { if (collection.timeline) { collection.timeline .filter((entry) => entry.type === 'request') .forEach((entry) => { requests.push({ ...entry, collectionName: collection.name, collectionUid: collection.uid }); }); } }); return requests.sort((a, b) => a.timestamp - b.timestamp); }, [collections]); const filteredRequests = useMemo(() => { return allRequests.filter((request) => { const method = request.data?.request?.method?.toUpperCase() || 'GET'; return networkFilters[method]; }); }, [allRequests, networkFilters]); const requestCounts = useMemo(() => { return allRequests.reduce((counts, request) => { const method = request.data?.request?.method?.toUpperCase() || 'GET'; counts[method] = (counts[method] || 0) + 1; return counts; }, {}); }, [allRequests]); const handleFilterToggle = (method, enabled) => { dispatch(updateNetworkFilter({ method, enabled })); }; const handleToggleAllFilters = (enabled) => { dispatch(toggleAllNetworkFilters(enabled)); }; const handleRequestClick = (request) => { dispatch(setSelectedRequest(request)); }; return (
{filteredRequests.length === 0 ? (

No network requests

Requests will appear here as you make API calls
) : (
Method
Status
Domain
Path
Time
Duration
Size
{filteredRequests.map((request, index) => ( handleRequestClick(request)} /> ))}
)}
); }; export default NetworkTab;