문의하기 스타일 적용

This commit is contained in:
현성필
2025-12-04 15:59:35 +09:00
parent dacae095c5
commit b1dbd4845e
6 changed files with 854 additions and 344 deletions
@@ -1,111 +1,81 @@
<!doctype html>
<!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">
<!-- Inquiry Detail Page -->
<div class="inquiry-page">
<div class="inquiry-container">
<!-- Page Header -->
<div class="inquiry-header">
<h1 class="page-title">Q&A</h1>
<p class="page-description">문의 내용을 확인하세요.</p>
</div>
<!-- Inquiry Detail Card -->
<div class="inquiry-detail-card">
<div class="detail-header">
<div class="status-wrapper">
<span class="status-badge-header"
th:classappend="${inquiry.inquiryStatus == 'RESPONDED' ? 'status-completed' : 'status-pending'}"
th:text="${inquiry.inquiryStatus == 'RESPONDED' ? '답변완료' : '문의중'}">
문의중
</span>
</div>
<h2 class="inquiry-title" th:text="${inquiry.inquirySubject}">질문 제목</h2>
<div class="inquiry-meta">
<div class="meta-item">
<i class="fas fa-calendar-alt"></i>
<span>등록일</span>
<strong th:text="${#temporals.format(inquiry.createdDate, 'yyyy-MM-dd HH:mm')}">2025.01.01 10:00</strong>
</div>
<div class="meta-item">
<i class="fas fa-user"></i>
<span>작성자</span>
<strong th:text="${inquiry.maskedInquirerName}">홍**</strong>
</div>
</div>
</div>
<!-- Attachment Section -->
<div class="detail-attachment" th:if="${!#strings.isEmpty(inquiry.attachFile)}">
<div class="attachment-icon">
<i class="fas fa-paperclip"></i>
</div>
<div class="attachment-list" th:with="fileInfo=${@fileService.findById(inquiry.attachFile)}">
<a class="attachment-item"
th:each="fileDetail : ${fileInfo.getFileDetails()}"
th:href="'javascript:fn_downloadFile(\\'' + ${fileDetail.fileId} + '\\',\\''+ ${fileDetail.fileSn} +'\\')'">
<i class="fas fa-file"></i>
<span>[[${fileDetail.originalFileName}]].[[${fileDetail.fileExtension}]]</span>
</a>
</div>
</div>
<!-- Inquiry Content -->
<div class="detail-content" style="white-space: pre-line;">
<th:block th:utext="${inquiry.inquiryDetail}"></th:block>
</div>
</div>
<!-- Admin Response Card -->
<div class="inquiry-response-card" th:if="${inquiry.inquiryStatus == 'RESPONDED'}">
<div class="response-header">
<div class="response-title">
<i class="fas fa-comment-dots"></i>
<span>관리자 답변</span>
</div>
<div class="response-meta">
<span th:text="${inquiry.responderName}">관리자</span>
<span class="meta-separator"></span>
<span th:text="${#temporals.format(inquiry.responseDate, 'yyyy-MM-dd HH:mm')}">2025.01.02 14:30</span>
</div>
</div>
<div class="response-content">
<th:block class="responseDetail" th:utext="${inquiry.responseDetail}"></th:block>
</div>
</div>
<!-- Action Buttons -->
<div class="inquiry-actions">
<div class="actions-left">
<a th:href="@{/inquiry}" class="action-btn-secondary">
<i class="fas fa-list"></i>
<span>목록</span>
</a>
</div>
<div class="actions-right" th:if="${inquiry.inquiryStatus != 'RESPONDED' && inquiry.inquirer.id == #authentication.principal.id}">
<form id="deleteForm" th:action="@{/inquiry/{id}/delete(id=${inquiry.id})}" method="post" style="display: inline;"></form>
<a th:href="@{/inquiry/edit(id=${inquiry.id})}" class="action-btn-edit">
<i class="fas fa-edit"></i>
<span>수정</span>
</a>
<a href="#" class="action-btn-delete" onclick="confirmDelete(); return false;">
<i class="fas fa-trash-alt"></i>
<span>삭제</span>
</a>
</div>
</div>
</div>
<section layout:fragment="title">
<div class="page-title-banner">
<img th:src="@{/img/img_title_bg.png}" class="title-image" alt="타이틀 배경">
<h1>Q&A</h1>
</div>
</section>
<section layout:fragment="contentFragment">
<div class="inquiry-detail-container">
<!-- Inquiry Header: Status Badge and Title -->
<div class="inquiry-detail-header">
<div class="inquiry-header-top">
<span class="inquiry-status-badge"
th:classappend="${inquiry.inquiryStatus == 'RESPONDED' ? 'inquiry-status-badge--completed' : 'inquiry-status-badge--pending'}"
th:text="${inquiry.inquiryStatus == 'RESPONDED' ? '답변완료' : '답변대기'}">
답변대기
</span>
<span class="inquiry-detail-date" th:text="${#temporals.format(inquiry.createdDate, 'yyyy.MM.dd')}">2025.11.01</span>
</div>
<h2 class="inquiry-detail-title" th:text="${inquiry.inquirySubject}">질문 제목</h2>
</div>
<!-- Attachment Section -->
<div class="inquiry-detail-attachment" th:if="${!#strings.isEmpty(inquiry.attachFile)}">
<div class="attachment-list" th:with="fileInfo=${@fileService.findById(inquiry.attachFile)}">
<div class="attachment-item" th:each="fileDetail : ${fileInfo.getFileDetails()}">
<a th:href="'javascript:fn_downloadFile(\'' + ${fileDetail.fileId} + '\',\''+ ${fileDetail.fileSn} +'\')'" class="inquiry-attachment-link">
<svg width="22" height="22" 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 class="attachment-label">첨부파일</span>
<span class="attachment-filename">[[${fileDetail.originalFileName}]].[[${fileDetail.fileExtension}]]</span>
</a>
</div>
</div>
</div>
<!-- Inquiry Content Section -->
<div class="inquiry-detail-content">
<div id="inquiryDetail" class="inquiry-content-body" th:utext="${inquiry.inquiryDetail}">
문의 내용이 여기에 표시됩니다.
</div>
</div>
<!-- Admin Response Section -->
<div class="inquiry-response-section" th:if="${inquiry.inquiryStatus == 'RESPONDED'}">
<div class="inquiry-response-header">
<span class="response-label">관리자 답변</span>
<span class="response-date" th:text="${#temporals.format(inquiry.responseDate, 'yyyy.MM.dd')}">2025.11.02</span>
</div>
<div class="inquiry-response-body" id="responseDetail" th:utext="${inquiry.responseDetail}">
답변 내용이 여기에 표시됩니다.
</div>
</div>
<!-- Action Buttons -->
<div class="inquiry-detail-actions">
<div class="actions-left">
<button type="button" class="btn-inquiry-list" th:onclick="|location.href='@{/inquiry}'|">목록</button>
</div>
<div class="actions-right" th:if="${inquiry.inquiryStatus != 'RESPONDED' && inquiry.inquirer.id == #authentication.principal.id}">
<form id="deleteForm" th:action="@{/inquiry/{id}/delete(id=${inquiry.id})}" method="post" style="display: none;"></form>
<button type="button" class="btn-inquiry-edit" th:onclick="|location.href='@{/inquiry/edit(id=${inquiry.id})}'|">수정</button>
<button type="button" class="btn-inquiry-delete" onclick="confirmDelete()">삭제</button>
</div>
</div>
</div>
</section>
</th:block>
</body>
<th:block layout:fragment="contentScript">
<script th:inline="javascript">
$(document).ready(function() {
@@ -136,11 +106,15 @@
}
document.addEventListener('DOMContentLoaded', function() {
var elements = document.querySelectorAll('.responseDetail');
var inquiryElement = document.getElementById('inquiryDetail');
if (inquiryElement) {
inquiryElement.innerHTML = decodeHTMLEntities(inquiryElement.innerHTML);
}
elements.forEach(function(element) {
element.innerHTML = decodeHTMLEntities(element.innerHTML);
});
var responseElement = document.getElementById('responseDetail');
if (responseElement) {
responseElement.innerHTML = decodeHTMLEntities(responseElement.innerHTML);
}
});
</script>
</th:block>
@@ -1,115 +1,120 @@
<!doctype html>
<!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>
<section layout:fragment="title">
<div class="page-title-banner">
<img th:src="@{/img/img_title_bg.png}" class="title-image" alt="타이틀 배경">
<h1>Q&A</h1>
</div>
</section>
<th:block layout:fragment="contentFragment" th:with="isNew=${inquiry.id == null}">
<section class="inquiry-form-container">
<!-- Inquiry Form Page -->
<div class="inquiry-page">
<div class="inquiry-container">
<!-- Title Bar -->
<div class="register-title-bar">
<h2 class="register-title" th:text="${isNew ? '질문하기' : '질문 수정'}">질문하기</h2>
<span class="register-subtitle">궁금하신 사항을 작성해 주세요.</span>
</div>
<!-- Page Header -->
<div class="inquiry-header">
<h1 class="page-title" th:text="${isNew ? 'Q&A 질문하기' : 'Q&A 질문 수정'}">Q&A 질문하기</h1>
<p class="page-description">궁금하신 사항을 작성해 주세요.</p>
</div>
<!-- Form Content -->
<div class="register-form-container">
<form name="inquiryForm" id="inquiryForm" th:action="${isNew}? @{/inquiry} : @{/inquiry/edit}"
th:object="${inquiry}" enctype="multipart/form-data" method="post" class="register-form">
<input type="hidden" th:field="*{id}" th:if="${!isNew}">
<!-- Inquiry Form Card -->
<div class="inquiry-form-card">
<form name="inquiryForm" id="inquiryForm" th:action="${isNew}? @{/inquiry} : @{/inquiry/edit}"
th:object="${inquiry}" enctype="multipart/form-data" method="post">
<input type="hidden" th:field="*{id}" th:if="${!isNew}">
<!-- Subject Field -->
<div class="form-group">
<label for="inquirySubject" class="form-label required">
<span>제목</span>
</label>
<div class="form-input-wrapper">
<input type="text"
id="inquirySubject"
th:field="*{inquirySubject}"
class="form-input"
placeholder="제목을 입력하세요"
required>
</div>
<!-- Subject Field -->
<div class="form-row">
<div class="form-label-wrapper label-offset">
<span class="form-label-text">제목</span>
<span class="required-badge">필수</span>
</div>
<!-- Content Field -->
<div class="form-group">
<label for="inquiryDetail" class="form-label required">
<span>내용</span>
</label>
<div class="form-input-wrapper">
<textarea id="inquiryDetail"
th:field="*{inquiryDetail}"
class="form-textarea"
rows="10"
placeholder="내용을 입력하세요"
required></textarea>
</div>
<div class="form-field-wrapper">
<input type="text"
id="inquirySubject"
th:field="*{inquirySubject}"
class="form-input"
placeholder="제목을 입력하세요"
required
maxlength="200">
</div>
</div>
<!-- File Upload Field -->
<div class="form-group">
<label for="file" class="form-label">
<span>첨부파일</span>
</label>
<div class="form-input-wrapper">
<div class="file-upload-wrapper">
<input type="text"
class="form-input file-name-display"
th:class="${!#strings.isEmpty(inquiry.attachFile)} ? 'form-input file-name-display has-file' : 'form-input file-name-display'"
th:value="${!#strings.isEmpty(inquiry.attachFile)} ? ${@fileService.findById(inquiry.attachFile).fileDetails[0].originalFileName + '.' + @fileService.findById(inquiry.attachFile).fileDetails[0].fileExtension} : ''"
placeholder="파일을 선택하세요"
readonly>
<input type="hidden" th:field="*{attachFile}">
<label for="file" class="file-upload-btn">
<i class="fas fa-paperclip"></i>
<span>파일 선택</span>
</label>
<input type="file"
id="file"
name="files"
accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.hwp,.gif,.jpg,.png"
style="display: none;">
<button type="button" class="file-remove-btn" style="display: none;">
<i class="fas fa-times"></i>
<!-- Content Field -->
<div class="form-row">
<div class="form-label-wrapper">
<span class="form-label-text">내용</span>
<span class="required-badge">필수</span>
</div>
<div class="form-field-wrapper">
<textarea id="inquiryDetail"
th:field="*{inquiryDetail}"
class="form-textarea"
rows="10"
placeholder="내용을 입력하세요"
required
maxlength="2000"></textarea>
<small class="char-counter-wrapper">
<span class="char-counter">0 / 2000</span>
</small>
</div>
</div>
<!-- File Upload Field - Figma Design (node 1029-1507) -->
<div class="form-row">
<div class="form-label-wrapper label-offset">
<span class="form-label-text">첨부파일</span>
</div>
<div class="form-field-wrapper">
<div class="file-upload-inline">
<div class="file-input-display" id="fileInputDisplay">
<span class="file-display-text" id="fileDisplayText">선택된 파일이 없습니다</span>
<button type="button" class="btn-remove-file-inline" id="btnRemoveFile" title="파일 삭제" style="display: none;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<div class="form-help-text">
<!-- <p><i class="fas fa-info-circle"></i> 첨부파일은 10MB 이내로 등록해 주세요.</p>-->
<!-- <p><i class="fas fa-info-circle"></i> 문서파일과 이미지 파일만 등록 가능합니다. (pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)</p>-->
<p><i class="fas fa-check-circle"></i>
<span th:text="'첨부파일은 ' + ${@portalProperties.file.maxSize} + ' 이내로 등록해 주세요.'">첨부파일은 8MB 이내로 등록해 주세요.</span>
</p>
<p>
<i class="fas fa-check-circle"></i>
문서파일과 이미지 파일만 등록 가능합니다. (pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)
</p>
</div>
<button type="button" class="btn-file-attach" onclick="document.getElementById('file').click()">
<svg width="22" height="22" 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>
파일첨부
</button>
<input type="hidden" th:field="*{attachFile}">
<input type="file"
id="file"
name="files"
accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.hwp,.gif,.jpg,.jpeg,.png"
style="display: none;">
</div>
<div class="form-help-text">
<p><i class="fas fa-check-circle"></i>
<span th:text="'첨부파일은 ' + ${@portalProperties.file.maxSize} + ' 이내로 등록해 주세요.'">첨부파일은 8MB 이내로 등록해 주세요.</span>
</p>
<p>
<i class="fas fa-check-circle"></i>
문서파일과 이미지 파일만 등록 가능합니다. (pdf, doc, docx, xls, xlsx, ppt, pptx, hwp, gif, jpg, png)
</p>
</div>
</div>
</div>
<!-- Form Actions -->
<div class="inquiry-form-actions">
<a th:href="@{/inquiry}" class="action-btn-secondary">
<i class="fas fa-times"></i>
<span>취소</span>
</a>
<button type="button" class="action-btn-primary btn-submit">
<i class="fas fa-check"></i>
<span>확인</span>
</button>
</div>
</form>
</div>
</form>
</div>
</div>
<!-- Form Actions -->
<div class="form-actions">
<button type="button" class="btn btn-submit btn-secondary" th:onclick="|location.href='@{/inquiry}'|">취소</button>
<button type="button" class="btn btn-submit btn-primary btn-submit-form">
<span th:text="${isNew ? '등록' : '수정'}">등록</span>
</button>
</div>
</section>
</th:block>
</body>
@@ -117,25 +122,57 @@
<script th:if="${error}" th:inline="javascript">
$(document).ready(function () {
const errorMsg = [[${error}]];
const formattedMsg = errorMsg.replace(/\n/g,'<br>');
$('#customAlertMessage').html(formattedMsg);
$('#customAlert').css('display','flex');
customPopups.showAlert(errorMsg);
});
</script>
<script th:inline="javascript">
$(function () {
let btnSubmit = document.querySelector('.btn-submit');
let fileInput = document.getElementById('file');
let fileNameDisplay = document.querySelector('.file-name-display');
let fileRemoveBtn = document.querySelector('.file-remove-btn');
const btnSubmit = document.querySelector('.btn-submit-form');
const fileInput = document.getElementById('file');
const fileDisplayText = document.getElementById('fileDisplayText');
const fileInputDisplay = document.getElementById('fileInputDisplay');
const btnRemoveFile = document.getElementById('btnRemoveFile');
const attachFileInput = document.querySelector('input[name="attachFile"]');
const inquiryDetailTextarea = document.getElementById('inquiryDetail');
const charCounter = document.querySelector('.char-counter');
// Initialize character counter
if (inquiryDetailTextarea && charCounter) {
const currentLength = inquiryDetailTextarea.value.length;
const maxLength = inquiryDetailTextarea.getAttribute('maxlength');
charCounter.textContent = currentLength + ' / ' + maxLength;
// Character counter for textarea
inquiryDetailTextarea.addEventListener('input', function() {
const currentLength = this.value.length;
const maxLength = this.getAttribute('maxlength');
charCounter.textContent = currentLength + ' / ' + maxLength;
// Change color when near limit
if (currentLength > maxLength * 0.9) {
charCounter.style.color = '#FF6B6B';
} else {
charCounter.style.color = '#94A3B8';
}
});
}
// Show existing file if present
const existingFile = /*[[${!#strings.isEmpty(inquiry.attachFile) ? @fileService.findById(inquiry.attachFile).fileDetails[0].originalFileName + '.' + @fileService.findById(inquiry.attachFile).fileDetails[0].fileExtension : ''}]]*/ '';
if (existingFile) {
fileDisplayText.textContent = existingFile;
fileDisplayText.classList.add('has-file');
fileInputDisplay.classList.add('has-file');
btnRemoveFile.style.display = 'flex';
}
// Form submission handler
btnSubmit.addEventListener('click', function (event) {
event.preventDefault();
let form = document.getElementById('inquiryForm');
let inquirySubject = document.getElementById('inquirySubject').value.trim();
let inquiryDetail = document.getElementById('inquiryDetail').value;
const form = document.getElementById('inquiryForm');
const inquirySubject = document.getElementById('inquirySubject').value.trim();
const inquiryDetail = document.getElementById('inquiryDetail').value;
// Validation
if (!inquirySubject) {
@@ -163,30 +200,36 @@
if (!allowedExtensions.includes(fileExt)) {
customPopups.showAlert("허용된 파일 형식이 아닙니다.\n문서파일(pdf, doc, docx, xls, xlsx, ppt, pptx, hwp)과 이미지 파일(gif, jpg, png)만 등록 가능합니다.");
fileInput.value = '';
fileNameDisplay.value = '';
fileNameDisplay.classList.remove('has-file');
fileRemoveBtn.style.display = 'none';
return;
}
fileNameDisplay.value = file.name;
fileNameDisplay.classList.add('has-file');
fileRemoveBtn.style.display = 'flex';
// Show file name in display
fileDisplayText.textContent = file.name;
fileDisplayText.classList.add('has-file');
fileInputDisplay.classList.add('has-file');
btnRemoveFile.style.display = 'flex';
// Clear existing attachFile if new file selected
if (attachFileInput) {
attachFileInput.value = '';
}
}
});
// File remove handler
fileRemoveBtn.addEventListener('click', function () {
btnRemoveFile.addEventListener('click', function (e) {
e.stopPropagation();
fileInput.value = '';
fileNameDisplay.value = '';
fileNameDisplay.classList.remove('has-file');
fileRemoveBtn.style.display = 'none';
});
fileDisplayText.textContent = '선택된 파일이 없습니다';
fileDisplayText.classList.remove('has-file');
fileInputDisplay.classList.remove('has-file');
btnRemoveFile.style.display = 'none';
// Show remove button if file already exists
if (fileNameDisplay.value) {
fileRemoveBtn.style.display = 'flex';
}
// Clear attachFile hidden input
if (attachFileInput) {
attachFileInput.value = '';
}
});
// Focus on subject field
document.getElementById('inquirySubject').focus();
@@ -1,139 +1,141 @@
<!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>
<section layout:fragment="title">
<div class="page-title-banner">
<img th:src="@{/img/img_title_bg.png}" class="title-image" alt="타이틀 배경">
<h1>Q&A</h1>
</div>
</section>
<th:block layout:fragment="contentFragment">
<!-- Inquiry List Page -->
<div class="inquiry-page">
<div class="inquiry-container">
<section class="user-management-container">
<!-- Page Header -->
<div class="inquiry-header">
<h1 class="page-title">Q&A</h1>
<p class="page-description">궁금하신 사항을 문의하고 답변을 확인하세요.</p>
</div>
<!-- Search and Filter Controls -->
<form name="inquiryForm" th:action="@{/inquiry}" method="get" onsubmit="return false;">
<input type="hidden" name="page" value="1">
<input name="searchCnd" type="hidden" value="0">
<!-- Search and Filter Controls -->
<form name="inquiryForm" th:action="@{/inquiry}" method="get" onsubmit="return false;">
<input type="hidden" name="page" value="1">
<input name="searchCnd" type="hidden" value="0">
<div class="table-controls">
<div class="total-count">
<strong th:text="${page.totalElements}">0</strong>
</div>
<div class="search-box">
<input type="text"
name="searchWrd"
th:value="${search.searchWrd}"
placeholder="제목 또는 내용으로 검색">
<button type="button" class="btn btn-primary" onclick="fn_search_inquiry()">
<i class="fas fa-search"></i>
<span>검색</span>
</button>
</div>
</div>
</form>
<!-- Inquiry Table -->
<div class="inquiry-list-wrapper" th:if="${!inquiries.isEmpty()}">
<div class="inquiry-table">
<!-- Table Header -->
<div class="table-header">
<div class="col-num">NO</div>
<div class="col-title">제목</div>
<div class="col-name">작성자</div>
<div class="col-status">처리상태</div>
<div class="col-date">등록일</div>
</div>
<!-- Table Rows -->
<div class="table-row"
th:each="inquiry, status : ${inquiries}"
th:onclick="'location.href=\'' + @{/inquiry/detail(id=${inquiry.id})} + '\''">
<div class="col-num"
th:text="${page.totalElements - (page.number * page.size) - status.index}">1</div>
<div class="col-title">
<a th:href="@{/inquiry/detail(id=${inquiry.id})}">
<span th:text="${inquiry.inquirySubject}">질문 제목</span>
<span class="file-icon" th:if="${!#strings.isEmpty(inquiry.attachFile)}">
<img th:src="@{/img/icon/icon_file.png}" alt="첨부파일">
</span>
</a>
</div>
<div class="col-name" th:text="${inquiry.maskedInquirerName}">홍**</div>
<div class="col-status">
<span class="status-badge"
th:classappend="${inquiry.inquiryStatus == 'RESPONDED' ? 'status-completed' : 'status-pending'}"
th:text="${inquiry.inquiryStatus == 'RESPONDED' ? '답변완료' : '문의중'}">
문의중
</span>
</div>
<div class="col-date"
th:text="${#temporals.format(inquiry.createdDate, 'yyyy.MM.dd')}">2025.01.01</div>
</div>
</div>
</div>
<!-- Empty State -->
<div class="table-empty" th:if="${inquiries.isEmpty()}">
<div class="empty-icon">
<img th:src="@{/img/img_nodata.png}" alt="데이터 없음">
</div>
<p class="empty-text">조회된 검색 결과가 없습니다.</p>
</div>
<!-- Pagination -->
<div class="pagination" th:replace="~{fragment/pagination :: pagination(jsFunction='fn_select_page')}">
</div>
<!-- New Inquiry Button -->
<div class="inquiry-actions">
<a th:href="@{/inquiry/new}" class="btn btn-primary">
<i class="fas fa-pen"></i>
<span>질문하기</span>
</a>
</div>
<div class="table-controls">
<h2 class="total-count">
<strong th:text="${page.totalElements}">0</strong>
</h2>
<div class="search-field">
<input type="text"
name="searchWrd"
th:value="${search.searchWrd}"
placeholder="제목 또는 내용으로 검색"
onkeypress="if(event.keyCode === 13) { fn_search_inquiry(); return false; }">
<button type="button" class="search-field-btn" onclick="fn_search_inquiry()">
<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>
<!-- Inquiry Table -->
<div class="list-table" th:if="${!inquiries.isEmpty()}">
<!-- Table Header -->
<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: 100px;">작성자</div>
<div class="header-cell" style="width: 120px;">처리상태</div>
<div class="header-cell" style="width: 120px;">등록일</div>
</div>
<!-- Table Body -->
<div class="list-table-body">
<div class="list-table-row"
th:each="inquiry, status : ${inquiries}"
th:onclick="'location.href=\'' + @{/inquiry/detail(id=${inquiry.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="row-cell row-cell--title" style="flex: 1; min-width: 200px;" data-label="제목">
<a th:href="@{/inquiry/detail(id=${inquiry.id})}" class="notice-title-link">
<span class="notice-number" th:text="|[${page.totalElements - (page.number * page.size) - status.index}]|">[1]</span>
<span th:text="${inquiry.inquirySubject}">질문 제목</span>
<span class="file-icon" th:if="${!#strings.isEmpty(inquiry.attachFile)}">
<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="row-cell" style="width: 100px;" data-label="작성자" th:text="${inquiry.maskedInquirerName}">홍**</div>
<div class="row-cell" style="width: 120px;" data-label="처리상태">
<span class="inquiry-status-badge"
th:classappend="${inquiry.inquiryStatus == 'RESPONDED' ? 'inquiry-status-badge--completed' : 'inquiry-status-badge--pending'}"
th:text="${inquiry.inquiryStatus == 'RESPONDED' ? '답변완료' : '답변대기'}">
답변대기
</span>
</div>
<div class="row-cell" style="width: 120px;" data-label="등록일"
th:text="${#temporals.format(inquiry.createdDate, 'yyyy.MM.dd')}">2025.01.01</div>
</div>
</div>
</div>
<!-- Empty State -->
<div class="user-empty-state" th:if="${inquiries.isEmpty()}">
<div class="empty-icon">
<img th:src="@{/img/img_nodata.png}" alt="데이터 없음">
</div>
<h3>조회된 Q&A가 없습니다</h3>
<p>검색 조건을 변경하거나 새로운 질문을 등록해주세요.</p>
</div>
<!-- Pagination -->
<div class="pagination" th:replace="~{fragment/pagination :: pagination(jsFunction='fn_select_page')}">
</div>
<!-- New Inquiry Button -->
<div class="inquiry-actions">
<a th:href="@{/inquiry/new}" class="btn btn-primary btn-lg">
<span>질문하기</span>
</a>
</div>
</section>
</th:block>
</body>
<th:block layout:fragment="contentScript">
<script th:inline="javascript">
$(document).ready(function () {
var successMsg = [[${success}]];
console.log("Success message:", successMsg); // 디버깅용
if (successMsg) {
console.log("Showing alert"); // 디버깅용
customPopups.showAlert(successMsg);
}
});
</script>
<script>
function fn_init() {
document.inquiryForm.searchCnd.focus();
}
<script th:inline="javascript">
$(document).ready(function () {
var successMsg = [[${success}]];
if (successMsg) {
customPopups.showAlert(successMsg);
}
});
</script>
<script>
function fn_init() {
document.inquiryForm.searchWrd.focus();
}
function fn_select_page(pageNo) {
document.inquiryForm.page.value = pageNo;
document.inquiryForm.submit();
}
function fn_select_page(pageNo) {
document.inquiryForm.page.value = pageNo;
document.inquiryForm.submit();
}
function fn_search_inquiry() {
document.inquiryForm.page.value = 1;
document.inquiryForm.submit();
}
function fn_search_inquiry() {
document.inquiryForm.page.value = 1;
document.inquiryForm.submit();
}
$(function () {
fn_init();
});
</script>
$(function () {
fn_init();
});
</script>
</th:block>
</html>