import React, { useState, useEffect } from 'react'; import Layout from '../components/Layout'; import { fredApi, FredUsageStats, FredSeriesData, FredObservationsData } from '../lib/api'; interface QuotaDisplayProps { stats: FredUsageStats; isLoading: boolean; } const QuotaDisplay: React.FC = ({ stats, isLoading }) => { if (isLoading) { return (
); } const getQuotaColor = (percentage: number) => { if (percentage < 50) return 'bg-green-500'; if (percentage < 80) return 'bg-yellow-500'; return 'bg-red-500'; }; const getQuotaTextColor = (percentage: number) => { if (percentage < 50) return 'text-green-600'; if (percentage < 80) return 'text-yellow-600'; return 'text-red-600'; }; return (

📊 FRED API Daily Quota

Used Today
{stats.used_today}
Remaining
{stats.remaining_today}
Daily Limit
{stats.daily_limit}
Usage %
{stats.usage_percentage.toFixed(1)}%
{/* Progress Bar */}
API Usage Progress {stats.used_today} / {stats.daily_limit}
{/* Status */}
{stats.can_make_requests ? 'API Available' : 'Daily Limit Reached'}
); }; interface CacheStatsProps { stats: FredUsageStats; } const CacheStats: React.FC = ({ stats }) => { return (

💾 Database Cache Statistics

Cached Series
{stats.cache_stats.cached_series.toLocaleString()}
Economic data series
Cached Observations
{stats.cache_stats.cached_observations.toLocaleString()}
Historical data points
Cache Duration
{stats.cache_stats.cache_duration_hours}h
Auto-refresh period

🔧 Proxy Information

Mode: {stats.proxy_info.mode}
Smart Caching: {stats.proxy_info.smart_caching ? 'Enabled' : 'Disabled'}
Permanent Storage: {stats.proxy_info.permanent_storage ? 'Yes' : 'No'}
Supported Endpoints: {stats.proxy_info.supported_endpoints}
); }; interface EndpointStatsProps { stats: FredUsageStats; } const EndpointStats: React.FC = ({ stats }) => { const topEndpoints = stats.endpoint_stats.slice(0, 10); return (

🔥 Most Used Endpoints

{topEndpoints.length > 0 ? (
{topEndpoints.map((endpoint, index) => (
{index + 1}
{endpoint.endpoint}
{endpoint.call_count}
calls
))}
) : (
No endpoint usage data available
)}
); }; interface PopularSeriesProps { series: FredSeriesData[]; isLoading: boolean; onSelectSeries: (seriesId: string) => void; } const PopularSeries: React.FC = ({ series, isLoading, onSelectSeries }) => { if (isLoading) { return (

📈 Popular Economic Indicators

{[...Array(5)].map((_, i) => (
))}
); } return (

📈 Popular Economic Indicators

{series.map((seriesData) => ( ))}
); }; interface SeriesSearchProps { onSelectSeries: (seriesId: string) => void; } const SeriesSearch: React.FC = ({ onSelectSeries }) => { const [searchTerm, setSearchTerm] = useState(''); const [searchResults, setSearchResults] = useState([]); const [isSearching, setIsSearching] = useState(false); const handleSearch = async () => { if (!searchTerm.trim()) return; setIsSearching(true); try { const results = await fredApi.searchSeries(searchTerm, 15); setSearchResults(results); } catch (error) { console.error('Search failed:', error); setSearchResults([]); } finally { setIsSearching(false); } }; const handleKeyPress = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { handleSearch(); } }; return (

🔍 Search Economic Data

setSearchTerm(e.target.value)} onKeyPress={handleKeyPress} placeholder="Search for economic indicators (e.g., unemployment, inflation, GDP)" className="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" />
{searchResults.length > 0 && (
{searchResults.map((seriesData) => ( ))}
)} {searchTerm && searchResults.length === 0 && !isSearching && (
No results found for "{searchTerm}"
)}
); }; interface SeriesDataDisplayProps { seriesId: string; observations: FredObservationsData | null; isLoading: boolean; onClose: () => void; } const SeriesDataDisplay: React.FC = ({ seriesId, observations, isLoading, onClose }) => { if (isLoading) { return (
{[...Array(10)].map((_, i) => (
))}
); } if (!observations) return null; return (

📊 {seriesId} {observations.cached && ( From Cache )}

{observations.count} observations • Last 20 shown {observations.cached_at && ( • Cached: {new Date(observations.cached_at).toLocaleString()} )}
{observations.observations.slice(0, 20).map((obs, index) => ( ))}
Date Value
{obs.date} {obs.value === '.' ? 'N/A' : parseFloat(obs.value).toLocaleString()}
); }; const FredPage: React.FC = () => { const [stats, setStats] = useState(null); const [popularSeries, setPopularSeries] = useState([]); const [selectedSeriesId, setSelectedSeriesId] = useState(null); const [seriesObservations, setSeriesObservations] = useState(null); const [isLoadingStats, setIsLoadingStats] = useState(true); const [isLoadingPopular, setIsLoadingPopular] = useState(true); const [isLoadingObservations, setIsLoadingObservations] = useState(false); // Load initial data useEffect(() => { const loadInitialData = async () => { try { // Load usage stats const statsData = await fredApi.getUsageStats(7, true); setStats(statsData); setIsLoadingStats(false); // Load popular series const popularData = await fredApi.getPopularSeries(); setPopularSeries(popularData); setIsLoadingPopular(false); } catch (error) { console.error('Failed to load initial data:', error); setIsLoadingStats(false); setIsLoadingPopular(false); } }; loadInitialData(); }, []); // Load series observations when selected const handleSelectSeries = async (seriesId: string) => { setSelectedSeriesId(seriesId); setIsLoadingObservations(true); try { const observationsData = await fredApi.getSeriesObservations(seriesId, 50); setSeriesObservations(observationsData); } catch (error) { console.error('Failed to load series observations:', error); setSeriesObservations(null); } finally { setIsLoadingObservations(false); } }; const handleCloseSeriesData = () => { setSelectedSeriesId(null); setSeriesObservations(null); }; return (

🏦 FRED Economic Data

Federal Reserve Economic Data (FRED) API Access
{/* Quota Display */} {stats && }
{/* Left Column */}
{/* Popular Series */} {/* Search */}
{/* Right Column */}
{/* Cache Stats */} {stats && } {/* Endpoint Stats */} {stats && }
{/* Series Data Display */} {selectedSeriesId && ( )}
); }; export default FredPage;