OLDBOY/skin/board/maria_event/list.skin.php
<?php
if (!defined('_GNUBOARD_')) exit;

// 외부 DB 연결
include_once('/home/www/DB/db_upbit.php');

// 스타일시트 등록
add_stylesheet('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">', 0);
add_stylesheet('<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Noto+Sans+KR:wght@300;400;500&display=swap">', 0);
add_stylesheet('<link rel="stylesheet" href="'.$board_skin_url.'/style.list.css">', 0);

error_reporting(E_ALL & ~E_NOTICE);
ini_set('display_errors', '0');

// 이벤트 상태 일괄 조회
$event_map = array();
if (count($list) > 0 && isset($db_upbit)) {
    $subjects = array();
    foreach ($list as $item) {
        if ($item['wr_subject']) $subjects[] = $item['wr_subject'];
    }
    if (!empty($subjects)) {
        $in_clause = "'" . implode("','", array_map('addslashes', $subjects)) . "'";
        $ev_sql = "SELECT EVENT_NAME, LAST_EXECUTED FROM information_schema.EVENTS WHERE EVENT_SCHEMA='upbit_data' AND EVENT_NAME IN ($in_clause)";
        if (isset($db_upbit)) {
            if ($db_upbit instanceof mysqli) {
                $ev_res = mysqli_query($db_upbit, $ev_sql);
                if ($ev_res) {
                    while ($row = mysqli_fetch_assoc($ev_res)) {
                        $event_map[$row['EVENT_NAME']] = $row['LAST_EXECUTED'];
                    }
                }
            } elseif ($db_upbit instanceof PDO) {
                $stmt = $db_upbit->query($ev_sql);
                if ($stmt) {
                    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                        $event_map[$row['EVENT_NAME']] = $row['LAST_EXECUTED'];
                    }
                }
            }
        }
    }
}

// 메모 카드 데이터 로드
$memo_cards = array();
$memo_sql = "SELECT wr_id, wr_subject, wr_datetime, x2_memo FROM {$write_table} WHERE wr_is_comment = '0' AND wr_parent = wr_id AND TRIM(IFNULL(x2_memo, '')) <> '' AND IFNULL(x2_memo_clean, '0') <> '1' ORDER BY wr_id DESC";
$memo_res = sql_query($memo_sql);
while ($memo_row = sql_fetch_array($memo_res)) {
    $memo_plain = trim(preg_replace('/\s+/', ' ', strip_tags($memo_row['x2_memo'])));
    if ($memo_plain === '') continue;
    if (function_exists('mb_substr')) {
        $memo_preview = mb_substr($memo_plain, 0, 110, 'UTF-8');
        if (mb_strlen($memo_plain, 'UTF-8') > 110) $memo_preview .= '...';
    } else {
        $memo_preview = substr($memo_plain, 0, 110);
        if (strlen($memo_plain) > 110) $memo_preview .= '...';
    }
    $memo_cards[] = array(
        'wr_id'    => $memo_row['wr_id'],
        'subject'  => $memo_row['wr_subject'],
        'datetime' => $memo_row['wr_datetime'],
        'preview'  => $memo_preview,
        'href'     => get_pretty_url($bo_table, $memo_row['wr_id'])
    );
}

// 우선(priority) 항목 분리 → 상단 출력용
$priority_list = array();
$normal_list   = array();
foreach ($list as $item) {
    if (!empty($item['x2_top'])) {
        $priority_list[] = $item;
    } else {
        $normal_list[] = $item;
    }
}
$merged_list = array_merge($priority_list, $normal_list);
?>

