공지사항 목록 디자인 적용

This commit is contained in:
현성필
2025-12-04 15:05:34 +09:00
parent 46f0388832
commit c341f83e3d
3 changed files with 202 additions and 77 deletions
@@ -684,3 +684,70 @@ select.form-control {
.form-actions-center {
@extend .form-actions;
}
// -----------------------------------------------------------------------------
// Search Field - Figma Design (node 1041:1670)
// Rounded search input with icon button
// -----------------------------------------------------------------------------
.search-field {
position: relative;
display: flex;
align-items: center;
width: 340px;
height: 44px;
background: $white;
border: 1px solid #dadada;
border-radius: 12px;
overflow: hidden;
@include respond-to('sm') {
width: 100%;
}
input {
flex: 1;
height: 100%;
padding: 0 44px 0 16px;
border: none;
background: transparent;
font-family: $font-family-primary;
font-size: 14px;
font-weight: $font-weight-regular;
color: $text-dark;
outline: none;
&::placeholder {
color: #8c959f;
}
}
.search-field-btn {
position: absolute;
right: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
width: 44px;
height: 100%;
background: transparent;
border: none;
cursor: pointer;
color: #515961;
transition: $transition-fast;
&:hover {
color: $primary-blue;
}
svg {
width: 20px;
height: 20px;
}
}
&:focus-within {
border-color: $primary-blue;
box-shadow: 0 0 0 2px rgba($primary-blue, 0.1);
}
}
@@ -366,6 +366,61 @@
text-align: left;
}
}
// Title cell with inline file icon
&--title {
justify-content: flex-start;
@media (max-width: $breakpoint-md) {
&::before {
display: none; // Hide data-label for title on mobile
}
}
.notice-title-link {
display: inline-flex;
align-items: center;
gap: $spacing-sm;
color: inherit;
text-decoration: none;
transition: $transition-base;
&:hover {
color: $primary-blue;
}
// Mobile number prefix [1] [2] etc
.notice-number {
display: none;
font-weight: $font-weight-medium;
color: $text-gray;
flex-shrink: 0;
@media (max-width: $breakpoint-md) {
display: inline;
}
}
}
.file-icon {
display: inline-flex;
align-items: center;
flex-shrink: 0;
color: #212529;
svg {
width: 24px;
height: 24px;
}
}
}
// Number cell for notice list
&--number {
@media (max-width: $breakpoint-md) {
display: none; // Hide separate number cell on mobile
}
}
}
// Action buttons container
@@ -1,85 +1,87 @@
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kjbank_base_layout}">
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout/kjbank_title_layout}">
<body>
<th:block layout:fragment="contentFragment">
<!-- Notice List Page -->
<div class="notice-page">
<div class="notice-container">
<!-- Page Header -->
<div class="notice-header">
<h1 class="page-title">공지사항</h1>
<p class="page-description">광주은행 API Portal의 새로운 소식과 공지사항을 확인하세요.</p>
<section layout:fragment="title">
<div class="page-title-banner">
<img th:src="@{/img/img_title_bg.png}" class="title-image" alt="타이틀 배경">
<h1>공지사항</h1>
</div>
</section>
<th:block layout:fragment="contentFragment">
<section class="user-management-container">
<!-- Search and Filter Controls -->
<form name="noticeForm" th:action="@{/portalnotice}" method="get" onsubmit="return false;">
<input type="hidden" name="page" value="1">
<div class="table-controls">
<div class="total-count">
<h2 class="total-count">
<strong th:text="${page.totalElements}">0</strong>
</div>
</h2>
<div class="search-box">
<div class="search-field">
<input type="text"
name="searchSubjectOrDetail"
th:value="${search.searchSubjectOrDetail}"
placeholder="제목 또는 내용으로 검색">
<button type="button" class="btn btn-primary" onclick="fn_search_notice()">
<i class="fas fa-search"></i>
<span>검색</span>
placeholder="제목/내용 검색"
onkeypress="if(event.keyCode === 13) { fn_search_notice(); return false; }">
<button type="button" class="search-field-btn" onclick="fn_search_notice()">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.5 17.5L13.875 13.875M15.8333 9.16667C15.8333 12.8486 12.8486 15.8333 9.16667 15.8333C5.48477 15.8333 2.5 12.8486 2.5 9.16667C2.5 5.48477 5.48477 2.5 9.16667 2.5C12.8486 2.5 15.8333 5.48477 15.8333 9.16667Z" stroke="currentColor" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span class="blind">검색</span>
</button>
</div>
</div>
</form>
<!-- Notice Table -->
<div class="notice-list-wrapper" th:if="${!portalNotices.isEmpty()}">
<div class="notice-table">
<div class="list-table" th:if="${!portalNotices.isEmpty()}">
<!-- Table Header -->
<div class="table-header">
<div class="col-num">NO</div>
<div class="col-title">제목</div>
<div class="col-date">등록일</div>
<div class="list-table-header">
<div class="header-cell" style="width: 80px;">NO</div>
<div class="header-cell" style="flex: 1; min-width: 200px;">제목</div>
<div class="header-cell" style="width: 120px;">등록일</div>
</div>
<!-- Table Rows -->
<div class="table-row"
<!-- Table Body -->
<div class="list-table-body">
<div class="list-table-row"
th:each="notice, status : ${portalNotices}"
th:onclick="'location.href=\'' + @{/portalnotice/detail(id=${notice.id})} + '\''">
<div class="col-num"
th:onclick="'location.href=\'' + @{/portalnotice/detail(id=${notice.id})} + '\''"
style="cursor: pointer;">
<div class="row-cell row-cell--number" style="width: 80px;" data-label="NO"
th:text="${page.totalElements - (page.number * page.size) - status.index}">1</div>
<div class="col-title">
<a th:href="@{/portalnotice/detail(id=${notice.id})}">
<div class="row-cell row-cell--title" style="flex: 1; min-width: 200px;" data-label="제목">
<a th:href="@{/portalnotice/detail(id=${notice.id})}" class="notice-title-link">
<span class="notice-number" th:text="|[${page.totalElements - (page.number * page.size) - status.index}]|">[1]</span>
<span th:text="${notice.noticeSubject}">공지사항 제목</span>
<span class="file-icon" th:if="${notice.fileId != null and !notice.fileId.isEmpty()}">
<img th:src="@{/img/icon/icon_file.png}" alt="첨부파일">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 15.75C18 17.4833 17.3917 18.9583 16.175 20.175C14.9583 21.3917 13.4833 22 11.75 22C10.0167 22 8.54167 21.3917 7.325 20.175C6.10833 18.9583 5.5 17.4833 5.5 15.75V6.5C5.5 5.25 5.9375 4.1875 6.8125 3.3125C7.6875 2.4375 8.75 2 10 2C11.25 2 12.3125 2.4375 13.1875 3.3125C14.0625 4.1875 14.5 5.25 14.5 6.5V15.25C14.5 16.0167 14.2333 16.6667 13.7 17.2C13.1667 17.7333 12.5167 18 11.75 18C10.9833 18 10.3333 17.7333 9.8 17.2C9.26667 16.6667 9 16.0167 9 15.25V6H11V15.25C11 15.4667 11.0708 15.6458 11.2125 15.7875C11.3542 15.9292 11.5333 16 11.75 16C11.9667 16 12.1458 15.9292 12.2875 15.7875C12.4292 15.6458 12.5 15.4667 12.5 15.25V6.5C12.4833 5.8 12.2375 5.20833 11.7625 4.725C11.2875 4.24167 10.7 4 10 4C9.3 4 8.70833 4.24167 8.225 4.725C7.74167 5.20833 7.5 5.8 7.5 6.5V15.75C7.48333 16.9333 7.89167 17.9375 8.725 18.7625C9.55833 19.5875 10.5667 20 11.75 20C12.9167 20 13.9083 19.5875 14.725 18.7625C15.5417 17.9375 15.9667 16.9333 16 15.75V6H18V15.75Z" fill="currentColor"/>
</svg>
</span>
</a>
</div>
<div class="col-date"
<div class="row-cell" style="width: 120px;" data-label="등록일"
th:text="${#temporals.format(notice.createdDate, 'yyyy.MM.dd')}">2025.01.01</div>
</div>
</div>
</div>
<!-- Empty State -->
<div class="table-empty" th:if="${portalNotices.isEmpty()}">
<div class="empty-icon">
<img th:src="@{/img/img_nodata.png}" alt="데이터 없음">
</div>
<p class="empty-text">조회된 데이터가 없습니다.</p>
<div class="user-empty-state" th:if="${portalNotices.isEmpty()}">
<h3>조회된 공지사항이 없습니다</h3>
</div>
<!-- Pagination -->
<div class="pagination" th:replace="~{fragment/pagination :: pagination(jsFunction='fn_select_page')}">
</div>
</div>
</div>
</section>
</th:block>
</body>
@@ -105,3 +107,4 @@
});
</script>
</th:block>
</html>