Really-amin's picture
Upload 196 files
dd7ffbd verified
import apiClient from './apiClient.js';
class ChartLabView {
constructor(section) {
this.section = section;
this.symbolSelect = section.querySelector('[data-chart-symbol]');
this.timeframeButtons = section.querySelectorAll('[data-chart-timeframe]');
this.indicatorInputs = section.querySelectorAll('[data-indicator]');
this.analyzeButton = section.querySelector('[data-run-analysis]');
this.canvas = section.querySelector('#chart-lab-canvas');
this.insightsContainer = section.querySelector('[data-ai-insights]');
this.chart = null;
this.symbol = 'BTC';
this.timeframe = '7d';
}
async init() {
await this.loadChart();
this.bindEvents();
}
bindEvents() {
if (this.symbolSelect) {
this.symbolSelect.addEventListener('change', async () => {
this.symbol = this.symbolSelect.value;
await this.loadChart();
});
}
this.timeframeButtons.forEach((btn) => {
btn.addEventListener('click', async () => {
this.timeframeButtons.forEach((b) => b.classList.remove('active'));
btn.classList.add('active');
this.timeframe = btn.dataset.chartTimeframe;
await this.loadChart();
});
});
if (this.analyzeButton) {
this.analyzeButton.addEventListener('click', () => this.runAnalysis());
}
}
async loadChart() {
if (!this.canvas) return;
const result = await apiClient.getPriceChart(this.symbol, this.timeframe);
const container = this.canvas.parentElement;
if (!result.ok) {
if (container) {
let errorNode = container.querySelector('.chart-error');
if (!errorNode) {
errorNode = document.createElement('div');
errorNode.className = 'inline-message inline-error chart-error';
container.appendChild(errorNode);
}
errorNode.textContent = result.error;
}
return;
}
if (container) {
const errorNode = container.querySelector('.chart-error');
if (errorNode) errorNode.remove();
}
const points = result.data || [];
const labels = points.map((point) => point.time || point.timestamp || '');
const prices = points.map((point) => point.price || point.close || point.value);
if (this.chart) {
this.chart.destroy();
}
this.chart = new Chart(this.canvas, {
type: 'line',
data: {
labels,
datasets: [
{
label: `${this.symbol} (${this.timeframe})`,
data: prices,
borderColor: '#f472b6',
backgroundColor: 'rgba(244, 114, 182, 0.2)',
fill: true,
tension: 0.4,
},
],
},
options: {
scales: {
x: { ticks: { color: 'var(--text-muted)' } },
y: { ticks: { color: 'var(--text-muted)' } },
},
plugins: {
legend: { display: false },
},
},
});
}
async runAnalysis() {
if (!this.insightsContainer) return;
const enabledIndicators = Array.from(this.indicatorInputs)
.filter((input) => input.checked)
.map((input) => input.value);
this.insightsContainer.innerHTML = '<p>Running AI analysis...</p>';
const result = await apiClient.analyzeChart(this.symbol, this.timeframe, enabledIndicators);
if (!result.ok) {
this.insightsContainer.innerHTML = `<div class="inline-message inline-error">${result.error}</div>`;
return;
}
const payload = result.data || {};
const insights = payload.insights || result.insights || payload;
if (!insights) {
this.insightsContainer.innerHTML = '<p>No AI insights returned.</p>';
return;
}
const summary =
insights.narrative?.summary?.summary || insights.narrative?.summary || insights.narrative?.summary_text;
const signals = insights.narrative?.signals || {};
const bullets = Object.entries(signals)
.map(([key, value]) => `<li><strong>${key}:</strong> ${(value?.label || 'n/a')} (${value?.score ?? 'β€”'})</li>`)
.join('');
this.insightsContainer.innerHTML = `
<h4>AI Insights</h4>
<p><strong>Direction:</strong> ${insights.change_direction || 'N/A'} (${insights.change_percent ?? 'β€”'}%)</p>
<p><strong>Range:</strong> High ${insights.high ?? 'β€”'} / Low ${insights.low ?? 'β€”'}</p>
<p>${summary || insights.narrative?.summary?.summary || insights.narrative?.summary || ''}</p>
<ul>${bullets || '<li>No sentiment signals provided.</li>'}</ul>
`;
}
}
export default ChartLabView;