Really-amin's picture
Upload 1460 files
96af7c9 verified
/**
* Enhanced Charts Module
* Modern, Beautiful, Responsive Charts with Chart.js
*/
// Chart.js Global Configuration
Chart.defaults.color = '#e2e8f0';
Chart.defaults.borderColor = 'rgba(255, 255, 255, 0.1)';
Chart.defaults.font.family = "'Manrope', 'Inter', sans-serif";
Chart.defaults.font.size = 13;
Chart.defaults.font.weight = 500;
// Chart Instances Storage
const chartInstances = {};
/**
* Initialize Market Overview Chart
* Shows top 5 cryptocurrencies price trends
*/
export function initMarketOverviewChart(data) {
const ctx = document.getElementById('market-overview-chart');
if (!ctx) return;
// Destroy existing chart
if (chartInstances.marketOverview) {
chartInstances.marketOverview.destroy();
}
const topCoins = data.slice(0, 5);
const labels = Array.from({length: 24}, (_, i) => `${i}:00`);
const colors = [
{ border: '#8f88ff', bg: 'rgba(143, 136, 255, 0.1)' },
{ border: '#16d9fa', bg: 'rgba(22, 217, 250, 0.1)' },
{ border: '#4ade80', bg: 'rgba(74, 222, 128, 0.1)' },
{ border: '#f472b6', bg: 'rgba(244, 114, 182, 0.1)' },
{ border: '#facc15', bg: 'rgba(250, 204, 21, 0.1)' }
];
const datasets = topCoins.map((coin, index) => ({
label: coin.name,
data: coin.sparkline_in_7d?.price?.slice(-24) || [],
borderColor: colors[index].border,
backgroundColor: colors[index].bg,
borderWidth: 3,
fill: true,
tension: 0.4,
pointRadius: 0,
pointHoverRadius: 6,
pointHoverBackgroundColor: colors[index].border,
pointHoverBorderColor: '#fff',
pointHoverBorderWidth: 2
}));
chartInstances.marketOverview = new Chart(ctx, {
type: 'line',
data: { labels, datasets },
options: {
responsive: true,
maintainAspectRatio: false,
interaction: {
mode: 'index',
intersect: false,
},
plugins: {
legend: {
display: true,
position: 'top',
align: 'end',
labels: {
usePointStyle: true,
pointStyle: 'circle',
padding: 20,
font: {
size: 13,
weight: 600
},
color: '#e2e8f0'
}
},
tooltip: {
enabled: true,
backgroundColor: 'rgba(15, 23, 42, 0.95)',
titleColor: '#fff',
bodyColor: '#e2e8f0',
borderColor: 'rgba(143, 136, 255, 0.5)',
borderWidth: 1,
padding: 16,
displayColors: true,
boxPadding: 8,
usePointStyle: true,
callbacks: {
label: function(context) {
return context.dataset.label + ': $' + context.parsed.y.toFixed(2);
}
}
}
},
scales: {
x: {
grid: {
display: false
},
ticks: {
color: '#94a3b8',
font: {
size: 11
}
}
},
y: {
grid: {
color: 'rgba(255, 255, 255, 0.05)',
drawBorder: false
},
ticks: {
color: '#94a3b8',
font: {
size: 11
},
callback: function(value) {
return '$' + value.toLocaleString();
}
}
}
}
}
});
}
/**
* Create Mini Sparkline Chart for Table
*/
export function createSparkline(canvasId, data, color = '#8f88ff') {
const ctx = document.getElementById(canvasId);
if (!ctx) return;
new Chart(ctx, {
type: 'line',
data: {
labels: data.map((_, i) => i),
datasets: [{
data: data,
borderColor: color,
backgroundColor: color + '20',
borderWidth: 2,
fill: true,
tension: 0.4,
pointRadius: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: { enabled: false }
},
scales: {
x: { display: false },
y: { display: false }
}
}
});
}
/**
* Initialize Price Chart with Advanced Features
*/
export function initPriceChart(coinId, days = 7) {
const ctx = document.getElementById('price-chart');
if (!ctx) return;
// Destroy existing
if (chartInstances.price) {
chartInstances.price.destroy();
}
// Fetch data and create chart
fetch(`https://api.coingecko.com/api/v3/coins/${coinId}/market_chart?vs_currency=usd&days=${days}`)
.then(res => res.json())
.then(data => {
const labels = data.prices.map(p => new Date(p[0]).toLocaleDateString());
const prices = data.prices.map(p => p[1]);
chartInstances.price = new Chart(ctx, {
type: 'line',
data: {
labels,
datasets: [{
label: 'Price (USD)',
data: prices,
borderColor: '#8f88ff',
backgroundColor: 'rgba(143, 136, 255, 0.1)',
borderWidth: 3,
fill: true,
tension: 0.4,
pointRadius: 0,
pointHoverRadius: 8,
pointHoverBackgroundColor: '#8f88ff',
pointHoverBorderColor: '#fff',
pointHoverBorderWidth: 3
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
backgroundColor: 'rgba(15, 23, 42, 0.95)',
titleColor: '#fff',
bodyColor: '#e2e8f0',
borderColor: 'rgba(143, 136, 255, 0.5)',
borderWidth: 1,
padding: 16,
displayColors: false,
callbacks: {
label: function(context) {
return 'Price: $' + context.parsed.y.toLocaleString();
}
}
}
},
scales: {
x: {
grid: { display: false },
ticks: {
color: '#94a3b8',
maxRotation: 0,
autoSkip: true,
maxTicksLimit: 8
}
},
y: {
grid: {
color: 'rgba(255, 255, 255, 0.05)',
drawBorder: false
},
ticks: {
color: '#94a3b8',
callback: function(value) {
return '$' + value.toLocaleString();
}
}
}
}
}
});
});
}
/**
* Initialize Volume Chart
*/
export function initVolumeChart(coinId, days = 7) {
const ctx = document.getElementById('volume-chart');
if (!ctx) return;
if (chartInstances.volume) {
chartInstances.volume.destroy();
}
fetch(`https://api.coingecko.com/api/v3/coins/${coinId}/market_chart?vs_currency=usd&days=${days}`)
.then(res => res.json())
.then(data => {
const labels = data.total_volumes.map(v => new Date(v[0]).toLocaleDateString());
const volumes = data.total_volumes.map(v => v[1]);
chartInstances.volume = new Chart(ctx, {
type: 'bar',
data: {
labels,
datasets: [{
label: 'Volume',
data: volumes,
backgroundColor: 'rgba(74, 222, 128, 0.6)',
borderColor: '#4ade80',
borderWidth: 2,
borderRadius: 8,
borderSkipped: false
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
backgroundColor: 'rgba(15, 23, 42, 0.95)',
padding: 16,
callbacks: {
label: function(context) {
return 'Volume: $' + (context.parsed.y / 1000000).toFixed(2) + 'M';
}
}
}
},
scales: {
x: {
grid: { display: false },
ticks: {
color: '#94a3b8',
maxRotation: 0,
autoSkip: true,
maxTicksLimit: 8
}
},
y: {
grid: {
color: 'rgba(255, 255, 255, 0.05)',
drawBorder: false
},
ticks: {
color: '#94a3b8',
callback: function(value) {
return '$' + (value / 1000000).toFixed(0) + 'M';
}
}
}
}
}
});
});
}
/**
* Initialize Sentiment Doughnut Chart
*/
export function initSentimentChart() {
const ctx = document.getElementById('sentiment-chart');
if (!ctx) return;
if (chartInstances.sentiment) {
chartInstances.sentiment.destroy();
}
chartInstances.sentiment = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Very Bullish', 'Bullish', 'Neutral', 'Bearish', 'Very Bearish'],
datasets: [{
data: [25, 35, 20, 15, 5],
backgroundColor: [
'#4ade80',
'#16d9fa',
'#facc15',
'#f472b6',
'#ef4444'
],
borderWidth: 0,
hoverOffset: 10
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
labels: {
padding: 20,
usePointStyle: true,
pointStyle: 'circle',
font: {
size: 13,
weight: 600
}
}
},
tooltip: {
backgroundColor: 'rgba(15, 23, 42, 0.95)',
padding: 16,
callbacks: {
label: function(context) {
return context.label + ': ' + context.parsed + '%';
}
}
}
}
}
});
}
/**
* Initialize Market Dominance Pie Chart
*/
export function initDominanceChart(data) {
const ctx = document.getElementById('dominance-chart');
if (!ctx) return;
if (chartInstances.dominance) {
chartInstances.dominance.destroy();
}
const btc = data.find(c => c.id === 'bitcoin');
const eth = data.find(c => c.id === 'ethereum');
const bnb = data.find(c => c.id === 'binancecoin');
const totalMarketCap = data.reduce((sum, coin) => sum + coin.market_cap, 0);
const btcDominance = ((btc?.market_cap || 0) / totalMarketCap * 100).toFixed(1);
const ethDominance = ((eth?.market_cap || 0) / totalMarketCap * 100).toFixed(1);
const bnbDominance = ((bnb?.market_cap || 0) / totalMarketCap * 100).toFixed(1);
const othersDominance = (100 - btcDominance - ethDominance - bnbDominance).toFixed(1);
chartInstances.dominance = new Chart(ctx, {
type: 'pie',
data: {
labels: ['Bitcoin', 'Ethereum', 'BNB', 'Others'],
datasets: [{
data: [btcDominance, ethDominance, bnbDominance, othersDominance],
backgroundColor: [
'#facc15',
'#8f88ff',
'#f472b6',
'#94a3b8'
],
borderWidth: 0,
hoverOffset: 10
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom',
labels: {
padding: 20,
usePointStyle: true,
font: {
size: 13,
weight: 600
}
}
},
tooltip: {
backgroundColor: 'rgba(15, 23, 42, 0.95)',
padding: 16,
callbacks: {
label: function(context) {
return context.label + ': ' + context.parsed + '%';
}
}
}
}
}
});
}
// Export chart instances for external access
export { chartInstances };