GNU/skin/board/memo/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);



$memo_cards = array();
// [트리플 필터 적용 - 체크박스 전용 최적화]
// 1. x2_pin 필드가 '1'인 것만 (체크박스 체크된 데이터)
// 2. x2_end가 완료되지 않은 것만 (미결 사항)
// 3. wr_subject를 가져와서 화면에 출력
$memo_sql = "SELECT wr_id, wr_subject, wr_datetime, x2_end, x2_pin
             FROM {$write_table}
             WHERE wr_is_comment = '0' 
               AND x2_pin = '1'                                    -- [조건 1] 핀 체크(1)된 데이터만 확실하게!
               AND (x2_end = '0' OR x2_end = '' OR x2_end IS NULL) -- [조건 2] 미완료 상태만
             ORDER BY wr_id DESC
             LIMIT 1000"; 

$memo_res = sql_query($memo_sql);

while($memo_row = sql_fetch_array($memo_res)) {
    // 제목(wr_subject) 정리
    // [수정] 문자열 시작 부분의 모든 공백 및 특수 제어 문자를 싹 다 박멸!
    $display_text = preg_replace('/^\s+/u', '', strip_tags($memo_row['wr_subject']));
    if ($display_text === '') continue;

    // UI 가독성을 위한 글자수 제한 (80자)
    $preview = mb_strimwidth($display_text, 0, 80, "...", "UTF-8");

    $memo_cards[] = array(
        'wr_id'    => $memo_row['wr_id'],
        'subject'  => $memo_row['wr_subject'], // 원본 제목
        'datetime' => $memo_row['wr_datetime'],
        'preview'  => $preview,                // 화면 출력용 제목
        '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>

                <div class="filter-group" style="display:inline-block;">
                    <button type="button" class="btn btn-filter" id="btnFilterPending">
                        <i class="fa-solid fa-hourglass-half"></i> <span>미완료</span>
                    </button>
                    
                    <button type="button" class="btn btn-filter" id="btnFilterCompleted">
                        <i class="fa-solid fa-check-double"></i> <span>완료만</span>
                    </button>
                    
                    <button type="button" class="btn" id="btnFilterAll" style="color: #ff4444; display: none;">
                        <i class="fa-solid fa-list"></i> <span>전체</span>
                    </button>
                </div>

                <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; ?>">

        <div id="memo_layer_popup" onclick="close_memo_popup();">
            <div class="Pop">                
                <div class="Title">
                    <span onclick="close_memo_popup();">닫기</span>
                </div>                
                <iframe id="memo_iframe" frameborder="0"></iframe>
            </div>
        </div>

        <div class="memo-masonry-wrapper">
            <?php 
            for ($i=0; $i<count($list); $i++) { 
                $full_memo = get_text($list[$i]['wr_subject'], 0);
                $date_info = date('y-m-d H:i', strtotime($list[$i]['wr_datetime']));
                $view_url = "./board.php?bo_table=$bo_table&wr_id={$list[$i]['wr_id']}"; 
                $update_url = "./write.php?w=u&bo_table=$bo_table&wr_id={$list[$i]['wr_id']}";

                $lines = explode("\n", $full_memo);
                $numbered_lines = array();
                for ($j = 0; $j < count($lines) && $j < 15; $j++) {
                    $numbered_lines[] = ($j + 1) . ". " . $lines[$j];
                }

                $cut_memo = implode("\n", $numbered_lines);
                if (count($lines) > 15) {
                    $cut_memo .= "\n...";
                }
            ?>
                <div class="memo-card-item">
                    <div class="memo-card-header"><?php echo $date_info; ?></div>
                    
                    <div class="memo-card-body" onclick="open_memo_popup('<?php echo $view_url; ?>');" style="<?php if ($list[$i]['x2_end']) echo 'opacity: 0.3; text-decoration: line-through;'; ?>">
                        <?php echo nl2br($cut_memo); ?>
                    </div>

                    <div class="memo-card-footer">
                        <a href="<?php echo $update_url; ?>">수정</a>
                    </div>
                </div>
            <?php } ?>
        </div>
























    </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-date"><?php echo date('Y-m-d H:i', strtotime($memo_card['datetime'])); ?></span>
                    </div>
                    <div class="memo-preview">
                        <?php echo nl2br(get_text($memo_card['preview'], 0)); ?>
                    </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'); ?>