56 lines
1.9 KiB
JavaScript
56 lines
1.9 KiB
JavaScript
/**
|
||
* 주요 지수 티커 (코스피·코스닥·다우·나스닥)
|
||
* - 10초 주기 폴링
|
||
* - 내비게이션 바 하단 어두운 띠에 표시
|
||
*/
|
||
(function () {
|
||
const ticker = document.getElementById('indexTicker');
|
||
const INTERVAL = 10 * 1000;
|
||
|
||
function colorClass(rate) {
|
||
if (rate > 0) return 'text-red-400';
|
||
if (rate < 0) return 'text-blue-400';
|
||
return 'text-gray-400';
|
||
}
|
||
|
||
function arrow(rate) {
|
||
if (rate > 0) return '▲';
|
||
if (rate < 0) return '▼';
|
||
return '–';
|
||
}
|
||
|
||
function fmtPrice(name, price) {
|
||
if (!price) return '-';
|
||
// 코스피·코스닥은 소수점 2자리, 해외는 정수 + 소수점 2자리
|
||
return price.toLocaleString('ko-KR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
||
}
|
||
|
||
function render(quotes) {
|
||
if (!quotes || quotes.length === 0) return;
|
||
ticker.innerHTML = quotes.map(q => {
|
||
const cls = colorClass(q.changeRate);
|
||
const arr = arrow(q.changeRate);
|
||
const rate = q.changeRate != null ? (q.changeRate >= 0 ? '+' : '') + q.changeRate.toFixed(2) + '%' : '-';
|
||
return `
|
||
<span class="shrink-0 flex items-center gap-1.5">
|
||
<span class="text-gray-400 font-medium">${q.name}</span>
|
||
<span class="font-mono font-semibold">${fmtPrice(q.name, q.price)}</span>
|
||
<span class="${cls} font-mono">${arr} ${rate}</span>
|
||
</span>`;
|
||
}).join('<span class="text-gray-600 shrink-0">|</span>');
|
||
}
|
||
|
||
async function fetch_() {
|
||
try {
|
||
const resp = await fetch('/api/indices');
|
||
if (!resp.ok) return;
|
||
const data = await resp.json();
|
||
render(data);
|
||
} catch (e) {
|
||
// 조용히 실패 (티커 미표시)
|
||
}
|
||
}
|
||
|
||
fetch_();
|
||
setInterval(fetch_, INTERVAL);
|
||
})(); |