dashboard / index.html
virtualpixelz's picture
fix button - Initial Deployment
e8c36e9 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FRED Dashboard | Economic Data Visualization</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- NFP Model Section -->
<div id="nfp-model" class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div class="bg-white rounded-xl shadow-md p-5 mb-8">
<h2 class="text-2xl font-bold text-gray-900 mb-6">Advanced NFP Prediction Model</h2>
<div class="flex flex-wrap gap-3 mb-6">
<button
id="regression-tab"
class="flex items-center bg-fred-blue text-white rounded-lg px-4 py-2 text-sm font-medium hover:bg-fred-dark-blue"
>
Regression Analysis
</button>
<button
id="rolling-tab"
class="flex items-center bg-gray-200 text-gray-700 rounded-lg px-4 py-2 text-sm font-medium hover:bg-gray-300"
>
Rolling Window Forecast
</button>
</div>
<div id="regression-content" class="space-y-6">
<!-- Content will be dynamically populated by JavaScript -->
</div>
<div id="rolling-content" class="space-y-6 hidden">
<!-- Content will be dynamically populated by JavaScript -->
</div>
</div>
</div>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script src="https://unpkg.com/recharts@2.1.16/umd/Recharts.js"></script>
<script>
// Initialize NFP Model
const { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } = Recharts;
// Simplified version of the AdvancedNFPModel component
function AdvancedNFPModel() {
const [activeTab, setActiveTab] = React.useState('regression');
const [windowSize, setWindowSize] = React.useState(24);
// ... rest of the component code from your model ...
return (
<div className="space-y-6">
<div className="flex flex-wrap gap-3 mb-6">
<button
onClick={() => setActiveTab('regression')}
className={`flex items-center rounded-lg px-4 py-2 text-sm font-medium ${
activeTab === 'regression'
? 'bg-fred-blue text-white hover:bg-fred-dark-blue'
: 'bg-gray-200 text-gray-700 hover:bg-gray-300'
}`}
>
Regression Analysis
</button>
<button
onClick={() => setActiveTab('rolling')}
className={`flex items-center rounded-lg px-4 py-2 text-sm font-medium ${
activeTab === 'rolling'
? 'bg-fred-blue text-white hover:bg-fred-dark-blue'
: 'bg-gray-200 text-gray-700 hover:bg-gray-300'
}`}
>
Rolling Window Forecast
</button>
</div>
{activeTab === 'regression' ? renderRegressionAnalysis() : renderRollingWindow()}
</div>
);
}
// Mount the React component
const root = ReactDOM.createRoot(document.getElementById('nfp-model'));
root.render(<AdvancedNFPModel />);
// Remove login-related JavaScript
tailwind.config = {
theme: {
extend: {
colors: {
'fred-blue': '#2563eb',
'fred-dark-blue': '#1e40af',
'fred-accent': '#f97316'
}
}
}
}
</script>
<style>
.chart-card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
transition: all 0.3s ease;
}
.grid-stack {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
}
.tooltip {
position: absolute;
background-color: rgba(0,0,0,0.85);
color: white;
padding: 8px 12px;
border-radius: 4px;
font-size: 12px;
pointer-events: none;
z-index: 100;
}
.kpi-card {
transition: all 0.2s ease;
}
.kpi-card:hover {
transform: scale(1.05);
}
.dropdown-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
.dropdown-content.show {
max-height: 300px;
}
</style>
</head>
<body class="bg-gray-100">
<!-- Main Dashboard -->
<div id="dashboard" class="min-h-screen">
<!-- Header -->
<header class="bg-white shadow-md">
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-4">
<div class="flex items-center justify-between">
<div class="flex items-center">
<div class="bg-gray-200 border-2 border-dashed rounded-xl w-10 h-10 flex items-center justify-center text-blue-600">
<i class="fas fa-chart-line"></i>
</div>
<span class="ml-3 text-xl font-bold text-gray-800">FRED Dashboard</span>
<div class="ml-8 hidden md:block">
<nav class="flex space-x-8">
<a href="#" class="text-fred-blue font-medium border-b-2 border-fred-blue pb-2">Summary</a>
<a href="#" class="text-gray-500 hover:text-gray-700 font-medium pb-2">Markets</a>
<a href="#" class="text-gray-500 hover:text-gray-700 font-medium pb-2">Employment</a>
<a href="#" class="text-gray-500 hover:text-gray-700 font-medium pb-2">Inflation</a>
</nav>
</div>
</div>
<div class="flex items-center space-x-4">
<div class="relative">
<button class="p-2 rounded-full hover:bg-gray-100 focus:outline-none">
<i class="far fa-bell text-gray-600"></i>
<span class="absolute top-0 right-0 w-2 h-2 bg-red-500 rounded-full"></span>
</button>
</div>
<div class="relative group">
<button id="user-menu" class="flex items-center text-sm focus:outline-none">
<img class="h-8 w-8 rounded-full object-cover" src="https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=64&h=64&q=80" alt="User profile">
<span class="ml-2 text-gray-700 font-medium hidden md:block">John D.</span>
<i class="fas fa-chevron-down ml-1 text-gray-500 text-xs"></i>
</button>
<div class="absolute right-0 mt-2 w-48 origin-top-right bg-white rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 hidden group-hover:block py-1 z-20">
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Your Profile</a>
<a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Settings</a>
<button id="logout-btn" class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Sign out</button>
</div>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- Dashboard Title and Controls -->
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-8">
<div>
<h1 class="text-2xl font-bold text-gray-900">Economic Dashboard</h1>
<p class="mt-1 text-sm text-gray-600">Real-time FRED data analysis and visualization</p>
</div>
<div class="mt-4 md:mt-0 flex flex-wrap gap-3">
<div class="relative">
<button id="date-filter-btn" class="flex items-center bg-white border border-gray-300 rounded-lg shadow-sm px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<i class="far fa-calendar mr-2 text-gray-500"></i>
Last 12 Months
<i class="fas fa-chevron-down ml-2 text-xs"></i>
</button>
<div id="date-options" class="dropdown-content absolute right-0 mt-1 w-56 origin-top-right bg-white rounded-md shadow-lg ring-1 ring-black ring-opacity-5 z-10">
<div class="py-1">
<button data-range="6" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 w-full text-left">Last 6 Months</button>
<button data-range="12" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 w-full text-left">Last 12 Months</button>
<button data-range="24" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 w-full text-left">Last 2 Years</button>
<button data-range="60" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 w-full text-left">Last 5 Years</button>
</div>
</div>
</div>
<button id="refresh-data-btn" class="flex items-center bg-white border border-gray-300 rounded-lg shadow-sm px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50">
<i class="fas fa-sync-alt mr-2 text-gray-500"></i>
Refresh Data
</button>
</div>
</div>
<!-- KPI Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<!-- GDP Growth -->
<div class="kpi-card bg-white rounded-xl shadow-md p-5 border-t-4 border-fred-blue">
<div class="flex justify-between items-start">
<div class="flex-1">
<div class="text-xs font-medium text-gray-500 uppercase tracking-wide">Real GDP Growth</div>
<div class="mt-1 flex items-baseline">
<div class="text-2xl font-bold text-gray-900">2.1%</div>
<div class="ml-2 text-sm font-medium text-green-600">
<span class="mr-1"><i class="fas fa-caret-up"></i></span>0.3%
</div>
</div>
</div>
<div class="bg-blue-100 p-2 rounded-lg">
<i class="fas fa-dollar-sign text-fred-blue"></i>
</div>
</div>
<div class="mt-4">
<div class="text-xs text-gray-500">Last Updated: <span>Sep 2023</span></div>
</div>
</div>
<!-- Unemployment Rate -->
<div class="kpi-card bg-white rounded-xl shadow-md p-5 border-t-4 border-amber-500">
<div class="flex justify-between items-start">
<div class="flex-1">
<div class="text-xs font-medium text-gray-500 uppercase tracking-wide">Unemployment Rate</div>
<div class="mt-1 flex items-baseline">
<div class="text-2xl font-bold text-gray-900">3.8%</div>
<div class="ml-2 text-sm font-medium text-red-600">
<span class="mr-1"><i class="fas fa-caret-down"></i></span>0.2%
</div>
</div>
</div>
<div class="bg-amber-100 p-2 rounded-lg">
<i class="fas fa-user-tie text-amber-500"></i>
</div>
</div>
<div class="mt-4">
<div class="text-xs text-gray-500">Last Updated: <span>Oct 2023</span></div>
</div>
</div>
<!-- Inflation Rate -->
<div class="kpi-card bg-white rounded-xl shadow-md p-5 border-t-4 border-pink-500">
<div class="flex justify-between items-start">
<div class="flex-1">
<div class="text-xs font-medium text-gray-500 uppercase tracking-wide">CPI Inflation</div>
<div class="mt-1 flex items-baseline">
<div class="text-2xl font-bold text-gray-900">3.2%</div>
<div class="ml-2 text-sm font-medium text-green-600">
<span class="mr-1"><i class="fas fa-caret-up"></i></span>1.0%
</div>
</div>
</div>
<div class="bg-pink-100 p-2 rounded-lg">
<i class="fas fa-chart-line text-pink-500"></i>
</div>
</div>
<div class="mt-4">
<div class="text-xs text-gray-500">Last Updated: <span>Oct 2023</span></div>
</div>
</div>
<!-- Interest Rate -->
<div class="kpi-card bg-white rounded-xl shadow-md p-5 border-t-4 border-purple-500">
<div class="flex justify-between items-start">
<div class="flex-1">
<div class="text-xs font-medium text-gray-500 uppercase tracking-wide">Fed Funds Rate</div>
<div class="mt-1 flex items-baseline">
<div class="text-2xl font-bold text-gray-900">5.33%</div>
<div class="ml-2 text-sm font-medium text-green-600">
<span class="mr-1"><i class="fas fa-pause"></i></span>unch
</div>
</div>
</div>
<div class="bg-purple-100 p-2 rounded-lg">
<i class="fas fa-percentage text-purple-500"></i>
</div>
</div>
<div class="mt-4">
<div class="text-xs text-gray-500">Last Updated: <span>Nov 2023</span></div>
</div>
</div>
</div>
<!-- Charts Grid -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
<!-- GDP Chart -->
<div class="chart-card bg-white rounded-xl shadow-md p-5">
<div class="flex justify-between items-center mb-4">
<h2 class="text-lg font-semibold text-gray-800">GDP Growth Trends</h2>
<button class="text-gray-500 hover:text-fred-blue">
<i class="fas fa-expand-alt"></i>
</button>
</div>
<div class="chart-container relative" style="height: 300px;">
<canvas id="gdp-chart"></canvas>
</div>
</div>
<!-- Inflation Chart -->
<div class="chart-card bg-white rounded-xl shadow-md p-5">
<div class="flex justify-between items-center mb-4">
<h2 class="text-lg font-semibold text-gray-800">Inflation Comparison</h2>
<button class="text-gray-500 hover:text-fred-blue">
<i class="fas fa-expand-alt"></i>
</button>
</div>
<div class="chart-container relative" style="height: 300px;">
<canvas id="inflation-chart"></canvas>
</div>
</div>
<!-- Unemployment Chart -->
<div class="chart-card bg-white rounded-xl shadow-md p-5">
<div class="flex justify-between items-center mb-4">
<h2 class="text-lg font-semibold text-gray-800">Unemployment Rate</h2>
<button class="text-gray-500 hover:text-fred-blue">
<i class="fas fa-expand-alt"></i>
</button>
</div>
<div class="chart-container relative" style="height: 300px;">
<canvas id="unemployment-chart"></canvas>
</div>
</div>
<!-- Market Index Chart -->
<div class="chart-card bg-white rounded-xl shadow-md p-5">
<div class="flex justify-between items-center mb-4">
<h2 class="text-lg font-semibold text-gray-800">Market Performance</h2>
<div class="flex">
<button class="text-gray-500 hover:text-fred-blue ml-3">
<i class="fas fa-expand-alt"></i>
</button>
</div>
</div>
<div class="chart-container relative" style="height: 300px;">
<canvas id="market-chart"></canvas>
</div>
</div>
</div>
<!-- AI Economic Analysis -->
<div class="bg-white rounded-xl shadow-md p-5 mb-8">
<div class="flex justify-between items-center mb-4">
<h2 class="text-lg font-semibold text-gray-800">AI Economic Analysis</h2>
<button id="ask-ai-btn" class="flex items-center bg-fred-blue text-white rounded-lg px-4 py-2 text-sm font-medium hover:bg-fred-dark-blue">
<i class="fas fa-robot mr-2"></i>
Ask AI
</button>
</div>
<div id="ai-analysis-container" class="bg-gray-50 rounded-lg p-4 min-h-32">
<p class="text-gray-500 text-sm">AI analysis will appear here...</p>
</div>
</div>
<!-- Economy Overview -->
<div class="bg-white rounded-xl shadow-md p-5 mb-8">
<h2 class="text-lg font-semibold text-gray-800 mb-4">Economic Indicators</h2>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Indicator</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Period</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Value</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Change</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Trend</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Data Source</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Industrial Production</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Oct 2023</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">102.8</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-green-600">+0.3%</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<i class="fas fa-caret-up text-green-600 mr-1"></i>
<div class="h-2 w-10 bg-green-200 rounded-full">
<div class="h-2 bg-green-600 rounded-full" style="width:60%"></div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
FRED: INDPRO
</td>
</tr>
<tr class="bg-gray-50">
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Retail Sales</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Oct 2023</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">$704.9B</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-green-600">+0.8%</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<i class="fas fa-caret-up text-green-600 mr-1"></i>
<div class="h-2 w-10 bg-green-200 rounded-full">
<div class="h-2 bg-green-600 rounded-full" style="width:80%"></div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
FRED: RSXFS
</td>
</tr>
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Consumer Confidence</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Nov 2023</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">102.0</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-red-600">-2.5%</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<i class="fas fa-caret-down text-red-600 mr-1"></i>
<div class="h-2 w-10 bg-red-200 rounded-full">
<div class="h-2 bg-red-600 rounded-full" style="width:40%"></div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
Conference Board
</td>
</tr>
</tbody>
</table>
</div>
</div>
</main>
<!-- Footer -->
<footer class="bg-gray-800 text-white py-8">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="flex items-center mb-6 md:mb-0">
<div class="bg-gray-200 border-2 border-dashed rounded-xl w-8 h-8 flex items-center justify-center">
<i class="fas fa-chart-line text-fred-blue"></i>
</div>
<span class="ml-3 text-lg font-bold">FRED Dashboard</span>
</div>
<div class="flex flex-wrap justify-center gap-6">
<a href="#" class="text-gray-300 hover:text-white text-sm">Data Sources</a>
<a href="#" class="text-gray-300 hover:text-white text-sm">Documentation</a>
<a href="#" class="text-gray-300 hover:text-white text-sm">API Status</a>
<a href="#" class="text-gray-300 hover:text-white text-sm">Help Center</a>
</div>
<div class="mt-6 md:mt-0 flex space-x-4">
<a href="#" class="text-gray-400 hover:text-white">
<i class="fab fa-twitter"></i>
</a>
<a href="#" class="text-gray-400 hover:text-white">
<i class="fab fa-linkedin"></i>
</a>
<a href="#" class="text-gray-400 hover:text-white">
<i class="fab fa-github"></i>
</a>
</div>
</div>
<div class="mt-8 pt-8 border-t border-gray-700 text-center text-sm text-gray-400">
<p>&copy; 2023 FRED Dashboard. All rights reserved. This product uses the FRED API but is not endorsed or certified by the Federal Reserve Bank of St. Louis.</p>
</div>
</div>
</footer>
</div>
<script>
// AI Model Configuration
let aiModel = null;
let aiTokenizer = null;
async function initAIModel() {
try {
// Load model only when needed
const { AutoModelForCausalLM, AutoTokenizer } = await import('transformers');
aiTokenizer = await AutoTokenizer.from_pretrained("AceInstruct-72B");
aiModel = await AutoModelForCausalLM.from_pretrained(
"AceInstruct-72B",
{torch_dtype: "auto", device_map: "auto"}
);
console.log("AI model loaded successfully");
} catch (error) {
console.error("Error loading AI model:", error);
}
}
// FRED API Configuration
const FRED_API_KEY = 'YOUR_API_KEY_HERE'; // Replace with your actual FRED API key
const FRED_BASE_URL = 'https://api.stlouisfed.org/fred/series/observations';
// FRED Series IDs for common economic indicators
const FRED_SERIES = {
GDP: 'GDPC1', // Real GDP
CPI: 'CPIAUCSL', // CPI All Items
CORE_CPI: 'CPILFESL', // Core CPI
UNRATE: 'UNRATE', // Unemployment Rate
FEDFUNDS: 'FEDFUNDS', // Federal Funds Rate
INDUSTRIAL: 'INDPRO', // Industrial Production
RETAIL: 'RSXFS' // Retail Sales
};
// Helper function to fetch FRED data
async function fetchFredData(seriesId, months = 12) {
const endDate = new Date().toISOString().split('T')[0];
const startDate = new Date();
startDate.setMonth(startDate.getMonth() - months);
const startDateStr = startDate.toISOString().split('T')[0];
const url = `${FRED_BASE_URL}?series_id=${seriesId}&api_key=${FRED_API_KEY}&file_type=json&observation_start=${startDateStr}&observation_end=${endDate}&frequency=m`;
try {
const response = await fetch(url);
const data = await response.json();
return processFredData(data.observations);
} catch (error) {
console.error('Error fetching FRED data:', error);
return [];
}
}
// Process FRED API response into chart-friendly format
function processFredData(observations) {
const months = [];
const values = [];
observations.forEach(obs => {
if (obs.value !== '.') { // FRED uses '.' for missing data
const date = new Date(obs.date);
months.push(date.toLocaleString('default', { month: 'short' }));
values.push(parseFloat(obs.value));
}
});
return { months, values };
}
// DOM references
const loginScreen = document.getElementById('login-screen');
const dashboard = document.getElementById('dashboard');
const googleLoginBtn = document.getElementById('google-login');
const logoutBtn = document.getElementById('logout-btn');
logoutBtn.addEventListener('click', () => {
// In a real app, you would handle actual logout logic here
alert('Logging out...');
// Then redirect to login page
// window.location.href = '/login';
});
const dateFilterBtn = document.getElementById('date-filter-btn');
const dateOptions = document.getElementById('date-options');
const refreshBtn = document.getElementById('refresh-data-btn');
const userMenuBtn = document.getElementById('user-menu');
// Initialize charts and tabs
setTimeout(initCharts, 100);
// Tab switching functionality
const regressionTab = document.getElementById('regression-tab');
const rollingTab = document.getElementById('rolling-tab');
const regressionContent = document.getElementById('regression-content');
const rollingContent = document.getElementById('rolling-content');
regressionTab.addEventListener('click', () => {
regressionTab.classList.remove('bg-gray-200', 'text-gray-700');
regressionTab.classList.add('bg-fred-blue', 'text-white');
rollingTab.classList.remove('bg-fred-blue', 'text-white');
rollingTab.classList.add('bg-gray-200', 'text-gray-700');
regressionContent.classList.remove('hidden');
rollingContent.classList.add('hidden');
});
rollingTab.addEventListener('click', () => {
rollingTab.classList.remove('bg-gray-200', 'text-gray-700');
rollingTab.classList.add('bg-fred-blue', 'text-white');
regressionTab.classList.remove('bg-fred-blue', 'text-white');
regressionTab.classList.add('bg-gray-200', 'text-gray-700');
rollingContent.classList.remove('hidden');
regressionContent.classList.add('hidden');
});
// Date filter dropdown
dateFilterBtn.addEventListener('click', (e) => {
e.stopPropagation();
dateOptions.classList.toggle('show');
});
// Close dropdown when clicking elsewhere
document.addEventListener('click', () => {
dateOptions.classList.remove('show');
});
// Initialize charts with real data
async function initCharts() {
// Fetch all data in parallel
const [gdpData, cpiData, coreCpiData, unrateData] = await Promise.all([
fetchFredData(FRED_SERIES.GDP),
fetchFredData(FRED_SERIES.CPI),
fetchFredData(FRED_SERIES.CORE_CPI),
fetchFredData(FRED_SERIES.UNRATE)
]);
// GDP Chart
const gdpCtx = document.getElementById('gdp-chart').getContext('2d');
new Chart(gdpCtx, {
type: 'line',
data: {
labels: gdpData.months,
datasets: [{
label: 'Real GDP',
data: gdpData.values,
backgroundColor: 'rgba(37, 99, 235, 0.05)',
borderColor: '#2563eb',
borderWidth: 2,
pointBackgroundColor: '#fff',
pointBorderColor: '#2563eb',
pointBorderWidth: 2,
pointRadius: 4,
tension: 0.3,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
tooltip: {
mode: 'index',
intersect: false,
backgroundColor: 'rgba(0, 0, 0, 0.85)',
titleFont: {
size: 12
},
bodyFont: {
size: 13
},
padding: 10
}
},
scales: {
y: {
beginAtZero: false,
min: 1.5,
ticks: {
stepSize: 0.5,
callback: function(value) {
return value + '%';
}
},
grid: {
drawBorder: false
}
},
x: {
grid: {
display: false
}
}
}
}
});
// Inflation Chart (Bar + Line)
const inflationCtx = document.getElementById('inflation-chart').getContext('2d');
new Chart(inflationCtx, {
type: 'bar',
data: {
labels: months,
datasets: [
{
label: 'CPI',
data: cpiData,
backgroundColor: 'rgba(249, 115, 22, 0.6)',
borderColor: 'rgba(249, 115, 22, 1)',
borderWidth: 1,
borderRadius: 4,
order: 2
},
{
label: 'Core CPI',
data: coreCpiData,
type: 'line',
borderColor: 'rgba(37, 99, 235, 1)',
borderWidth: 2,
pointBackgroundColor: '#fff',
pointBorderColor: '#2563eb',
pointBorderWidth: 2,
pointRadius: 4,
tension: 0.3,
order: 1
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
labels: {
usePointStyle: true,
padding: 20
}
},
tooltip: {
mode: 'index',
intersect: false,
backgroundColor: 'rgba(0, 0, 0, 0.85)',
padding: 10
}
},
scales: {
y: {
beginAtZero: false,
ticks: {
callback: function(value) {
return value + '%';
}
},
grid: {
drawBorder: false
}
},
x: {
grid: {
display: false
}
}
}
}
});
// Unemployment Chart
const unemploymentCtx = document.getElementById('unemployment-chart').getContext('2d');
new Chart(unemploymentCtx, {
type: 'line',
data: {
labels: months,
datasets: [{
label: 'Unemployment Rate (%)',
data: unemploymentData,
backgroundColor: 'rgba(163, 230, 53, 0.1)',
borderColor: 'rgba(163, 230, 53, 1)',
borderWidth: 2,
pointBackgroundColor: '#fff',
pointBorderColor: 'rgba(163, 230, 53, 1)',
pointBorderWidth: 2,
pointRadius: 4,
tension: 0.3,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
tooltip: {
mode: 'index',
intersect: false,
backgroundColor: 'rgba(0, 0, 0, 0.85)'
}
},
scales: {
y: {
reverse: false,
min: 3.5,
max: 4.2,
ticks: {
callback: function(value) {
return value + '%';
}
},
grid: {
drawBorder: false
}
},
x: {
grid: {
display: false
}
}
}
}
});
// Market Chart
const marketCtx = document.getElementById('market-chart').getContext('2d');
new Chart(marketCtx, {
type: 'line',
data: {
labels: months,
datasets: [{
label: 'Market Index',
data: marketData,
backgroundColor: 'rgba(124, 58, 237, 0.05)',
borderColor: 'rgba(124, 58, 237, 1)',
borderWidth: 2,
pointBackgroundColor: '#fff',
pointBorderColor: 'rgba(124, 58, 237, 1)',
pointBorderWidth: 2,
pointRadius: 4,
tension: 0.3,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
tooltip: {
mode: 'index',
intersect: false,
backgroundColor: 'rgba(0, 0, 0, 0.85)',
callbacks: {
label: function(context) {
return `Market Index: ${context.raw.toLocaleString()}`;
}
}
}
},
scales: {
y: {
beginAtZero: false,
min: 13000,
ticks: {
callback: function(value) {
return value.toLocaleString();
}
},
grid: {
drawBorder: false
}
},
x: {
grid: {
display: false
}
}
}
}
});
}
// AI Analysis Functionality
document.getElementById('ask-ai-btn').addEventListener('click', async () => {
if (!aiModel) {
document.getElementById('ai-analysis-container').innerHTML =
'<p class="text-sm text-gray-500">Loading AI model...</p>';
await initAIModel();
}
const analysisContainer = document.getElementById('ai-analysis-container');
analysisContainer.innerHTML = '<div class="flex justify-center"><i class="fas fa-spinner fa-spin text-fred-blue"></i></div>';
try {
// Get current economic data for context
const currentGDP = document.querySelector('.kpi-card:nth-child(1) .text-2xl').textContent;
const currentUnemployment = document.querySelector('.kpi-card:nth-child(2) .text-2xl').textContent;
const currentInflation = document.querySelector('.kpi-card:nth-child(3) .text-2xl').textContent;
const prompt = `Based on these economic indicators:
- GDP Growth: ${currentGDP}
- Unemployment Rate: ${currentUnemployment}
- Inflation Rate: ${currentInflation}
Provide a concise analysis of the current economic conditions, potential risks, and outlook for the next 6 months.`;
const messages = [{"role": "user", "content": prompt}];
const text = aiTokenizer.apply_chat_template(
messages,
tokenize=false,
add_generation_prompt=true
);
const modelInputs = aiTokenizer([text], return_tensors="pt").to("cuda");
const generatedIds = aiModel.generate(
**modelInputs,
max_new_tokens=1024,
temperature=0.7
);
const response = aiTokenizer.batch_decode(generatedIds, skip_special_tokens=true)[0];
analysisContainer.innerHTML = `<div class="prose prose-sm max-w-none">${response}</div>`;
} catch (error) {
analysisContainer.innerHTML = `<p class="text-red-500 text-sm">Error: ${error.message}</p>`;
}
});
// Real data refresh
refreshBtn.addEventListener('click', async () => {
// Show loading indicator
refreshBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i> Refreshing';
refreshBtn.disabled = true;
try {
// Destroy existing charts
Chart.helpers.each(Chart.instances, (instance) => {
instance.destroy();
});
// Reinitialize charts with fresh data
await initCharts();
refreshBtn.innerHTML = '<i class="fas fa-sync-alt mr-2"></i> Data Updated';
// Show success notification
showToast('Data refreshed successfully', 'success');
} catch (error) {
refreshBtn.innerHTML = '<i class="fas fa-sync-alt mr-2"></i> Refresh Failed';
console.error('Refresh error:', error);
showToast('Failed to refresh data', 'error');
} finally {
setTimeout(() => {
refreshBtn.innerHTML = '<i class="fas fa-sync-alt mr-2"></i> Refresh Data';
refreshBtn.disabled = false;
}, 2000);
}
});
// Helper function to show toast notifications
function showToast(message, type = 'info') {
const toast = document.createElement('div');
toast.className = `fixed bottom-4 right-4 px-4 py-2 rounded-md shadow-md text-white ${
type === 'success' ? 'bg-green-500' :
type === 'error' ? 'bg-red-500' : 'bg-blue-500'
}`;
toast.textContent = message;
document.body.appendChild(toast);
setTimeout(() => {
toast.classList.add('opacity-0', 'transition-opacity', 'duration-300');
setTimeout(() => toast.remove(), 300);
}, 3000);
}
// Date range selector
document.querySelectorAll('#date-options button').forEach(button => {
button.addEventListener('click', () => {
const range = button.getAttribute('data-range');
let text = '';
switch(range) {
case '6': text = 'Last 6 Months'; break;
case '12': text = 'Last 12 Months'; break;
case '24': text = 'Last 2 Years'; break;
case '60': text = 'Last 5 Years'; break;
}
dateFilterBtn.innerHTML = `<i class="far fa-calendar mr-2 text-gray-500"></i>${text}<i class="fas fa-chevron-down ml-2 text-xs"></i>`;
dateOptions.classList.remove('show');
// Here would be the API call to update the charts based on the date range
});
});
// Chart expand functionality
document.querySelectorAll('.expand-chart-btn').forEach(btn => {
btn.addEventListener('click', function() {
const chartCard = this.closest('.chart-card');
chartCard.classList.toggle('fullscreen');
if (chartCard.classList.contains('fullscreen')) {
this.innerHTML = '<i class="fas fa-compress-alt"></i>';
chartCard.style.position = 'fixed';
chartCard.style.top = '0';
chartCard.style.left = '0';
chartCard.style.width = '100vw';
chartCard.style.height = '100vh';
chartCard.style.zIndex = '1000';
chartCard.style.padding = '2rem';
} else {
this.innerHTML = '<i class="fas fa-expand-alt"></i>';
chartCard.style.position = '';
chartCard.style.top = '';
chartCard.style.left = '';
chartCard.style.width = '';
chartCard.style.height = '';
chartCard.style.zIndex = '';
chartCard.style.padding = '';
}
// Re-render chart to fit new dimensions
const chartId = chartCard.querySelector('canvas').id;
const chartInstance = Chart.getChart(chartId);
if (chartInstance) {
chartInstance.resize();
}
});
});
// Table row click for drill down
document.querySelectorAll('tbody tr').forEach(row => {
row.addEventListener('click', function() {
const indicatorName = this.querySelector('td:first-child .text-sm').textContent;
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50';
modal.innerHTML = `
<div class="bg-white rounded-lg p-6 max-w-2xl w-full">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-bold">Detailed View: ${indicatorName}</h3>
<button class="close-modal text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="h-64">
<canvas id="detail-chart"></canvas>
</div>
<div class="mt-4 text-sm text-gray-600">
<p>Detailed analysis and historical data would be displayed here.</p>
</div>
</div>
`;
document.body.appendChild(modal);
// Close modal handler
modal.querySelector('.close-modal').addEventListener('click', () => {
modal.remove();
});
// In a real app, you would fetch detailed data and render the chart
setTimeout(() => {
const ctx = modal.querySelector('#detail-chart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
datasets: [{
label: indicatorName,
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'rgba(37, 99, 235, 0.2)',
borderColor: 'rgba(37, 99, 235, 1)',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
}, 100);
});
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=virtualpixelz/dashboard" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>