사용자 최근 작성 글 조회 기능 추가:
- 최근 3건 조회 서비스/페이사드/리포지토리 구현 - HTML 아코디언 UI 및 스타일 추가
This commit is contained in:
+1
@@ -40,6 +40,7 @@ public class PartnershipApplicationController {
|
||||
|
||||
model.addAttribute("partnership", new PartnershipApplicationDTO());
|
||||
model.addAttribute("isInternalUser", UserTypeUtil.isCurrentUserInternal());
|
||||
model.addAttribute("recentApplications", partnershipApplicationFacade.getMyRecentApplications());
|
||||
return "apps/community/mainPartnershipForm";
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -2,8 +2,10 @@ package com.eactive.apim.portal.apps.community.partnership.mapper;
|
||||
|
||||
|
||||
import com.eactive.apim.portal.apps.community.partnership.dto.PartnershipApplicationDTO;
|
||||
import com.eactive.apim.portal.apps.community.partnership.dto.PartnershipApplicationSummaryDTO;
|
||||
import com.eactive.apim.portal.common.mapper.CommonMapper;
|
||||
import com.eactive.apim.portal.partnershipapplication.entity.PartnershipApplication;
|
||||
import java.util.List;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -16,4 +18,8 @@ import org.springframework.stereotype.Component;
|
||||
public interface PartnershipApplicationMapper {
|
||||
|
||||
PartnershipApplication toEntity(PartnershipApplicationDTO dto);
|
||||
|
||||
PartnershipApplicationSummaryDTO toSummaryDto(PartnershipApplication entity);
|
||||
|
||||
List<PartnershipApplicationSummaryDTO> toSummaryDtoList(List<PartnershipApplication> entities);
|
||||
}
|
||||
|
||||
+7
@@ -2,6 +2,7 @@ package com.eactive.apim.portal.apps.community.partnership.repository;
|
||||
|
||||
import com.eactive.apim.portal.partnershipapplication.entity.PartnershipApplication;
|
||||
import com.eactive.eai.rms.data.EMSDataSource;
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
@@ -9,4 +10,10 @@ import org.springframework.stereotype.Repository;
|
||||
@Repository
|
||||
@EMSDataSource
|
||||
public interface PartnershipApplicationRepository extends JpaRepository<PartnershipApplication, String>, JpaSpecificationExecutor<PartnershipApplication> {
|
||||
|
||||
/**
|
||||
* 특정 작성자(createdBy)가 등록한 최근 3건을 최신순으로 조회한다.
|
||||
* createdBy 는 PersonalDataEncryptConverter 로 결정적 암호화되므로 평문 사용자 id 로 등가 조회가 가능하다.
|
||||
*/
|
||||
List<PartnershipApplication> findTop3ByCreatedByOrderByCreatedDateDesc(String createdBy);
|
||||
}
|
||||
|
||||
+7
@@ -1,9 +1,16 @@
|
||||
package com.eactive.apim.portal.apps.community.partnership.service;
|
||||
|
||||
import com.eactive.apim.portal.apps.community.partnership.dto.PartnershipApplicationDTO;
|
||||
import com.eactive.apim.portal.apps.community.partnership.dto.PartnershipApplicationSummaryDTO;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public interface PartnershipApplicationFacade {
|
||||
|
||||
void createPartnershipApplication(PartnershipApplicationDTO partnershipApplicationDTO) throws IOException;
|
||||
|
||||
/**
|
||||
* 현재 로그인 사용자가 작성한 최근 3건을 조회한다. 미인증이면 빈 목록.
|
||||
*/
|
||||
List<PartnershipApplicationSummaryDTO> getMyRecentApplications();
|
||||
}
|
||||
|
||||
+13
@@ -1,6 +1,7 @@
|
||||
package com.eactive.apim.portal.apps.community.partnership.service;
|
||||
|
||||
import com.eactive.apim.portal.apps.community.partnership.dto.PartnershipApplicationDTO;
|
||||
import com.eactive.apim.portal.apps.community.partnership.dto.PartnershipApplicationSummaryDTO;
|
||||
import com.eactive.apim.portal.apps.community.partnership.mapper.PartnershipApplicationMapper;
|
||||
import com.eactive.apim.portal.common.user.PortalAuthenticatedUser;
|
||||
import com.eactive.apim.portal.common.util.SecurityUtil;
|
||||
@@ -15,7 +16,9 @@ import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@@ -60,4 +63,14 @@ public class PartnershipApplicationFacadeImpl implements PartnershipApplicationF
|
||||
}
|
||||
portalAdminNotifier.notifyPortalAdmins(MessageCode.PARTNERSHIP_CREATED, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PartnershipApplicationSummaryDTO> getMyRecentApplications() {
|
||||
PortalAuthenticatedUser user = SecurityUtil.getPortalAuthenticatedUser();
|
||||
if (user == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<PartnershipApplication> recent = partnershipApplicationService.findRecentByCreatedBy(user.getId());
|
||||
return partnershipApplicationMapper.toSummaryDtoList(recent);
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -2,6 +2,7 @@ package com.eactive.apim.portal.apps.community.partnership.service;
|
||||
|
||||
import com.eactive.apim.portal.apps.community.partnership.repository.PartnershipApplicationRepository;
|
||||
import com.eactive.apim.portal.partnershipapplication.entity.PartnershipApplication;
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -21,4 +22,12 @@ public class PartnershipApplicationService {
|
||||
public void createPartnershipApplication(PartnershipApplication partnershipApplication) {
|
||||
partnershipApplicationRepository.save(partnershipApplication);
|
||||
}
|
||||
|
||||
/**
|
||||
* 작성자 id 로 최근 등록 3건 조회(최신순).
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public List<PartnershipApplication> findRecentByCreatedBy(String createdBy) {
|
||||
return partnershipApplicationRepository.findTop3ByCreatedByOrderByCreatedDateDesc(createdBy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,23 @@
|
||||
</section>
|
||||
|
||||
<th:block layout:fragment="contentFragment">
|
||||
<style>
|
||||
.recent-apps { margin: 0 0 24px; }
|
||||
.recent-apps-title { font-size: 15px; font-weight: 600; color: #334155; margin: 0 0 10px; }
|
||||
.recent-apps-list { list-style: none; margin: 0; padding: 0; border: 1px solid #E2E8F0; border-radius: 8px; overflow: hidden; }
|
||||
.recent-apps-item + .recent-apps-item { border-top: 1px solid #E2E8F0; }
|
||||
.recent-apps-head { display: flex; align-items: center; gap: 12px; width: 100%; padding: 14px 16px;
|
||||
background: #F8FAFC; border: 0; cursor: pointer; text-align: left; font: inherit; }
|
||||
.recent-apps-head:hover { background: #F1F5F9; }
|
||||
.recent-apps-subject { flex: 1; min-width: 0; font-size: 14px; font-weight: 500; color: #1E293B;
|
||||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.recent-apps-date { flex-shrink: 0; font-size: 12px; color: #94A3B8; }
|
||||
.recent-apps-arrow { flex-shrink: 0; color: #94A3B8; transition: transform .2s ease; }
|
||||
.recent-apps-item.is-open .recent-apps-arrow { transform: rotate(180deg); }
|
||||
.recent-apps-body { display: none; padding: 14px 16px; background: #fff; }
|
||||
.recent-apps-item.is-open .recent-apps-body { display: block; }
|
||||
.recent-apps-detail { margin: 0; font-size: 13px; line-height: 1.6; color: #475569; white-space: pre-wrap; word-break: break-word; }
|
||||
</style>
|
||||
<section class="inquiry-form-container">
|
||||
|
||||
<!-- Title Bar -->
|
||||
@@ -19,6 +36,27 @@
|
||||
<span class="register-subtitle">DJBank은 온라인 비즈니스 혁신을 위한 피드백/개선요청을 환영합니다.</span>
|
||||
</div>
|
||||
|
||||
<!-- 내가 작성한 최근 글(최대 3건) 아코디언 -->
|
||||
<div class="recent-apps" th:if="${recentApplications != null and !recentApplications.isEmpty()}">
|
||||
<p class="recent-apps-title">내가 작성한 최근 글</p>
|
||||
<ul class="recent-apps-list">
|
||||
<li class="recent-apps-item" th:each="item : ${recentApplications}">
|
||||
<button type="button" class="recent-apps-head">
|
||||
<span class="recent-apps-subject" th:text="${item.bizSubject}">제목</span>
|
||||
<span class="recent-apps-date"
|
||||
th:text="${item.createdDate != null ? #temporals.format(item.createdDate, 'yyyy.MM.dd') : ''}">2026.07.13</span>
|
||||
<svg class="recent-apps-arrow" width="18" height="18" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="recent-apps-body">
|
||||
<p class="recent-apps-detail" th:text="${item.bizDetail}">내용</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Form Content -->
|
||||
<div class="register-form-container">
|
||||
<form name="partnershipForm" id="partnershipForm" th:action="@{/partnership}" th:object="${partnership}"
|
||||
@@ -131,6 +169,13 @@
|
||||
</script>
|
||||
<script th:inline="javascript">
|
||||
$(function () {
|
||||
// 최근 글 아코디언 토글
|
||||
document.querySelectorAll('.recent-apps-head').forEach(function (head) {
|
||||
head.addEventListener('click', function () {
|
||||
head.closest('.recent-apps-item').classList.toggle('is-open');
|
||||
});
|
||||
});
|
||||
|
||||
const btnSubmit = document.querySelector('.btn-submit-form');
|
||||
const fileInput = document.getElementById('file');
|
||||
const fileDisplayText = document.getElementById('fileDisplayText');
|
||||
|
||||
Reference in New Issue
Block a user