GNU/skin/board/webbot_news/list.skin.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);
add_stylesheet('<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Noto+Sans+KR:wght@300;400;500;700&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');

if (!empty($list) && is_array($list)) {
    foreach ($list as $idx => $row) {
        $list[$idx]['_origin_idx'] = $idx;
    }

    usort($list, function($a, $b) {
        $a_top = !empty($a['x2_top']) ? 1 : 0;
        $b_top = !empty($b['x2_top']) ? 1 : 0;
        if ($a_top !== $b_top) {
            return $b_top - $a_top;
        }

        $a_notice = !empty($a['is_notice']) ? 1 : 0;
        $b_notice = !empty($b['is_notice']) ? 1 : 0;
        if ($a_notice !== $b_notice) {
            return $b_notice - $a_notice;
        }

        return ($a['_origin_idx'] ?? 0) - ($b['_origin_idx'] ?? 0);
    });
}

$memo_cards = array();
$memo_sql = "SELECT wr_id, wr_subject, wr_datetime, x2_memo, x2_memo_clean
             FROM {$write_table}
             WHERE wr_is_comment = '0' AND wr_parent = wr_id
               AND TRIM(IFNULL(x2_memo, '')) <> ''
             ORDER BY wr_id DESC
             LIMIT 40";
$memo_res = sql_query($memo_sql);
while($memo_row = sql_fetch_array($memo_res)) {
    if (!empty($memo_row['x2_memo_clean'])) continue;

    $memo_plain = trim(preg_replace('/\s+/', ' ', strip_tags($memo_row['x2_memo'])));
    if ($memo_plain === '') continue;

    $memo_plain_len = function_exists('mb_strlen') ? mb_strlen($memo_plain, 'UTF-8') : strlen($memo_plain);

    if (function_exists('mb_substr')) {
        $memo_preview = mb_substr($memo_plain, 0, 80, 'UTF-8');
        if ($memo_plain_len > 80) $memo_preview .= '...';
    } else {
        $memo_preview = substr($memo_plain, 0, 80);
        if ($memo_plain_len > 80) $memo_preview .= '...';
    }

    $memo_cards[] = array(
        'wr_id' => $memo_row['wr_id'],
        'subject' => $memo_row['wr_subject'],
        'datetime' => $memo_row['wr_datetime'],
        'preview' => $memo_preview,
        'preview_len' => $memo_plain_len,
        'href' => get_pretty_url($bo_table, $memo_row['wr_id'])
    );
}

$notice_text = stripslashes((string)$board['notice']);
$notice_lines = preg_split('/\r\n|\r|\n/', $notice_text);
$notice_lines = array_map(function($line) {
    return trim($line);
}, $notice_lines);
$notice_clean = implode("\n", $notice_lines);
?>

