OLDBOY/skin/board/outline_bybit/view.skin.bybit.php
<?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.'&amp;stx='.urlencode($t).'&amp;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;

    // Bybit ticker: USDT -> linear, USD -> inverse
    const unit = ("<?php echo strtoupper($view['x2_ver'] ?: 'USDT'); ?>");
    const category = (unit === 'USD') ? 'inverse' : 'linear';

    fetch(`https://api.bybit.com/v5/market/tickers?category=${category}&symbol=${encodeURIComponent(coinSymbol)}`)
        .then(response => response.json())
        .then(json => {
            const list = json && json.result && json.result.list ? json.result.list : [];
            if (list && list[0]) {
                const tradePrice = parseFloat(list[0].lastPrice || list[0].last_price || 0);
                if (!tradePrice) return;

                const formattedPrice = new Intl.NumberFormat('ko-KR').format(tradePrice);
                document.getElementById('realtime_upbit_price').innerText = formattedPrice;

                // 손익(진입가=감시가 기준): 롱=현재-감시, 숏=감시-현재
                const diff = (position === "숏") ? (watchPrice - tradePrice) : (tradePrice - watchPrice);
                const diffPercent = watchPrice !== 0 ? ((diff / watchPrice) * 100).toFixed(2) : 0;
                const pClass = diff > 0 ? "p-up" : (diff < 0 ? "p-down" : "");

                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;">(${diffPercent}%)</div>`;
                document.getElementById('profit_box').innerHTML = profitHtml;

                // 목표 달성 판정
                let reached = false;
                if (position === "롱") reached = tradePrice >= targetPrice;
                else reached = tradePrice <= targetPrice;

                document.getElementById('target_status').innerHTML = reached
                    ? `<span class="status-btn bg-on">달성</span>`
                    : `<span class="status-btn bg-off">미달성</span>`;
            }
        });}

$(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>