/**
* Header Component — Symbol selector, timeframe selector, live price, loss counter
*/
import { SYMBOL_CONFIG, TIMEFRAME_MAP } from '../data/dataManager.js';
export class Header {
constructor({ onSymbolChange, onTimeframeChange }) {
this.onSymbolChange = onSymbolChange;
this.onTimeframeChange = onTimeframeChange;
this.activeSymbol = 'BTCUSDT';
this.activeTimeframe = '15m';
this.lastPrice = null;
this.dailyLosses = 0;
this._init();
}
_init() {
this._renderSymbols();
this._renderTimeframes();
this._setupTabListener();
}
_renderSymbols() {
const container = document.getElementById('symbol-selector');
if (!container) return;
const symbols = Object.entries(SYMBOL_CONFIG);
container.innerHTML = symbols.map(([key, config]) => {
const isActive = key === this.activeSymbol;
const icon = this._getSymbolIcon(config.type);
return ``;
}).join('');
container.addEventListener('click', (e) => {
const btn = e.target.closest('.symbol-btn');
if (!btn) return;
const symbol = btn.dataset.symbol;
this.setActiveSymbol(symbol);
});
}
_renderTimeframes() {
const container = document.getElementById('timeframe-selector');
if (!container) return;
const timeframes = Object.keys(TIMEFRAME_MAP);
container.innerHTML = timeframes.map(tf => {
const isActive = tf === this.activeTimeframe;
return ``;
}).join('');
container.addEventListener('click', (e) => {
const btn = e.target.closest('.tf-btn');
if (!btn) return;
const tf = btn.dataset.tf;
this.setActiveTimeframe(tf);
});
}
_setupTabListener() {
// Analysis tabs
const tabBtns = document.querySelectorAll('.tab-btn');
tabBtns.forEach(btn => {
btn.addEventListener('click', () => {
tabBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('.tab-pane').forEach(p => p.classList.remove('active'));
const target = document.getElementById(`tab-${btn.dataset.tab}`);
if (target) target.classList.add('active');
});
});
}
_getSymbolIcon(type) {
switch (type) {
case 'crypto': return '₿';
case 'commodity': return '🥇';
case 'forex': return '💱';
default: return '📈';
}
}
setActiveSymbol(symbol) {
this.activeSymbol = symbol;
document.querySelectorAll('.symbol-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.symbol === symbol);
});
const config = SYMBOL_CONFIG[symbol];
if (config) {
document.getElementById('overlay-symbol').textContent = config.displayName;
}
this.onSymbolChange(symbol);
}
setActiveTimeframe(tf) {
this.activeTimeframe = tf;
document.querySelectorAll('.tf-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.tf === tf);
});
document.getElementById('overlay-timeframe').textContent = tf;
this.onTimeframeChange(tf);
}
updatePrice(price, prevPrice) {
const el = document.getElementById('current-price');
if (!el) return;
const config = SYMBOL_CONFIG[this.activeSymbol];
const decimals = this._getDecimals(this.activeSymbol);
el.textContent = price.toFixed(decimals);
// Tick animation
el.classList.remove('tick-up', 'tick-down');
if (prevPrice !== null && prevPrice !== undefined) {
if (price > prevPrice) {
el.classList.add('tick-up');
} else if (price < prevPrice) {
el.classList.add('tick-down');
}
setTimeout(() => el.classList.remove('tick-up', 'tick-down'), 500);
}
// Price change
if (this.lastPrice === null) this.lastPrice = price;
const changeEl = document.getElementById('price-change');
if (changeEl && this.openPrice) {
const change = ((price - this.openPrice) / this.openPrice) * 100;
changeEl.textContent = `${change >= 0 ? '+' : ''}${change.toFixed(2)}%`;
changeEl.className = `price-change ${change >= 0 ? 'positive' : 'negative'}`;
}
}
setOpenPrice(price) {
this.openPrice = price;
}
_getDecimals(symbol) {
if (symbol === 'XAUUSD') return 2;
if (symbol === 'BTCUSDT') return 2;
return 5; // forex pairs
}
updateDailyLosses(count) {
this.dailyLosses = count;
const el = document.getElementById('loss-count');
if (!el) return;
el.textContent = count.toString();
el.className = 'loss-count';
}
updateAccountSummary(balance, equity) {
const balEl = document.getElementById('account-balance');
const eqEl = document.getElementById('account-equity');
if (!balEl || !eqEl) return;
balEl.textContent = `$${balance.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
eqEl.textContent = `$${equity.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
eqEl.className = 'account-value';
if (equity > balance + 0.01) {
eqEl.classList.add('equity-up');
} else if (equity < balance - 0.01) {
eqEl.classList.add('equity-down');
}
}
setConnectionStatus(status) {
const dot = document.querySelector('.status-dot');
const text = document.querySelector('.status-text');
if (!dot || !text) return;
dot.className = 'status-dot';
switch (status) {
case 'connected':
dot.classList.add('connected');
text.textContent = 'Live';
break;
case 'connecting':
dot.classList.add('connecting');
text.textContent = 'Connecting...';
break;
case 'disconnected':
dot.classList.add('disconnected');
text.textContent = 'Offline';
break;
}
}
}
export default Header;