<div id="SPACE_WRAP">
    <div class="nebula"></div>

    <article id="LIST">

        <!-- 상단 타이틀 -->
        <section class="TopTitle">
            <p><?php echo strtoupper($bo_table); ?></p>
            <span><i class="fa-solid fa-satellite"></i> <?php echo $board["bo_subject"]; ?></span>
        </section>

        <!-- 컨트롤 바 -->
        <div class="Control-Bar">
            <div class="ctrl-group">
                <button type="button" onclick="$('#NoticeLayer').fadeIn();">
                    <i class="fa-solid fa-bullhorn"></i> NOTICE
                </button>

                <?php if ($is_category) { ?>
                    <!-- 대분류 -->
                    <select onchange="location.href=this.value;">
                        <option value="<?php echo get_pretty_url($bo_table); ?>">거래소</option>
                        <?php
                        $categories = explode('|', $board['bo_category_list']);
                        foreach ($categories as $ca) {
                            if (!$ca) continue;
                            $selected = ($sca == $ca) ? 'selected' : '';
                            echo "<option value='".get_pretty_url($bo_table, '', 'sca='.urlencode($ca))."' $selected>$ca</option>";
                        }
                        ?>
                    </select>

                    <!-- SUB 1 -->
                    <select onchange="location.href=this.value;">
                        <option value="">종류</option>
                        <?php
                        $res2 = sql_query("SELECT DISTINCT x2_ca2 FROM $write_table WHERE x2_ca2 <> '' ORDER BY x2_ca2");
                        while ($row2 = sql_fetch_array($res2)) {
                            echo "<option value='".get_pretty_url($bo_table, '', 'sfl=x2_ca2&stx='.urlencode($row2['x2_ca2']))."'>".$row2['x2_ca2']."</option>";
                        }
                        ?>
                    </select>

                    <!-- SUB 2 -->
                    <select onchange="location.href=this.value;">
                        <option value="">형태</option>
                        <?php
                        $res3 = sql_query("SELECT DISTINCT x2_ca3 FROM $write_table WHERE x2_ca3 <> '' ORDER BY x2_ca3");
                        while ($row3 = sql_fetch_array($res3)) {
                            echo "<option value='".get_pretty_url($bo_table, '', 'sfl=x2_ca3&stx='.urlencode($row3['x2_ca3']))."'>".$row3['x2_ca3']."</option>";
                        }
                        ?>
                    </select>

                    <!-- 특이사항 필터 버튼 -->
                    <button type="button" id="btn-special" onclick="toggleFilter('special')" title="특이사항 있는 항목만 보기">
                        <i class="fa-solid fa-triangle-exclamation" style="color:#f59e0b;"></i> 특이사항
                    </button>

                    <!-- 라벨 필터 버튼 -->
                    <button type="button" id="btn-label" onclick="toggleFilter('label')" title="라벨 있는 항목만 보기">
                        <i class="fa-solid fa-tag" style="color:#818cf8;"></i> 라벨
                    </button>

                    <!-- 메모 패널 버튼 -->
                    <button type="button" class="memo-note-btn" id="memoPanelToggleBtn" title="메모">
                        <i class="fa-solid fa-note-sticky"></i> MEMO
                    </button>

                <?php } ?>
            </div>

            <div class="ctrl-group">
                <!-- 실시간 검색 인풋 -->
                <div class="realtime-search-wrap">
                    <i class="fa-solid fa-bolt" style="color:var(--accent-blue);"></i>
                    <input type="text" id="realtimeSearch" placeholder="실시간 검색..." autocomplete="off" oninput="realtimeFilter(this.value)">
                </div>

                <!-- 기존 검색 버튼 -->
                <button type="button" onclick="$('#SCH').css('display','flex').fadeIn();">
                    <i class="fa-solid fa-magnifying-glass"></i> SEARCH
                </button>

                <?php if ($is_admin) { ?>
                    <button type="button" onclick="location.href='<?php echo G5_ADMIN_URL; ?>/board_form.php?w=u&bo_table=<?php echo $bo_table; ?>'" class="btn-admin">
                        <i class="fa-solid fa-gear"></i> ADMIN
                    </button>
                <?php } ?>

                <?php if ($write_href) { ?>
                    <button type="button" onclick="location.href='<?php echo $write_href; ?>'" class="btn-write">
                        <i class="fa-solid fa-pen"></i> WRITE
                    </button>
                <?php } ?>
            </div>
        </div>

        <!-- 리스트 폼 -->
        <form name="fboardlist" id="fboardlist" action="./board_list_update.php" method="post">
            <input type="hidden" name="bo_table" value="<?php echo $bo_table; ?>">
            <input type="hidden" name="sfl"      value="<?php echo $sfl; ?>">
            <input type="hidden" name="stx"      value="<?php echo $stx; ?>">

            <table class="List-Table" id="listTable">
                <thead>
                    <tr class="List-Header">
                        <th class="col-num">번호</th>
                        <th class="col-run">상태</th>
                        <th class="col-subject">이벤트명</th>
                        <th class="col-subject">원장</th>
                        <th class="col-subject">대상 DB</th>
                        <th class="col-subject">한글명</th>
                        <th class="col-desc">간략설명</th>
                        <th class="col-icons">아이콘</th>
                        <th class="col-ca">대분류</th>
                        <th class="col-ca2">중분류</th>
                        <th class="col-ca2">소분류</th>
                        <th class="col-day">날짜</th>
                    </tr>
                </thead>
                <tbody>
                <?php
                $row_idx = 0;
                foreach ($merged_list as $item) {
                    $is_notice  = $item['is_notice'];
                    $delay      = ($row_idx * 0.04) + 0.3;
                    $row_idx++;

                    $last_exec  = isset($event_map[$item['wr_subject']]) ? $event_map[$item['wr_subject']] : null;
                    $ev_text    = (!empty($last_exec)) ? '시작' : '완료';
                    $ev_class   = (!empty($last_exec)) ? 'ev_done' : 'ev_start';

                    // 핵심 여부 (체크박스 1)
                    $is_core    = ($item['x2_core'] == '1');
                    // 우선 여부 (체크박스 1)
                    $is_prio    = ($item['x2_top'] == '1');
                    // 라벨 여부 (체크박스 1)
                    $is_label   = ($item['x2_label'] == '1');
                    // 메모 여부
                    $has_memo   = !empty(trim((string)$item['x2_memo']));
                    // 추가설명 여부
                    $has_content  = !empty(trim((string)$item['x2_content']));
                    // 특이사항 여부
                    $has_special  = !empty(trim((string)$item['x2_content_2']));

                    // 필터용 data 속성
                    $data_special = $has_special ? 'true' : 'false';
                    $data_label   = $is_label    ? 'true' : 'false';

                    // 행 클래스 조합
                    $row_class = '';
                    if ($is_core) $row_class .= ' row-core';
                    if ($is_prio) $row_class .= ' row-priority';
                ?>
                <tr onclick="location.href='<?php echo $item['href']; ?>'"
                    style="animation-delay:<?php echo $delay; ?>s;"
                    class="<?php echo trim($row_class); ?>"
                    data-special="<?php echo $data_special; ?>"
                    data-label="<?php echo $data_label; ?>"
                    data-search="<?php echo htmlspecialchars(strtolower($item['wr_subject'].' '.$item['wr_subject_kor'].' '.$item['wr_1']), ENT_QUOTES); ?>">

                    <!-- 번호 -->
                    <td class="col-num">
                        <?php if ($is_notice): ?>
                            <i class="fa-solid fa-thumbtack" style="color:var(--accent-blue)"></i>
                        <?php else: ?>
                            <?php echo $item['num']; ?>
                        <?php endif; ?>
                    </td>

                    <!-- 이벤트 상태 -->
                    <td class="col-run">
                        <span class="event_btn <?php echo $ev_class; ?>"><?php echo $ev_text; ?></span>
                    </td>

                    <!-- 이벤트명 -->
                    <td class="col-subject">
                        <?php if ($is_notice): ?>
                            <strong class="txt-main-sub"><?php echo $item['subject']; ?></strong>
                        <?php else: ?>
                            <span class="txt-main-sub"><?php echo $item['subject']; ?></span>
                        <?php endif; ?>
                    </td>

                    <!-- 원장 (x2_db_master) -->
                    <td class="col-subject">
                        <?php if (!empty($item['x2_db_master'])): ?>
                            <span class="txt-ledger"><?php echo htmlspecialchars($item['x2_db_master']); ?></span>
                        <?php else: ?>
                            <span class="txt-empty">-</span>
                        <?php endif; ?>
                    </td>

                    <!-- 대상 DB -->
                    <td class="col-subject">
                        <?php if (!empty($item['x2_db_table'])): ?>
                            <span class="txt-db-table"><?php echo $item['x2_db_table']; ?></span>
                        <?php endif; ?>
                    </td>

                    <!-- 한글명 -->
                    <td class="col-subject">
                        <?php if (!empty($item['wr_subject_kor'])): ?>
                            <span class="txt-kor-name"><?php echo $item['wr_subject_kor']; ?></span>
                        <?php endif; ?>
                    </td>

                    <!-- 간략 설명 -->
                    <td class="col-desc">
                        <?php if (!empty($item['wr_1'])): ?>
                            <span class="txt-desc"><?php echo $item['wr_1']; ?></span>
                        <?php endif; ?>
                    </td>

                    <!-- 아이콘 컬럼 -->
                    <td class="col-icons">
                        <div class="icon-group">
                            <?php if ($is_prio): ?>
                                <span class="ico ico-priority" title="우선">
                                    <i class="fa-solid fa-arrow-up"></i>
                                </span>
                            <?php endif; ?>
                            <?php if ($is_label): ?>
                                <span class="ico ico-label" title="라벨">
                                    <i class="fa-solid fa-tag"></i>
                                </span>
                            <?php endif; ?>
                            <?php if ($is_core): ?>
                                <span class="ico ico-core" title="핵심">
                                    <i class="fa-solid fa-circle-dot"></i>
                                </span>
                            <?php endif; ?>
                            <?php if ($has_content): ?>
                                <span class="ico ico-content" title="추가설명 있음">
                                    <i class="fa-solid fa-file-lines"></i>
                                </span>
                            <?php endif; ?>
                            <?php if ($has_special): ?>
                                <span class="ico ico-special" title="특이사항: <?php echo htmlspecialchars($item['x2_content_2']); ?>">
                                    <i class="fa-solid fa-triangle-exclamation"></i>
                                </span>
                            <?php endif; ?>
                            <?php if ($has_memo): ?>
                                <span class="ico ico-memo" title="메모: <?php echo htmlspecialchars($item['x2_memo']); ?>">
                                    <i class="fa-solid fa-note-sticky"></i>
                                </span>
                            <?php endif; ?>
                            <?php if (!empty($item['wr_link1']) || !empty($item['wr_link2'])): ?>
                                <span class="ico ico-link" title="링크 있음">
                                    <i class="fa-solid fa-link"></i>
                                </span>
                            <?php endif; ?>
                            <?php if ($item['wr_file_count'] > 0): ?>
                                <span class="ico ico-file" title="첨부파일 <?php echo $item['wr_file_count']; ?>개">
                                    <i class="fa-solid fa-paperclip"></i>
                                </span>
                            <?php endif; ?>
                        </div>
                    </td>

                    <!-- 대/중/소분류 -->
                    <td class="col-ca"><?php echo $item['ca_name'] ?: '-'; ?></td>
                    <td class="col-ca2"><?php echo $item['x2_ca2'] ?: '-'; ?></td>
                    <td class="col-ca2"><?php echo $item['x2_ca3'] ?: '-'; ?></td>

                    <!-- 날짜 -->
                    <td class="col-day"><?php echo substr($item['wr_datetime'], 2, 8); ?></td>
                </tr>
                <?php } ?>
                <?php if (count($list) == 0): ?>
                    <tr><td colspan="13" class="empty-row">No signals detected in space.</td></tr>
                <?php endif; ?>
                </tbody>
            </table>
        </form>

        <!-- 페이지네이션 (자체 코드) -->
        <?php if ($total_page > 1) { ?>
        <div id="TERM_PAGING_DIRECT">
            <?php
            $pg_count = $config['cf_write_pages'];
            $start_pg = ((int)(($page - 1) / $pg_count) * $pg_count) + 1;
            $end_pg   = $start_pg + $pg_count - 1;
            if ($end_pg >= $total_page) $end_pg = $total_page;

            if ($page > 1)
                echo '<a href="'.get_pretty_url($bo_table, '', $qstr.'&page=1').'" class="trm-btn"><i class="trm-ico-start fas fa-angles-left"></i></a>';
            if ($start_pg > 1)
                echo '<a href="'.get_pretty_url($bo_table, '', $qstr.'&page='.($start_pg-1)).'" class="trm-btn"><i class="trm-ico-prev fas fa-angle-left"></i></a>';

            for ($k = $start_pg; $k <= $end_pg; $k++) {
                if ($page != $k)
                    echo '<a href="'.get_pretty_url($bo_table, '', $qstr.'&page='.$k).'" class="trm-btn">'.$k.'</a>';
                else
                    echo '<strong class="trm-btn trm-current">'.$k.'</strong>';
            }

            if ($total_page > $end_pg)
                echo '<a href="'.get_pretty_url($bo_table, '', $qstr.'&page='.($end_pg+1)).'" class="trm-btn"><i class="trm-ico-next fas fa-angle-right"></i></a>';
            if ($page < $total_page)
                echo '<a href="'.get_pretty_url($bo_table, '', $qstr.'&page='.$total_page).'" class="trm-btn"><i class="trm-ico-end fas fa-angles-right"></i></a>';
            ?>
        </div>
        <?php } ?>

        <!-- 메모 사이드 패널 -->
        <aside id="memo_side_panel" class="memo-side-panel" aria-hidden="true">
            <div class="memo-panel-head">
                <div class="memo-panel-title"><i class="fa-solid fa-note-sticky"></i> MEMO</div>
                <button type="button" class="memo-panel-close" id="memoPanelCloseBtn"><i class="fa-solid fa-xmark"></i></button>
            </div>

            <div class="memo-panel-layout-wrap">
                <button type="button" class="memo-layout-switch" id="memoLayoutToggle" aria-pressed="false">
                    <span class="memo-layout-label memo-layout-label-1">1x1</span>
                    <span class="memo-layout-thumb"></span>
                    <span class="memo-layout-label memo-layout-label-2">1x2</span>
                </button>
                <span class="memo-total-text">TOTAL : <?php echo number_format(count($memo_cards)); ?></span>
            </div>

            <div class="memo-card-list layout-1" id="memoCardList">
                <?php if (!empty($memo_cards)) { ?>
                    <?php foreach ($memo_cards as $mc) { ?>
                    <article class="memo-card-item">
                        <div class="memo-card-date"><?php echo date('Y-m-d H:i', strtotime($mc['datetime'])); ?></div>
                        <div class="memo-card-subject"><?php echo get_text($mc['subject']); ?></div>
                        <div class="memo-card-content"><?php echo get_text($mc['preview']); ?></div>
                        <a href="<?php echo $mc['href']; ?>" class="memo-card-link">VIEW POST</a>
                    </article>
                    <?php } ?>
                <?php } else { ?>
                    <div class="memo-empty">표시할 메모가 없습니다.</div>
                <?php } ?>
            </div>
        </aside>

    </article><!-- /#LIST -->
