<?php
if (!defined('_GNUBOARD_')) exit;
add_stylesheet('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">', 0);
include_once(G5_LIB_PATH.'/thumbnail.lib.php');
// 가동 여부 확인 (1이면 가동, 나머지는 정지)
$is_active = ($view['x2_ca3'] == '1');
// 목표 타입 확인 (금액형인지 이율형인지)
$is_rate_type = ($view['x2_target_type'] == 'rate');
// 1. 목표율일 경우 출력할 계산된 금액 미리 연산 (PHP 영역)
$calc_target_price = 0;
if ($is_rate_type && $is_active) {
$watch_p = (float)str_replace(',', '', $view['wr_subject']);
$rate_val = (float)$view['x2_rate'] / 100;
if ($view['x2_ca4'] == '롱') {
$calc_target_price = $watch_p * (1 + $rate_val);
} else {
$calc_target_price = $watch_p * (1 - $rate_val);
}
}
?>
<style>
@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css');
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=JetBrains+Mono:wght@400;700&family=Noto+Sans+KR:wght@400;700;900&display=swap');
:root {
--neon-cyan: #00d4ff; --neon-pink: #ff2d55; --bg-black: #0d1117;
--panel-bg: #161b22; --input-bg: #0d1117; --border-color: #30363d;
--text-dim: #8b949e; --side-margin: 50px;
--price-up: #4ade80; --price-down: #ff2d55;
--electric-blue: #5de2ff;
--golden-yellow: #ffdf00;
--bright-green: #39ff14;
--dark-red: #8b0000;
color-scheme: dark;
}
#CYBER_LOADER { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: var(--bg-black); z-index: 10000; display: flex; flex-direction: column; align-items: center; justify-content: center; transition: opacity 0.5s ease; }
.load-text { font-family: 'Orbitron'; color: var(--neon-cyan); letter-spacing: 3px; margin-bottom: 20px; font-size: 0.9rem; }
.load-bar-wrap { width: 200px; height: 1px; background: rgba(255,255,255,0.1); position: relative; }
.load-bar { width: 0%; height: 100%; background: var(--neon-cyan); animation: loadingProgress 1.5s forwards; }
@keyframes loadingProgress { to { width: 100%; } }
#VIEW_WRAP { position: relative; min-height: 100vh; background: var(--bg-black); padding: 40px 0; font-family: 'Pretendard', sans-serif; color: #c9d1d9; overflow-x: hidden; }
#space-canvas { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; opacity: 0.2; }
.view-container { position: relative; z-index: 2; width: calc(100% - 100px); margin: 0 var(--side-margin); max-width: none !important; animation: fadeIn 0.6s ease-out; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
#v_frame { background: var(--panel-bg); border: 1px solid var(--border-color); border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,0.5); overflow: hidden; position: relative; }
#v_frame::before, #v_frame::after { content: ''; position: absolute; width: 30px; height: 30px; border: 2px solid var(--neon-cyan); z-index: 10; pointer-events: none; }
#v_frame::before { top: -1px; left: -1px; border-right: 0; border-bottom: 0; border-radius: 8px 0 0 0; }
#v_frame::after { bottom: -1px; right: -1px; border-left: 0; border-top: 0; border-radius: 0 0 8px 0; }
.view-header { padding: 25px 35px; border-bottom: 1px solid var(--border-color); background: linear-gradient(90deg, rgba(0, 212, 255, 0.05), transparent); }
.view-header h2 { margin:0; font-family: 'Orbitron'; font-size: 1.1rem; color: var(--neon-cyan); font-weight: 700; letter-spacing: 1px; }
.info-meta { margin-top: 10px; font-family: 'JetBrains Mono'; font-size: 0.75rem; color: var(--text-dim); }
.view-info-bar { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; padding: 20px 35px; background: rgba(0, 0, 0, 0.2); border-bottom: 1px solid var(--border-color); }
.info-tag { border: 1px solid var(--border-color); padding: 5px 15px; border-radius: 4px; font-size: 0.8rem; font-family: 'Noto Sans KR'; font-weight: 600; color: #fff; background: rgba(255,255,255,0.03); }
.info-tag.cyan { color: var(--neon-cyan); border-color: rgba(0, 212, 255, 0.3); }
.info-tag.coin-id { color: var(--neon-pink); border-color: var(--neon-pink); font-family: 'Orbitron'; letter-spacing: 1px; }
.status-badge { padding: 6px 20px; border-radius: 4px; font-size: 0.9rem; font-weight: 800; font-family: 'Noto Sans KR', sans-serif; letter-spacing: 1px; transition: 0.3s; color: #fff }
.stat-on { background:#1fca00; box-shadow: 0 0 15px rgba(57, 255, 20, 0.4); }
.stat-off { background: var(--dark-red); box-shadow: 0 0 15px rgba(139, 0, 0, 0.4); }
.dashboard-panel { display: flex; align-items: stretch; border-bottom: 1px solid var(--border-color); background: rgba(0,0,0,0.1); }
.dash-item { flex: 1; padding: 45px 10px; border-right: 1px solid var(--border-color); text-align: center; display: flex; flex-direction: column; justify-content: center; align-items: center; transition: 0.3s; position: relative; }
.dash-item:last-child { border-right: none; }
.dash-item:hover { background: rgba(255,255,255,0.03); }
.dash-label { font-family: 'Noto Sans KR'; font-size: 1rem; color: #ffffff; margin-bottom: 18px; font-weight: 700; letter-spacing: 0.5px; position: relative; padding-bottom: 8px; }
.dash-label::after { content: ''; position: absolute; bottom: 0; left: 50%; transform: translateX(-50%); width: 20px; height: 2px; background: rgba(255,255,255,0.2); }
.dash-value { font-family: 'JetBrains Mono'; font-size: 2.2rem; font-weight: 800; color: #fff; letter-spacing: -1px; line-height: 1; }
.dash-watch .dash-value { color: var(--bright-green); text-shadow: 0 0 15px rgba(57, 255, 20, 0.4); }
.dash-target .dash-value { color: var(--golden-yellow); text-shadow: 0 0 20px rgba(255, 223, 0, 0.4); }
.dash-realtime .dash-value { color: var(--electric-blue); font-size: 2.5rem; text-shadow: 0 0 25px rgba(93, 226, 255, 0.5); }
#profit_indicator { transition: all 0.5s ease; }
.p-up { color: var(--price-up) !important; text-shadow: 0 0 15px rgba(74, 222, 128, 0.4); }
.p-down { color: var(--price-down) !important; text-shadow: 0 0 15px rgba(255, 45, 85, 0.4); }
.target-status-btn { padding: 15px 10px; border-radius: 8px; font-family: 'Noto Sans KR', sans-serif; font-size: 1.2rem; font-weight: 900; letter-spacing: -0.5px; display: flex; align-items: center; justify-content: center; width: 90%; min-height: 60px; transition: 0.4s; border: none; }
.status-reached { background: var(--bright-green) !important; color: #fff !important; box-shadow: 0 0 25px rgba(57, 255, 20, 0.5); }
.status-waiting { background: var(--price-down) !important; color: #fff !important; box-shadow: 0 0 15px rgba(255, 45, 85, 0.4); }
.view-tags { padding: 20px 35px; border-top: 1px solid var(--border-color); display: flex; flex-wrap: wrap; gap: 10px; }
.tag-link { color: var(--neon-pink); font-size: 0.75rem; text-decoration: none; opacity: 0.8; }
.view-footer { padding: 30px 35px; border-top: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: center; background: rgba(0, 0, 0, 0.1); }
.btn-action { border: 1px solid var(--border-color); background: transparent; color: var(--text-dim); padding: 8px 18px; border-radius: 4px; font-family: 'Orbitron'; font-weight: 600; cursor: pointer; transition: 0.2s; font-size: 0.7rem; text-decoration: none; text-transform: uppercase; }
.btn-action.highlight { background: var(--neon-cyan); color: #000; border: none; }
.view-nav { display: flex; border-top: 1px solid var(--border-color); }
.view-nav a { flex: 1; padding: 25px 35px; text-decoration: none; color: #fff; border-right: 1px solid var(--border-color); transition: 0.2s; }
.nav-label { font-family: 'Orbitron'; font-size: 0.6rem; color: var(--neon-cyan); display: block; margin-bottom: 5px; }
.nav-subject { font-size: 0.85rem; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 1200px) {
.dash-value { font-size: 1.8rem; }
.dash-realtime .dash-value { font-size: 2rem; }
}
@media (max-width: 1024px) {
:root { --side-margin: 20px; }
.view-container { width: calc(100% - 40px); margin: 0 20px; }
.dashboard-panel { flex-direction: column; }
.dash-item { border-right: none; border-bottom: 1px solid var(--border-color); padding: 35px 20px; }
.dash-value { font-size: 2.8rem; }
}
</style>
<div id="CYBER_LOADER"><div class="load-text">DECRYPTING_DATA</div><div class="load-bar-wrap"><div class="load-bar"></div></div></div>
<div id="VIEW_WRAP">
<canvas id="space-canvas"></canvas>
<article class="view-container">
<div id="v_frame">
<div class="view-header">
<div style="display:flex; justify-content:space-between; align-items:center;">
<div>
<h2><i class="fa-solid fa-database"></i> <?php echo $board['bo_subject']; ?></h2>
<div class="info-meta">
<span style="color:var(--neon-cyan); margin-right:15px;">ID: <?php echo $view['wr_id']; ?></span>
<span><i class="fa-regular fa-clock"></i> <?php echo date("Y-m-d H:i", strtotime($view['wr_datetime'])); ?></span>
<span style="margin-left:15px;"><i class="fa-regular fa-eye"></i> <?php echo number_format($view['wr_hit']); ?></span>
</div>
</div>
</div>
</div>
<div class="view-info-bar">
<?php if($view['ca_name']) { ?><span class="info-tag"><?php echo $view['ca_name']; ?></span><?php } ?>
<?php if($view['x2_ca2']) { ?><span class="info-tag"><?php echo $view['x2_ca2']; ?></span><?php } ?>
<?php if($view['x2_ca4']) { ?><span class="info-tag cyan"><?php echo $view['x2_ca4']; ?></span><?php } ?>
<?php if($view['x2_coin']) { ?><span class="info-tag coin-id"><i class="fa-solid fa-coins"></i> <?php echo $view['x2_coin']; ?></span><?php } ?>
<?php
$stat_text = $is_active ? '가동중' : '정지됨';
$stat_class = $is_active ? 'stat-on' : 'stat-off';
?>
<span class="status-badge <?php echo $stat_class; ?>"><?php echo $stat_text; ?></span>
</div>
<div class="dashboard-panel">
<div class="dash-item dash-watch">
<div class="dash-label">감시금액</div>
<div class="dash-value"><?php echo $is_active ? number_format((float)$view['wr_subject']) : '-'; ?></div>
</div>
<div class="dash-item dash-target">
<?php if ($is_rate_type) { ?>
<div class="dash-label">목표수익률</div>
<div class="dash-value"><?php echo $is_active ? number_format((float)$view['x2_rate'], 2) . '%' : '-'; ?></div>
<div style="font-size:0.9rem; color:var(--text-dim); margin-top:5px; font-family:'JetBrains Mono';">
(<?php echo number_format($calc_target_price); ?>)
</div>
<?php } else { ?>
<div class="dash-label">목표금액</div>
<div class="dash-value"><?php echo $is_active ? number_format((float)$view['x2_target']) : '-'; ?></div>
<?php } ?>
</div>
<div class="dash-item dash-realtime">
<div class="dash-label">실시간 현재금액</div>
<div class="dash-value" id="realtime_upbit_price"><?php echo $is_active ? 'LOADING...' : '-'; ?></div>
</div>
<div class="dash-item">
<div class="dash-label">손익 현황</div>
<div class="dash-value" id="profit_indicator">-</div>
</div>
<div class="dash-item">
<div class="dash-label">도달 상태</div>
<div style="width:100%; display:flex; justify-content:center;">
<div id="target_status_display" class="target-status-btn status-waiting"><?php echo $is_active ? '분석 중...' : '-'; ?></div>
</div>
</div>
</div>
<?php if ($view['x2_tag']) { ?>
<div class="view-tags">
<span style="font-size:0.75rem; color:var(--text-dim);">태그 : </span><?php $tags = explode(',', $view['x2_tag']); foreach($tags as $t) { $t = trim($t); if($t) echo '<a href="'.G5_BBS_URL.'/board.php?bo_table='.$bo_table.'&stx='.urlencode($t).'&sfl=wr_subject||wr_content" class="tag-link">#'.$t.'</a>'; } ?>
</div>
<?php } ?>
<div class="view-footer">
<div style="display:flex; gap:8px;">
<a href="<?php echo $list_href; ?>" class="btn-action">감시 코인 목록</a>
<?php if ($write_href) { ?><a href="<?php echo $write_href; ?>" class="btn-action highlight">새 코인 등록</a><?php } ?>
</div>
<div style="display:flex; gap:8px;">
<?php if ($update_href) { ?><a href="<?php echo $update_href; ?>" class="btn-action highlight">코인 감시 수정</a><?php } ?>
<?php if ($delete_href) { ?><a href="<?php echo $delete_href; ?>" class="btn-action" onclick="return confirm('PURGE DATA FROM SYSTEM?');">삭제</a><?php } ?>
</div>
</div>
<nav class="view-nav">
<?php if ($prev_href) { ?><a href="<?php echo $prev_href; ?>"><span class="nav-label"><i class="fa-solid fa-angle-left"></i> PREV_SECTOR</span><div class="nav-subject"><?php echo $prev_wr_subject; ?></div></a><?php } ?>
<?php if ($next_href) { ?><a href="<?php echo $next_href; ?>" style="text-align:right;"><span class="nav-label">NEXT_SECTOR <i class="fa-solid fa-angle-right"></i></span><div class="nav-subject"><?php echo $next_wr_subject; ?></div></a><?php } ?>
</nav>
</div>
</article>
</div>
<script src="<?php echo G5_JS_URL; ?>/viewimageresize.js"></script>
<script>
window.addEventListener('load', function() { setTimeout(() => { document.getElementById('CYBER_LOADER').style.opacity = '0'; setTimeout(() => document.getElementById('CYBER_LOADER').style.visibility = 'hidden', 500); }, 800); });
function fetchRealtimeData() {
const isActive = "<?php echo $view['x2_ca3']; ?>" === "1";
if (!isActive) {
document.getElementById('realtime_upbit_price').innerText = "-";
document.getElementById('profit_indicator').innerText = "-";
document.getElementById('target_status_display').innerText = "-";
return;
}
const coinSymbol = "<?php echo $view['x2_coin']; ?>";
const watchPrice = parseFloat("<?php echo str_replace(',', '', $view['wr_subject']); ?>");
const targetType = "<?php echo $view['x2_target_type']; ?>";
const position = "<?php echo $view['x2_ca4']; ?>";
let targetPrice = 0;
if (targetType === 'rate') {
const rate = parseFloat("<?php echo $view['x2_rate']; ?>") / 100;
if (position === "롱") {
targetPrice = watchPrice * (1 + rate);
} else {
targetPrice = watchPrice * (1 - rate);
}
} else {
targetPrice = parseFloat("<?php echo str_replace(',', '', $view['x2_target']); ?>");
}
if (!coinSymbol) return;
fetch(`https://api.upbit.com/v1/ticker?markets=${coinSymbol}`)
.then(response => response.json())
.then(data => {
if (data && data[0]) {
const tradePrice = data[0].trade_price;
const formattedPrice = new Intl.NumberFormat('ko-KR').format(tradePrice);
document.getElementById('realtime_upbit_price').innerText = formattedPrice;
const diff = tradePrice - watchPrice;
const diffPercent = watchPrice !== 0 ? ((diff / watchPrice) * 100).toFixed(2) : 0;
const pClass = diff > 0 ? "p-up" : (diff < 0 ? "p-down" : "");
// 2. 손익률 부분에도 pClass 색상 적용
const profitHtml = `<div class="${pClass}">${new Intl.NumberFormat('ko-KR').format(Math.abs(diff))}</div>
<div class="${pClass}" style="font-size:1.1rem; opacity:0.9; margin-top:5px;">(${diffPercent}%)</div>`;
document.getElementById('profit_indicator').innerHTML = profitHtml;
const statusBtn = document.getElementById('target_status_display');
let isReached = false;
let progressPercent = 0;
const totalDistance = Math.abs(targetPrice - watchPrice);
const currentMove = Math.abs(tradePrice - watchPrice);
if (totalDistance > 0) progressPercent = ((currentMove / totalDistance) * 100).toFixed(2);
if (position === "롱") { if (tradePrice >= targetPrice) isReached = true; }
else if (position === "숏") { if (tradePrice <= targetPrice) isReached = true; }
if (isReached) {
statusBtn.className = "target-status-btn status-reached";
statusBtn.innerHTML = "<i class='fa-solid fa-flag-checkered' style='margin-right:8px;'></i> 도달 완료!";
} else {
statusBtn.className = "target-status-btn status-waiting";
statusBtn.innerHTML = `미도달 : [${progressPercent}%]`;
}
}
});
}
$(function() {
fetchRealtimeData();
setInterval(fetchRealtimeData, 1000);
$(".view-content img").viewimageresize();
const canvas = document.getElementById('space-canvas'); const ctx = canvas.getContext('2d'); let stars = [];
function initSpace() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; stars = []; for(let i=0; i<80; i++) stars.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, size: Math.random() * 1.1, speed: Math.random() * 0.15 }); }
function animateSpace() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "rgba(201, 209, 217, 0.3)"; stars.forEach(star => { ctx.beginPath(); ctx.arc(star.x, star.y, star.size, 0, Math.PI*2); ctx.fill(); star.y += star.speed; if(star.y > canvas.height) star.y = 0; }); requestAnimationFrame(animateSpace); }
window.addEventListener('resize', initSpace); initSpace(); animateSpace();
});
</script>