<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="Left">
            <button type="button" class="btn" id="btnOpenNotice"><i class="fa-solid fa-bullhorn"></i> 공지사항</button>

            <?php if ($is_category) { ?>
                <select class="control-select" onchange="location.href=this.value;">
                    <option value="<?php echo get_pretty_url($bo_table); ?>">실행상태</option>
                    <option value="<?php echo get_pretty_url($bo_table, '', 'sfl=x2_run&stx=1'); ?>" <?php echo $stx=='1'?'selected':''; ?>>실행</option>
                    <option value="<?php echo get_pretty_url($bo_table, '', 'sfl=x2_run&stx=0'); ?>" <?php echo ($stx=='0' && $stx!='')?'selected':''; ?>>중지</option>
                </select>

                <select class="control-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>

                <select class="control-select" onchange="location.href=this.value;">
                    <option value="">중분류</option>
                    <?php
                    $sql2 = "select distinct x2_ca2 from $write_table where x2_ca2 <> '' order by x2_ca2";
                    $res2 = sql_query($sql2);
                    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>

                <select class="control-select" onchange="location.href=this.value;">
                    <option value="">소분류</option>
                    <?php
                    $sql3 = "select distinct x2_ca3 from $write_table where x2_ca3 <> '' order by x2_ca3";
                    $res3 = sql_query($sql3);
                    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" class="btn" id="btnOpenMemo"><i class="fa-solid fa-note-sticky"></i> 메모</button>
            <?php } ?>
        </div>

        <div class="Right">
            <div class="realtime-search-wrap">
                <i class="fa-solid fa-filter"></i>
                <input type="text" id="realtimeSearch" placeholder="실시간 검색 (심볼/한글명)">
            </div>
            <button type="button" class="btn" id="btnOpenSearch"><i class="fa-solid fa-magnifying-glass"></i> 검색</button>
            <?php if ($is_admin) { ?>
                <button type="button" class="btn btn-admin" onclick="location.href='<?php echo G5_ADMIN_URL; ?>/board_form.php?w=u&bo_table=<?php echo $bo_table; ?>'"><i class="fa-solid fa-gear"></i> 관리</button>
            <?php } ?>
            <?php if ($write_href) { ?>
                <button type="button" class="btn btn-write" onclick="location.href='<?php echo $write_href; ?>'"><i class="fa-solid fa-pen"></i> 글쓰기</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">
            <thead>
            <tr class="List-Header">
                <th class="Num">번호</th>
                <th class="Run">상태</th>
                <th class="Subject">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;코인</th>
                <th class="CaName"><i class="fa-solid fa-layer-group"></i> 대분류</th>
                <th class="Ca2"><i class="fa-solid fa-diagram-project"></i> 중분류</th>
                <th class="Ca3"><i class="fa-solid fa-shapes"></i> 소분류</th>
                <th class="Day"><i class="fa-regular fa-clock"></i> 날짜</th>
            </tr>
            </thead>
            <tbody>
            <?php
            for ($i=0; $i<count($list); $i++) {
                $is_notice = $list[$i]['is_notice'];
                $run_val = $list[$i]['x2_run'];
                $run_text = ($run_val == '1') ? '실행' : '중단';
                $run_class = ($run_val == '1') ? 'run_on' : 'run_off';

                $coin_symbol = trim(strip_tags($list[$i]['subject']));
                $coin_kr = isset($list[$i]['x2_korean_name']) ? trim($list[$i]['x2_korean_name']) : '';
                $is_top = !empty($list[$i]['x2_top']);
                $is_label = !empty($list[$i]['x2_label']);
                $is_core = !empty($list[$i]['x2_core']);

                $date_text = '-';
                if (!empty($list[$i]['wr_datetime']) && $list[$i]['wr_datetime'] !== '0000-00-00 00:00:00') {
                    $ts = strtotime($list[$i]['wr_datetime']);
                    if ($ts !== false) {
                        $date_text = date('Y-m-d H:i', $ts);
                    }
                }
            ?>
            <tr class="list-row <?php echo $is_core ? 'is-core' : ''; ?>"
                onclick="location.href='<?php echo $list[$i]['href']; ?>'"
                data-symbol="<?php echo htmlspecialchars(mb_strtolower($coin_symbol, 'UTF-8'), ENT_QUOTES); ?>"
                data-korean="<?php echo htmlspecialchars(mb_strtolower($coin_kr, 'UTF-8'), ENT_QUOTES); ?>">
                <td class="Num">
                    <?php if ($is_notice) echo '<i class="fa-solid fa-thumbtack row-pin"></i>'; else echo $list[$i]['num']; ?>
                </td>
                <td class="Run">
                    <span class="run_btn <?php echo $run_class; ?>"><?php echo $run_text; ?></span>
                </td>
                <td class="Subject">
                    <div class="coin-line">
                        <?php echo $list[$i]['icon_reply']; ?>
                        <?php if ($is_notice) { ?>
                            <strong class="coin-symbol"><?php echo $coin_symbol; ?></strong>
                        <?php } else { ?>
                            <span class="coin-symbol"><?php echo $coin_symbol; ?></span>
                        <?php } ?>
                        <span class="coin-korean"><?php echo $coin_kr !== '' ? $coin_kr : '-'; ?></span>
                        <?php if ($is_top) { ?><i class="fa-solid fa-circle-up coin-badge-top" title="우선"></i><?php } ?>
                        <?php if ($is_label) { ?><i class="fa-solid fa-star coin-badge-label" title="라벨"></i><?php } ?>
                        <?php if ($is_core) { ?><i class="fa-solid fa-gem coin-badge-core" title="핵심"></i><?php } ?>
                        <?php if ($list[$i]['comment_cnt']) { ?>
                            <span class="comment-badge"><?php echo $list[$i]['comment_cnt']; ?></span>
                        <?php } ?>
                    </div>
                </td>
                <td class="CaName"><span class="tag-pill"><?php echo $list[$i]['ca_name'] ? $list[$i]['ca_name'] : '-'; ?></span></td>
                <td class="Ca2"><span class="tag-pill"><?php echo $list[$i]['x2_ca2'] ? $list[$i]['x2_ca2'] : '-'; ?></span></td>
                <td class="Ca3"><span class="tag-pill"><?php echo $list[$i]['x2_ca3'] ? $list[$i]['x2_ca3'] : '-'; ?></span></td>
                <td class="Day"><?php echo $date_text; ?></td>
            </tr>
            <?php } ?>
            <?php if (count($list) == 0) { ?>
                <tr class="empty-row"><td colspan="7">출력할 데이터가 없습니다.</td></tr>
            <?php } ?>
            <tr id="RealtimeNoResult" class="empty-row" style="display:none;"><td colspan="7">실시간 검색 결과가 없습니다.</td></tr>
            </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"></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"></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"></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"></i></a>'; }
        ?>
    </div>
    <?php } ?>

    <div id="NoticeLayer" class="NoticeLayer">
        <div class="notice-head">
            <h3><i class="fa-solid fa-circle-info"></i> 공지사항</h3>
            <button type="button" class="btn-icon" id="btnCloseNoticeTop"><i class="fa-solid fa-xmark"></i></button>
        </div>
        <div class="notice-body">
            <?php echo nl2br(get_text($notice_clean, 0)); ?>
        </div>
        <div class="notice-foot">
            <?php if ($is_admin) { ?>
                <button type="button" class="btn btn-admin" 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);">공지 수정</button>
            <?php } ?>
            <button type="button" class="btn" id="btnCloseNoticeBottom">닫기</button>
        </div>
    </div>

    <div id="MemoLayer" class="MemoLayer">
        <div class="memo-head">
            <h3><i class="fa-solid fa-note-sticky"></i> 메모</h3>
            <div class="memo-head-actions">
                <div class="memo-view-toggle" role="group" aria-label="메모 출력 방식">
                    <button type="button" class="memo-view-btn" data-view="1x1">1X1</button>
                    <button type="button" class="memo-view-btn" data-view="1x2">1X2</button>
                </div>
                <button type="button" class="btn-icon" id="btnCloseMemoTop"><i class="fa-solid fa-xmark"></i></button>
            </div>
        </div>
        <div class="memo-body">
            <?php if (!empty($memo_cards)) { ?>
                <?php foreach ($memo_cards as $memo_card) { ?>
                <a href="<?php echo $memo_card['href']; ?>" class="memo-item">
                    <div class="memo-item-head">
                        <span class="memo-subject"><?php echo get_text($memo_card['subject']); ?></span>
                        <span class="memo-date"><?php echo date('Y-m-d H:i', strtotime($memo_card['datetime'])); ?></span>
                    </div>
                    <div class="memo-preview">
                        <?php echo get_text($memo_card['preview']); ?>
                    </div>
                </a>
                <?php } ?>
            <?php } else { ?>
                <div class="memo-empty">표시할 메모가 없습니다.</div>
            <?php } ?>
        </div>
        <div class="memo-foot">
            <button type="button" class="btn" id="btnCloseMemoBottom">닫기</button>
        </div>
    </div>

    <section id="SCH" class="Search">
        <div class="search-panel">
            <form name="fsearch" method="get" class="search-form">
                <input type="hidden" name="bo_table" value="<?php echo $bo_table; ?>">
                <input type="hidden" name="sfl" value="<?php echo $sfl; ?>">
                <h3>검색</h3>
                <input type="text" name="stx" value="<?php echo stripslashes($stx); ?>" required placeholder="검색어 입력" class="search-input">
                <div class="search-actions">
                    <button type="submit" class="btn btn-write">검색</button>
                    <button type="button" class="btn" id="btnCloseSearch">취소</button>
                </div>
            </form>
        </div>
    </section>
</article>

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