</div><!-- /#SPACE_WRAP -->


<!-- NOTICE 모달 -->
<div id="NoticeLayer" class="ModalLayer" style="display:none;">
    <h3><i class="fa-solid fa-terminal"></i> SYSTEM NOTICE</h3>
    <div class="modal-body">
        <?php echo nl2br(stripslashes($board['notice'])); ?>
    </div>
    <div class="modal-footer">
        <div>
            <?php if ($is_admin) { ?>
                <button type="button"
                    onclick="window.open('<?php echo $board_skin_url;?>/notice.php?bo_table=<?php echo $bo_table;?>', 'notice_win', 'width=800,height=700,left='+(screen.availWidth-800)/2+',top='+(screen.availHeight-600)/2);"
                    class="btn-purple">WRITE NOTICE</button>
            <?php } ?>
        </div>
        <button type="button" onclick="$('#NoticeLayer').fadeOut();">DISMISS</button>
    </div>
</div>

<!-- SEARCH 모달 -->
<section id="SCH">
    <div class="search-box">
        <form name="fsearch" method="get">
            <input type="hidden" name="bo_table" value="<?php echo $bo_table; ?>">
            <h3>TERMINAL SEARCH</h3>
            <input type="text" name="stx" value="<?php echo stripslashes($stx); ?>" required placeholder="Keyword entry..." class="search-input">
            <select name="sfl" style="width:100%; margin-top:12px;">
                <option value="wr_subject"  <?php echo ($sfl=='wr_subject')  ? 'selected' : ''; ?>>이벤트명</option>
                <option value="wr_subject_kor" <?php echo ($sfl=='wr_subject_kor') ? 'selected' : ''; ?>>한글명</option>
                <option value="wr_1"        <?php echo ($sfl=='wr_1')        ? 'selected' : ''; ?>>간략설명</option>
            </select>
            <div class="search-actions">
                <button type="submit" class="btn-write" style="flex:1; height:45px;">EXECUTE</button>
                <button type="button" onclick="$('#SCH').fadeOut();" class="btn-cancel" style="flex:1; height:45px;">CANCEL</button>
            </div>
        </form>
    </div>
</section>

<?php include_once($board_skin_path.'/list/list.script.php'); ?>