관리 메뉴

거니의 velog

(11) 마이 플랜 > 여행 정보 검색 페이지 > 코드 리뷰 본문

대덕인재개발원_최종 포트폴리오

(11) 마이 플랜 > 여행 정보 검색 페이지 > 코드 리뷰

Unlimited00 2024. 2. 16. 09:08

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<c:set value="${pageContext.request.contextPath }" var="contextPath" />
<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8" />
        <meta name="author" content="부루마불" />
        <meta name="description" content="대덕인재개발원 7월반 4조 부루마불의 여기갈래 프로젝트입니다." />
        <meta name="keywords" content="부루마불, 여기갈래, 여행, 통합, 플랫폼" />
        <meta name="copyright" content="대덕인재개발원" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>여기갈래 &gt; 마이 플랜</title>
        
        <!-- 사용자 페이지 > 헤더세팅 영역 -->
        <tiles:insertAttribute name="headerSettings" />
    	
    	<!-- 
    		내부 CSS 
    		- 내부 CSS는 외부 CSS의 스타일링을 건드리지 않기 위해서
    		개별적인 페이지에다 스타일을 적용할 때 종종 쓴다.
    		- 보통 프로토타이핑 테스트용이나, FE Leader의 판단에 따라 여기에
    		추가적인 스타일을 작성한다.
    	-->
    	<style>
    		.msub a {
    			color: #333;
    		}
    	</style>
    	
    	<c:if test="${not empty message }">
		    <script type="text/javascript">
		        //alert("${message}");
		        $(function(){
		        	// 성공시
		        	<c:if test="${msgflag eq 'su'}">
		        		Swal.fire({
		                    title: "성공",
		                    text: "${message}",
		                    icon: "success"
		                });
		        	</c:if>
		        	// 실패시
		        	<c:if test="${msgflag eq 'fa'}">
			        	Swal.fire({
		                    title: "실패",
		                    text: "${message}",
		                    icon: "error"
		                });
		        	</c:if>
		        	// 정보성 메시지
		        	<c:if test="${msgflag eq 'in'}">
			        	Swal.fire({
		                    title: "안내",
		                    text: "${message}",
		                    icon: "info"
		                });
		        	</c:if>
		        });
		        <c:remove var="message" scope="request" />
		        <c:remove var="message" scope="session" />
		    </script>
		</c:if>
		
	</head>
    <body class="scroll">
        
        <!-- 사용자 페이지 > 헤더 영역 -->
        <tiles:insertAttribute name="header" />
        
        <!-- 사용자 페이지 > 마이 플랜 구현 영역 -->
        <tiles:insertAttribute name="userMyPlanContainer" />
        
        <!-- 사용자 페이지 > 푸터 영역 -->
		<tiles:insertAttribute name="footer" />
		
		<!-- 사용자 페이지 > 자바스크립트 세팅 영역 -->
		<tiles:insertAttribute name="settings" />

    </body>
</html>

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    
<!-- 여행 정보 css -->
<link href="${contextPath }/resources/css/journeyInfo.css" rel="stylesheet" />

<section class="journeyInfoHeadStyle emptySpace">
	<article>
	    <div class="jourImgBox">
	        <img src="${contextPath }/resources/images/journeyBgImg.jpg" alt="커뮤니티 배경 이미지" />
	    </div>
	    <div>
	        <h3>마이 플랜</h3>
	        <span>MY PLAN</span>
	    </div>
	</article>
</section>

<section class="journeyInfoContainer cen">
	<c:if test="${sessionInfo.memCategory eq '03' }">
	    <button id="journeyRegiBtn" type="button">
	        <i class="fas fa-map-marked-alt"></i>
	    </button>
	</c:if>
    <h3>여행 정보 검색</h3>
    <div class="journeyInfoSearchContents">
        <div>
            <input type="text" class="form-control" id="jourInfoSearch" name="jourInfoSearch" placeholder="도시명으로 검색해보세요." />
            <button type="button" id="searchBtn">
                <i class="fas fa-search"></i>
            </button>
        </div>
    </div>
    <div class="journeyInfoContents">
    	<!-- 반복 구간 -->
    	<c:choose>
    		<c:when test="${not empty journeyList }">
	    		<c:forEach items="${journeyList }" var="journey">
	    			<article>
			            <div class="infoThumbnailBox">
			                <img src="${journey.infoPreviewimg }" alt="여행 정보 썸네일 이미지" />
			            </div>
			            <div>
			                <h4 class="textDrop">${journey.infoEngname }</h4>
			                <span class="infoTitle textDrop">${journey.infoName }</span>
			                <p>
								${journey.infoDescription }
			                </p>
			                <c:if test="${journey.infoFlightyn eq 'y' }">
				                <span class="airportText">
				                    <span>
				                    	<c:if test="${journey.infoFlight eq 'str' }">
				                    		직항
				                    	</c:if>
				                    	<c:if test="${journey.infoFlight eq 'round' }">
				                    		왕복
				                    	</c:if>
				                    </span>
				                    <span>${journey.infoFlighttime }</span>
				                </span>
			                </c:if>
			                <c:if test="${journey.infoVisayn eq 'y' }">
			                	<span class="visaText">
				                    <span>
				                    	<c:if test="${journey.infoVisaexp eq 'visa' }">
				                    		비자
				                    	</c:if>
				                    	<c:if test="${journey.infoVisaexp eq 'none' }">
				                    		무비자
				                    	</c:if>
				                    </span>
				                    <span>${journey.infoVisatime }</span>
				                </span>
			                </c:if>
			                <span class="voltageTxt">
			                	<span>콘센트</span>
			                	<span>${journey.infoVoltage }</span>
			                </span>
			                <span class="infoTimediferTxt">
			                	<span>한국대비</span>
			                	<span>${journey.infoTimedifer }</span>
			                </span>
			                <input type="hidden" class="infoNo" name="infoNo" value="${journey.infoNo }" />
			            </div>
			        </article>
	    		</c:forEach>
    		</c:when>
    		<c:otherwise>
    			<article style="text-align: center; width: 50%; margin: 0px auto; float: none; cursor: auto; background-color: #333; color: white; padding: 20px; border-radius: 4px;">
    				등록된 여행 정보가 없습니다.
    			</article>
    		</c:otherwise>
    	</c:choose>
    </div>
</section>

<!-- 여행 정보 모달창 -->
<section class="infoModalContents">
    <div class="infoModalBox cen">
        <div class="infoModalClose">
            <div></div>
            <div></div>
        </div>
        <article class="infoModalLeft">
            <div>
                <div class="modalInfoSetting">
                    <span>여행 장소(영어)</span>
                    <h5>여행 장소</h5>
                    <p>여행 내용</p>
                </div>
                <div class="infoModalFourSection">
                    <div>
                        <div>
                            <i class="fas fa-plane"></i>
							항공
                        </div>
                        <div>
                            <span>없음</span>
                            <span>-</span>
                        </div>
                    </div>
                    <div>
                        <div>
                            <i class="fas fa-passport"></i>
							비자
                        </div>
                        <div>
                            <span>없음</span>
                            <span>-</span>
                        </div>
                    </div>
                    <div>
                        <div>
                            <i class="fas fa-plug"></i>
							전압
                        </div>
                        <div>
                            <span>콘센트</span>
                            <span>220V</span>
                        </div>
                    </div>
                    <div>
                        <div>
                            <i class="fas fa-clock"></i>
							시차
                        </div>
                        <div>
                            <span>한국대비</span>
                            <span>없음</span>
                        </div>
                    </div>
                </div>
                <a href="/myplan/makeplan.do" class="btn btn-info makePlanSty <c:if test="${empty sessionInfo }">noUserBlockModal</c:if>" style="color: white;">
					일정만들기 
                    <i class="fas fa-chevron-right"></i>
                </a>
                <c:if test="${sessionInfo.memCategory eq '03' }">
	                <div class="journeyInfoBtnGroup">
	                	<input type="hidden" id="choiceInfoNo" name="choiceInfoNo" />
	                	<button type="button" id="journeyInfoModify">
	                		<i class='fas fa-exchange-alt'></i>
	                	</button>
	                	<button type="button" id="journeyInfoDelete">
	                		<i class='fas fa-ban'></i>
	                	</button>
	                </div>
                </c:if>
            </div>
        </article>
        <article class="infoModalRight">
            <div class="infoModalImgBox">
                <img src="${contextPath }/resources/images/Jeju.jpg" alt="여행 정보 이미지" />
            </div>
        </article>
    </div>
</section>

<!-- 여행 정보 js -->
<script defer src="${contextPath }/resources/js/journeyInfo.js"></script>

<script>
    $(function(){
        
    	// 공통 함수
        $.JourneyInfoModalFn();
        $.journeyRegiPageMoveFn();
        $.makeplanClickEvent();
        $.journeyModifyPageMoveFn();
        $.journeyDeletePageMoveFn();
        $.ajaxJourneyInfoSearchFn();
        
        /* 종횡비 함수 */
        $.eachJourneyInfoImgResizeFn();
        
        var infoModalImgBox = $(".infoModalImgBox");
        var infoModalImg = $(".infoModalImgBox img");
        $.ratioBoxH(infoModalImgBox, infoModalImg);
        
        var jourImgBox = $(".jourImgBox");
        var jourImg = $(".jourImgBox img");
        $.ratioBoxH(jourImgBox, jourImg);
        
    });
</script>

/* 여행 정보 스타일 */
.cen {
    width: 1200px;
}

.journeyInfoContainer {
    position: relative;
    padding: 50px 0px 50px;
}

.journeyInfoHeadStyle>article {
    height: 310px;
    position: relative;
}

.jourImgBox {
    position: relative;
    overflow: hidden;
    height: inherit;
}

.jourImgBox img {
	display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.journeyInfoHeadStyle div:last-of-type {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	padding: 20px 50px;
	border-radius: 4px;
	background-color: rgba(255, 255, 255, 0.6);
	text-align: center;
}

.journeyInfoHeadStyle div:last-of-type h3 {
	font-weight: 700;
	font-size: 2.3rem;
}

.journeyInfoHeadStyle div:last-of-type span {
	font-size: 1.3rem;
}

.journeyInfoContainer h3 {
    text-align: center;
    font-size: 1.5rem;
    font-weight: 700;
    padding: 40px 0px 20px;
    margin-bottom: 0px;
}

.journeyInfoSearchContents>div {
    overflow: auto;
    position: relative;
    width: 600px;
    margin: 0px auto;
}

.journeyInfoSearchContents {
    padding: 30px 0px;
}

.journeyInfoSearchContents input,
.journeyInfoSearchContents button {
    float: left;
}

.journeyInfoSearchContents input {
    width: 100%;
}

.journeyInfoSearchContents input::placeholder {
    color: #dee2e6;
}

.journeyInfoSearchContents button {
    display: block;
    width: 20px;
    height: 100%;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    right: 10px;
    border: none;
    background-color: transparent;
    color: #dee2e6;
    transition: all 0.4s;
}

.journeyInfoSearchContents button:hover {
    color: black;
}

.journeyInfoContents {
    overflow: auto;
    margin: 25px 0px;
}

.journeyInfoContents article:hover {
    transform: none!important;
}

.journeyInfoContents article {
    float: left;
    width: calc(100% / 4 - 40px);
    margin: 0px 20px;
    cursor: pointer;
    transition: all 0.4s;
}

.journeyInfoContents article:hover {
    transform: none;
}

.journeyInfoContents .infoThumbnailBox {
	transition: all 0.4s;
}

.journeyInfoContents .infoThumbnailBox:hover {
	box-shadow: 2px 3px 5px #333;
}

.journeyInfoContents .infoThumbnailBox {
    position: relative;
    overflow: hidden;
    height: 320px;
    border-radius: 10px;
}

.journeyInfoContents .infoThumbnailBox img {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.journeyInfoContents h4 {
    margin-bottom: 5px;
}

.journeyInfoContents article>div:last-of-type {
    padding: 20px 0px;
}

.journeyInfoContents article>div:last-of-type span {
    font-weight: 300;
    display: block;
}

.journeyInfoContents article p,
.journeyInfoContents article .airportText,
.journeyInfoContents article .visaText,
.journeyInfoContents article .voltageTxt,
.journeyInfoContents article .infoTimediferTxt {
    display: none!important;
}

/* 여행 정보 모달창 */
.infoModalContents {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: rgba(0,0,0,0.3);
    z-index: 70;
    display: none;
}

.infoModalBox {
    position: absolute;
    top: 55%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: white;
    padding: 60px;
    overflow: auto;
    border-radius: 10px;
}

.infoModalClose {
    width: 30px;
    height: 30px;
    position: absolute;
    top: 20px;
    right: 20px;
    cursor: pointer;
    background-color: rgba(0,0,0,0.4);
    border-radius: 4px;
}

.infoModalClose div {
    width: 25px;
    height: 1px;
    background-color: white;
    position: absolute;
    top: 50%;
    left: 50%;
}

.infoModalClose div:first-of-type {
    transform: translate(-50%, -50%) rotate(45deg);
}

.infoModalClose div:last-of-type {
    transform: translate(-50%, -50%) rotate(-45deg);
}

.infoModalBox article {
    float: left;
    width: calc(100% / 2);
    padding: 24px;
}

.infoModalLeft>div {
    height: 400px;
    position: relative;
}

.modalInfoSetting span {
    color: #AAB1B8;
    font-size: 20px;
    font-weight: 300;
}

.modalInfoSetting h5 {
    font-size: 36px;
    font-weight: 700;
    margin-bottom: 20px;
}

.modalInfoSetting p {
    font-weight: 300;
    font-size: 14px;
    margin-bottom: 20px;
}

.infoModalImgBox {
    position: relative;
    overflow: hidden;
    height: 400px;
}

.infoModalImgBox img {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.infoModalFourSection {
    overflow: auto;
}

.infoModalFourSection>div {
    float: left;
    width: calc(100% / 4);
}

.infoModalFourSection>div>div:first-of-type {
    margin-bottom: 10px;
}

.infoModalFourSection>div>div:last-of-type span {
    display: block;
    margin-bottom: 10px;
}

.infoModalFourSection>div>div:last-of-type span:first-of-type {
    color: #AAB1B8;
    font-size: 12px;
}

.infoModalFourSection>div>div:last-of-type span:last-of-type {
    color: #737E8A;
    font-size: 14px;
}

.makePlanSty {
    display: block;
    position: absolute;
    bottom: 0;
    padding: 8px 30px;
}

.makePlanSty i {
    margin-left: 10px;
}

.noUserBlockModal::before {
    content: "";
    display: block;
    width: 100%;
    height: 100%;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: rgba(0,0,0,0.6);
}

.noUserBlockModal::after {
    content: "회원전용";
    display: block;
    width: 80px;
    height: 20px;
    background-color: #0dcaf0;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: 4px;
    font-size: 0.8rem;
}

#journeyRegiBtn {
    display: block;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: none;
    position: absolute;
    left: 0px;
    top: 92px;
    background-color: #333;
    color: white;
    transition: all 0.4s;
}

#journeyRegiBtn:hover {
    background-color: #eee;
    color: #333;
}

/* 여행 정보 등록 페이지 스타일링 */
.placeinfoRegContainer {
    position: relative;
}

.placeinfoRegContainer h3 {
    margin-bottom: 0px;
    padding: 20px 0px;
    border-bottom: 1px solid #eee;
}

#jourInfoRegForm .form-group {
    overflow: auto;
    padding-top: 20px;
}

#jourInfoRegForm .form-group:last-of-type {
    text-align: right;
}

#jourInfoRegForm .form-group:last-of-type button {
    margin-left: 10px;
}

.placeinfoRegContents {
    padding: 40px 0px;
}

.placeinfoRegContents label:first-of-type {
    display: block;
    width: 200px;
    float: left;
}

.placeinfoRegContents input[type=text],
.placeinfoRegContents input[type=file],
.placeinfoRegContents textarea {
    float: left;
    width: calc(100% - 200px);
}

.placeinfoRegContents textarea {
    min-height: 200px;
}

.previewSty>div {
    overflow: auto;
    padding: 20px 0px;
}

.journeyInfoThumbnailPreview,
.journeyInfoModalPreview {
    float: left;
}

.journeyInfoThumbnailPreview {
    width: 270px;
    margin-right: 20px;
}

.previewThumbBox {
    position: relative;
    overflow: hidden;
    height: 320px;
    border-radius: 10px;
}

.previewThumbBox img {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}

.journeyInfoThumbnailPreview>div:last-of-type {
    padding: 20px 0px;
}

.journeyInfoThumbnailPreview>div:last-of-type h4 {
    margin-bottom: 5px;
}

.journeyInfoThumbnailPreview>div:last-of-type span {
    font-weight: 300;
}

.journeyInfoModalPreview {
    width: calc(100% - 290px);
    border-left: 1px solid #eee;
}

.previewinfoModal {
    position: relative;
    overflow: auto;
    border-radius: 10px;
}

.previewinfoModal>div {
    float: left;
    width: calc(100% / 2);
    padding: 24px;
}

.previewModalLeft>div {
    height: 400px;
    position: relative;
}

.previewModalInfoSetting span {
    color: #AAB1B8;
    font-size: 20px;
    font-weight: 300;
}

.previewModalInfoSetting h5 {
    font-size: 36px;
    font-weight: 700;
    margin-bottom: 20px;
}

.previewModalInfoSetting p {
    font-weight: 300;
    font-size: 14px;
    margin-bottom: 20px;
}

.previewModalImgBox {
    position: relative;
    overflow: hidden;
    height: 400px;
}

.previewModalImgBox img {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}

.previewModalFourSection {
    overflow: auto;
}

.previewModalFourSection>div {
    float: left;
    width: calc(100% / 4);
}

.previewModalFourSection>div>div:first-of-type {
    margin-bottom: 10px;
}

.previewModalFourSection>div>div:last-of-type span {
    display: block;
    margin-bottom: 10px;
}

.previewModalFourSection>div>div:last-of-type span:first-of-type {
    color: #AAB1B8;
    font-size: 12px;
}

.previewMakePlanSty {
    display: block;
    position: absolute;
    bottom: 0;
    padding: 8px 30px;
}

.previewModalFourSection>div>div:last-of-type span:last-of-type {
    color: #737E8A;
    font-size: 14px;
}

#jourInfoRegForm .card-footer {
    padding: 16px;
}

.placeinfoRegContainer .card-header {
    border-bottom: none;
}

.journeyInfoBtnGroup {
	position: absolute;
	bottom: 0px;
	right: 0px;
}

.journeyInfoBtnGroup button {
	border: none;
	width: 42px;
	height: 42px;
	line-height: 42px;
	display: inline-block;
	background-color: #333;
	color: white;
	border-radius: 50%;
	text-align: center;
	margin-left: 10px;
	transition: all 0.4s;
}

.journeyInfoBtnGroup button:hover {
	background-color: #eee;
	color: #333;
}

// 여행 정보 모달창 기능
$.JourneyInfoModalFn = function () {
    // 모달창 닫기
    var infoModalClose = $(".infoModalClose");
    var infoModalContents = $(".infoModalContents");
    infoModalClose.click(function () {
        infoModalContents.hide();
    });
    // 모달창 열기
    var journeyInfoContents = $(".journeyInfoContents article");
    var modalInfoSetting = $(".modalInfoSetting");
    journeyInfoContents.click(function () {
        
        var thisIs = $(this);
        var infoImgSrc = thisIs.find("img").attr("src").trim();
        var infoH4 = thisIs.find("h4").text().trim();
        var infoSpan = thisIs.find(".infoTitle").text().trim();
        var infoP = thisIs.find("p").text().trim();
        
        modalInfoSetting.find("span").text(infoH4);
        modalInfoSetting.find("h5").text(infoSpan);
        modalInfoSetting.find("p").text(infoP);
        var infoModalImgBox = $(".infoModalImgBox");
        infoModalImgBox.find("img").attr("src", infoImgSrc);
        
        var airportText = thisIs.find(".airportText").html();
        var airportHtmlEl = $(".infoModalFourSection>div:first-of-type>div:last-of-type");
        airportHtmlEl.html("");

        var visaText = thisIs.find(".visaText").html();
        var visaHtmlEl = $(".infoModalFourSection>div:nth-of-type(2)>div:last-of-type");
        visaHtmlEl.html("");

        var voltageTxt = thisIs.find(".voltageTxt").html();
        var voltageHtmlEl = $(".infoModalFourSection>div:nth-of-type(3)>div:last-of-type");
        voltageHtmlEl.html("");

        var infoTimediferTxt = thisIs.find(".infoTimediferTxt").html();
        var infoTimediferHtmlEl = $(".infoModalFourSection>div:last-of-type>div:last-of-type");
        infoTimediferHtmlEl.html("");

        var emptyHtmlEl = "<span>없음</span><span>-</span>";

        if(airportText != undefined) {
            airportHtmlEl.html(airportText);
        }else {
            airportHtmlEl.html(emptyHtmlEl);
        }

        if(visaText != undefined) {
            visaHtmlEl.html(visaText);
        }else {
            visaHtmlEl.html(emptyHtmlEl);
        }

        if(voltageTxt != undefined) {
            voltageHtmlEl.html(voltageTxt);
        }else {
            voltageHtmlEl.html(emptyHtmlEl);
        }

        if(infoTimediferTxt != undefined) {
            infoTimediferHtmlEl.html(infoTimediferTxt);
        }else {
            infoTimediferHtmlEl.html(emptyHtmlEl);
        }
        
        var infoNoVal = thisIs.find(".infoNo").val();
        $("#choiceInfoNo").val(infoNoVal);
        
        infoModalContents.show();
        
        var infoModalImgBox = $(".infoModalImgBox");
        var infoModalImg = $(".infoModalImgBox img");
        $.ratioBoxH(infoModalImgBox, infoModalImg);
        
    });
};

// 여행 정보 각각의 이미지 종횡비 변경 함수
$.eachJourneyInfoImgResizeFn = function(){
    $(".journeyInfoContents article").each(function(i, v){
        var thisIs = $(this);
        var infoThumbnailBox = thisIs.find(".infoThumbnailBox");
        var infoThumbnailImg = thisIs.find("img");
        $.ratioBoxH(infoThumbnailBox, infoThumbnailImg);
    });
};

// 여행 정보 등록 페이지 이동
$.journeyRegiPageMoveFn = function(){
	var journeyRegiBtn = $("#journeyRegiBtn");
	journeyRegiBtn.click(function(){
		location.href = "/myplan/inforeg.do";
	});
};

// 여행 정보 미리보기 기능 함수
var journeyInfoThumbnailPreview = $(".journeyInfoThumbnailPreview");
var previewModalInfoSetting = $(".previewModalInfoSetting");
$.journeyInfoPreviewFn = function(inputEl){
    var journeyInfoThumbnailPreviewTxt = journeyInfoThumbnailPreview.find("span").text();
    var previewModalInfoSettingH5 = previewModalInfoSetting.find("h5").text();
    inputEl.keyup(function(){
        var inputElVal = inputEl.val();
        if(inputElVal) {
            journeyInfoThumbnailPreview.find("span").text(inputElVal);
            previewModalInfoSetting.find("h5").text(inputElVal);
        }else {
            journeyInfoThumbnailPreview.find("span").text(journeyInfoThumbnailPreviewTxt);
            previewModalInfoSetting.find("h5").text(previewModalInfoSettingH5);
        }
    });
};

var journeyInfoThumbnailPreviewLast = $(".journeyInfoThumbnailPreview>div:last-of-type");
$.journeyInfoPreviewFn2 = function(inputEl){
    var journeyInfoThumbnailPreviewLastTxt = journeyInfoThumbnailPreviewLast.find("h4").text();
    var previewModalInfoSettingH5 = previewModalInfoSetting.find("span").text();
    inputEl.keyup(function(){
        var inputElVal = inputEl.val().toUpperCase();
        inputEl.val(inputElVal);
        if(inputElVal) {
            journeyInfoThumbnailPreview.find("h4").text(inputElVal);
            previewModalInfoSetting.find("span").text(inputElVal);
        }else {
            journeyInfoThumbnailPreview.find("h4").text(journeyInfoThumbnailPreviewLastTxt);
            previewModalInfoSetting.find("span").text(previewModalInfoSettingH5);
        }
    });
};

$.journeyInfoPreviewFn3 = function(textareaEl){
    var previewModalInfoSettingP = previewModalInfoSetting.find("p").text();
    textareaEl.keyup(function(){
        var textareaElVal = textareaEl.val().trim();
        textareaElVal = textareaElVal.replace(/\r?\n/g, ""); // 모든 개행 문자를 제거
        if(textareaElVal) {
            previewModalInfoSetting.find("p").text(textareaElVal);
        }else {
            previewModalInfoSetting.find("p").text(previewModalInfoSettingP);
        }
    });
};

$.flightPreviewFn = function(){
    var infoFlightynBtn = $('input[name="infoFlightyn"]');
    var infoFlightBtn = $('input[name="infoFlight"]');
    var infoFlighttime = $('#infoFlighttime');
    //infoFlightBtn.prop('disabled', true);
    //infoFlighttime.prop('disabled', true);
    infoFlightynBtn.change(function() {
        var selectedValue = $('input[name="infoFlightyn"]:checked').val();
        if(selectedValue == "y") {
            infoFlightBtn.prop('disabled', false);
            infoFlighttime.prop('disabled', false);
        }else {
            infoFlightBtn.prop('disabled', true).prop('checked', false);
            infoFlighttime.prop('disabled', true);
            firstSpanVal.text(firstSpanValTxt);
            infoFlighttime.val("");
            secondSpanVal.text("-");
        }
    });
    
    var firstSpanVal = $(".previewModalFourSection>div:first-of-type>div:last-of-type span:first-of-type");
    var firstSpanValTxt = firstSpanVal.text();
    infoFlightBtn.change(function(){
        var selectedValue = $('input[name="infoFlight"]:checked').val();
        if(selectedValue == "str") {
            firstSpanVal.text("직항");
        }else {
            firstSpanVal.text("왕복");
        }
    });
    
    var secondSpanVal = $(".previewModalFourSection>div:first-of-type>div:last-of-type span:last-of-type");
    infoFlighttime.keyup(function(){
        var thisIs = $(this);
        var timeVal = thisIs.val();
        //console.log("timeVal : " + timeVal);
        if(timeVal) {
            secondSpanVal.text(timeVal);
        }else {
            secondSpanVal.text("-");
        }
    });
};

$.visaPreviewFn = function(){
    var infoVisaynBtn = $('input[name="infoVisayn"]');
    var infoVisaexpBtn = $('input[name="infoVisaexp"]');
    var infoVisatime = $('#infoVisatime');
    //infoVisaexpBtn.prop('disabled', true);
    //infoVisatime.prop('disabled', true);
    infoVisaynBtn.change(function() {
        var selectedValue = $('input[name="infoVisayn"]:checked').val();
        if(selectedValue == "y") {
            infoVisaexpBtn.prop('disabled', false);
            infoVisatime.prop('disabled', false);
        }else {
            infoVisaexpBtn.prop('disabled', true).prop('checked', false);
            infoVisatime.prop('disabled', true);
            firstSpanVal.text(firstSpanValTxt);
            infoVisatime.val("");
            secondSpanVal.text("-");
        }
    });
    
    var firstSpanVal = $(".previewModalFourSection>div:nth-of-type(2)>div:last-of-type span:first-of-type");
    var firstSpanValTxt = firstSpanVal.text();
    infoVisaexpBtn.change(function(){
        var selectedValue = $('input[name="infoVisaexp"]:checked').val();
        if(selectedValue == "visa") {
            firstSpanVal.text("비자");
        }else {
            firstSpanVal.text("무비자");
        }
    });
    
    var secondSpanVal = $(".previewModalFourSection>div:nth-of-type(2)>div:last-of-type span:last-of-type");
    infoVisatime.keyup(function(){
        var thisIs = $(this);
        var timeVal = thisIs.val();
        if(timeVal) {
            secondSpanVal.text(timeVal);
        }else {
            secondSpanVal.text("-");
        }
    });
};

$.voltagePreviewFn = function(){
    var infoVoltageBtn = $('input[name="infoVoltage"]');
    var secondSpanVal = $(".previewModalFourSection>div:nth-of-type(3)>div:last-of-type span:last-of-type");
    infoVoltageBtn.change(function(){
        var selectedValue = $('input[name="infoVoltage"]:checked').val();
        if(selectedValue == "110V"){
            secondSpanVal.text("110V");
        }else {
            secondSpanVal.text("220V");
        }
    });
};

$.timeDifferPreviewFn = function(){
    var infoTimedifer = $("#infoTimedifer");
    var secondSpan = $(".previewModalFourSection>div:last-of-type>div:last-of-type span:last-of-type");
    var secondSpanTxt = secondSpan.text();
    infoTimedifer.keyup(function(){
        var thisIs = $(this);
        var thisVal = thisIs.val().toUpperCase();
        //console.log("thisVal : " + thisVal);
        thisIs.val(thisVal);
        if(thisVal){
            secondSpan.text(thisVal);
        }else{
            secondSpan.text(secondSpanTxt);
        }
    });
};

$.makeplanClickEvent = function(){
    var makePlanSty = $(".makePlanSty");
    makePlanSty.click(function(event){
        event.preventDefault();
        var thisIs = $(this);
        var hrefVal = thisIs.attr("href");
        var spanVal = thisIs.parents(".infoModalLeft").find(".modalInfoSetting>span").text();
        console.log("spanVal : " + spanVal);
        hrefVal += "?infoName=" + spanVal;
        console.log("hrefVal : " + hrefVal);
        location.href = hrefVal;
    });
};

$.journeyModifyPageMoveFn = function(){
	var journeyInfoModify = $("#journeyInfoModify");
	journeyInfoModify.click(function(){
		var choiceInfoNo = $("#choiceInfoNo");
		var infoNoVal = choiceInfoNo.val();
		//console.log("infoNoVal : " + infoNoVal);
		location.href = "/myplan/modify.do?infoNo=" + infoNoVal;
	});
};

$.journeyDeletePageMoveFn = function(){
    var journeyInfoDelete = $("#journeyInfoDelete");
    journeyInfoDelete.click(function(){
        var choiceInfoNo = $("#choiceInfoNo");
		var infoNoVal = choiceInfoNo.val();
        location.href = "/myplan/delete.do?infoNo=" + infoNoVal;
    });
};

// 여행 정보 실시간 검색 기능 함수
$.ajaxJourneyInfoSearchFn = function(){
	var jourInfoSearch = $("#jourInfoSearch");
    jourInfoSearch.keyup(function(){
    
    	//alert("잘 되는가용?");
    
        var thisIs = $(this);
        var thisVal = thisIs.val();
        console.log("thisVal : " + thisVal);
        
        var languageType = detectLanguage(thisVal);
        console.log("languageType : " + languageType);
        
        var journeyVO = {};
        
        if(languageType == "korean") {
            journeyVO.infoName = thisVal;
            journeyVO.infoEngname = "";
        }else if(languageType == "english") {
            journeyVO.infoName = "";
            journeyVO.infoEngname = thisVal;
        }else {
            journeyVO.infoName = "";
            journeyVO.infoEngname = "";
        }
        
        $.ajax({
            type: "get",
            url: "/myplan/ajaxSearch.do",
            data: journeyVO,
            dataType: "json",
            success: function(res){
                console.log("res : ", res);
                var searchHtml = "";
                if(res.length == 0) {
                	searchHtml += `
                		<article style="text-align: center; width: 50%; margin: 0px auto; float: none; cursor: auto; background-color: #333; color: white; padding: 20px; border-radius: 4px;">
		    				검색된 여행 정보가 없습니다.
		    			</article>
                	`;
                }
                for(var i=0; i<res.length; i++){
                    searchHtml += `
                        <article>
                            <div class="infoThumbnailBox">
                                <img src="${res[i].infoPreviewimg}" alt="여행 정보 썸네일 이미지" />
                            </div>
                            <div>
                                <h4 class="textDrop">${res[i].infoEngname}</h4>
                                <span class="infoTitle textDrop">${res[i].infoName}</span>
                                <p>${res[i].infoDescription}</p>
                                <span class="airportText">`;

                            if(res[i].infoFlightyn == 'y'){
                                searchHtml += `<span>`;

                                if(res[i].infoFlight == "str"){
                                    searchHtml += `직항</span>`;
                                }else {
                                    searchHtml += `왕복</span>`;
                                }

                                searchHtml += `<span>${res[i].infoFlighttime}</span>`;
                            }else {
                                searchHtml += `<span>없음</span>
                                                <span>-</span>`;
                            }

                    searchHtml += `</span>
                                <span class="visaText">`;

                            if(res[i].infoVisayn == 'y'){
                                searchHtml += `<span>`;

                                if(res[i].infoVisaexp == "visa"){
                                    searchHtml += `비자</span>`;
                                }else {
                                    searchHtml += `무비자</span>`;
                                }

                                searchHtml += `<span>${res[i].infoVisatime}</span>`;
                            }else {
                                searchHtml += `<span>없음</span>
                                                <span>-</span>`;
                            }

                    searchHtml += `</span>
                                <span class="voltageTxt">
                                    <span>콘센트</span>
                                    <span>${res[i].infoVoltage}</span>
                                </span>
                                <span class="infoTimediferTxt">
                                    <span>한국대비</span>
                                    <span>${res[i].infoTimedifer}</span>
                                </span>
                                <input type="hidden" class="infoNo" name="infoNo" value="${res[i].infoNo}" />
                            </div>
                        </article>
                    `;
                }
                var journeyInfoContents = $(".journeyInfoContents");
                journeyInfoContents.html("");
                journeyInfoContents.append(searchHtml);
                
                $.JourneyInfoModalFn();
                $.eachJourneyInfoImgResizeFn();
            }
        });
        
    });
};

function detectLanguage(inputValue) {
    // 정규표현식을 사용하여 문자열이 한글인지 영어인지 판별
    var koreanRegex = /[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]/;
    var englishRegex = /^[a-zA-Z]*$/;

    if (koreanRegex.test(inputValue)) {
        return "korean";
    } else if (englishRegex.test(inputValue)) {
        return "english";
    } else {
        return "etc";
    }
}

$(window).on("load", function(){
    $('input[name="infoFlightyn"]').trigger("change");
    $('input[name="infoVisayn"]').trigger("change");
});

package kr.or.ddit.users.myplan.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import kr.or.ddit.users.login.vo.MemberVO;
import kr.or.ddit.users.myplan.service.JourneyService;
import kr.or.ddit.users.myplan.vo.JourneyinfoVO;
import kr.or.ddit.utils.ServiceResult;
import kr.or.ddit.vo.RealTimeSenderVO;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/myplan")
public class InformationMyplanController {

	@Inject
	private JourneyService journeyService;
	
	// 마이 플랜 > 여행 정보 페이지 이동
	@CrossOrigin(origins = "http://localhost")
	@RequestMapping(value = "/info.do", method = RequestMethod.GET)
	public String information(
			Model model
			) {
		/** 자료 수집 및 정의 */
		Map<String, Object> param = new HashMap<String, Object>();
		
		/** 서비스 호출 */
		// 여행정보 리스트 가져오기
		journeyService.informationList(param);
		
		/** 반환 자료 */
		List<JourneyinfoVO> journeyList = (List<JourneyinfoVO>) param.get("journeyList");
		
		/** 자료 검증 */
		log.info("journeyList : {}", journeyList);
		
		/** 자료 반환 */
		model.addAttribute("journeyList", journeyList);
		
		return "myplan/information";
	}
	
	// 여행 정보 등록 페이지 이동
	@CrossOrigin(origins = "http://localhost")
	@RequestMapping(value = "/inforeg.do", method = RequestMethod.GET)
	public String inforRegForm() {
		return "myplan/infoReg";
	}
	
	// 여행 정보 등록 메소드
	@RequestMapping(value = "/inforeg.do", method = RequestMethod.POST)
	public String inforReg(
			HttpServletRequest req,
			JourneyinfoVO journeyVO,
			Model model,
			RedirectAttributes ra,
			@RequestParam("imgFile") MultipartFile imgFile
			) {
		
		log.info("imgFile : " + imgFile.getOriginalFilename());
		log.info("journeyVO : " + journeyVO.toString());
		
		// 이미지 파일이 없는 경우 예외 처리
		if(imgFile.isEmpty()) {
			model.addAttribute("message", "이미지 파일을 업로드해 주세요.");
			model.addAttribute("msgflag", "in");
			return "myplan/infoReg";
		}
		
		String goPage = "";
		
		Map<String, String> errors = new HashMap<String, String>();
		if(StringUtils.isBlank(journeyVO.getInfoName())) {
			errors.put("infoName", "지역명(한글)을 입력해 주세요.");
		}
		if(StringUtils.isBlank(journeyVO.getInfoEngname())) {
			errors.put("infoName", "지역명(영어)를 입력해 주세요.");
		}
		if(StringUtils.isBlank(journeyVO.getInfoDescription())) {
			errors.put("infoName", "지역 설명을 입력해 주세요.");
		}
		if(StringUtils.isBlank(journeyVO.getInfoTimedifer())) {
			errors.put("infoName", "한국 대비 시차 기록을 입력해 주세요.");
		}
		
		if(errors.size() > 0) { // 에러 정보가 존재
			model.addAttribute("errors", errors);
			model.addAttribute("msgflag", "fa");
			model.addAttribute("journey", journeyVO);
			goPage = "myplan/infoReg"; // 여행 정보 등록 페이지로 이동
		}else { // 정상적인 데이터
			ServiceResult result = journeyService.inforReg(req, journeyVO);
			if(result.equals(ServiceResult.OK)) { // 여행 정보 등록 성공
				ra.addFlashAttribute("message", "여행 정보 등록이 성공적으로 완료되었습니다.");
				ra.addFlashAttribute("msgflag", "su");
				goPage = "redirect:/myplan/info.do"; // 여행 정보 페이지 로이동
			}else { // 여행 정보 등록 실패
				model.addAttribute("message", "서버에러, 다시 시도해 주세요.");
				model.addAttribute("msgflag", "in");
				model.addAttribute("journey", journeyVO);
				goPage = "myplan/infoReg"; // 여행 정보 등록 페이지로 이동
			}
		}
		
		return goPage;
		
	}
	
	// 여행 정보 수정 페이지 이동
	@CrossOrigin(origins = "http://localhost")
	@RequestMapping(value = "/modify.do", method = RequestMethod.GET)
	public String inforModifyForm(int infoNo, Model model) {
		JourneyinfoVO journeyVO = journeyService.selectJourney(infoNo);
		model.addAttribute("journey", journeyVO);
		model.addAttribute("status", "u");
		return "myplan/infoReg";
	}
	
	// 여행 정보 수정 메서드
	@RequestMapping(value = "/modify.do", method = RequestMethod.POST)
	public String inforModify(
			HttpServletRequest req,
			JourneyinfoVO journeyVO,
			Model model,
			RedirectAttributes ra
			) {
		
		String goPage = "";
		
		ServiceResult result = journeyService.inforModify(req, journeyVO);
		if(result.equals(ServiceResult.OK)) {
			ra.addFlashAttribute("message", "여행 정보가 성공적으로 수정되었습니다.");
			ra.addFlashAttribute("msgflag", "su");
			goPage = "redirect:/myplan/info.do";
		}else {
			model.addAttribute("message", "서버 에러, 다시 시도해 주세요.");
			model.addAttribute("msgflag", "in");
			model.addAttribute("journey", journeyVO);
			model.addAttribute("status", "u");
			goPage = "myplan/infoReg";
		}
		
		return goPage;
		
	}
	
	// 여행 정보 삭제 메서드
	@RequestMapping(value = "/delete.do", method = RequestMethod.GET)
	public String inforDelete(
			RedirectAttributes ra,
			int infoNo,
			Model model
			) {
		
		String goPage = "";
		
		ServiceResult result = journeyService.inforDelete(infoNo);
		if(result.equals(ServiceResult.OK)) {
			ra.addFlashAttribute("message", "여행 정보 삭제가 완료되었습니다.");
			ra.addFlashAttribute("msgflag", "su");
			goPage = "redirect:/myplan/info.do";
		}else {
			ra.addFlashAttribute("message", "여행 정보 삭제에 실패했습니다.");
			ra.addFlashAttribute("msgflag", "fa");
			goPage = "redirect:/myplan/info.do";
		}
		
		return goPage;
		
	}
	
	// ajax > 실시간 여행 정보 검색 메서드
	@GetMapping("/ajaxSearch.do")
	@ResponseBody
	public List<JourneyinfoVO> journeyList(JourneyinfoVO journeyVO) {
		log.info("journeyVO : {}" , journeyVO);
		return journeyService.searchJourneyList(journeyVO);
	}
	
}

package kr.or.ddit.users.myplan.vo;

import org.springframework.web.multipart.MultipartFile;

import lombok.Data;

@Data
public class JourneyinfoVO {

	private int infoNo;
	private String infoName;
	private String infoEngname;
	private String infoDescription;
	private String infoFlightyn;
	private String infoFlight;
	private String infoFlighttime;
	private String infoVisayn;
	private String infoVisaexp;
	private String infoVisatime;
	private String infoVoltage;
	private String infoTimedifer;
	private String infoRegdate;
	
	private MultipartFile imgFile;
	private String infoPreviewimg;
	
}

package kr.or.ddit.users.myplan.service;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import kr.or.ddit.users.myplan.vo.JourneyinfoVO;
import kr.or.ddit.utils.ServiceResult;

public interface JourneyService {

	public ServiceResult inforReg(HttpServletRequest req, JourneyinfoVO journeyVO);
	public void informationList(Map<String, Object> param);
	public JourneyinfoVO selectJourney(int infoNo);
	public ServiceResult inforModify(HttpServletRequest req, JourneyinfoVO journeyVO);
	public ServiceResult inforDelete(int infoNo);
	public List<JourneyinfoVO> searchJourneyList(JourneyinfoVO journeyVO);

}

package kr.or.ddit.users.myplan.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import kr.or.ddit.mapper.JourneyMapper;
import kr.or.ddit.users.myplan.service.JourneyService;
import kr.or.ddit.users.myplan.vo.JourneyinfoVO;
import kr.or.ddit.utils.ServiceResult;
import kr.or.ddit.vo.RealTimeSenderVO;

@Service
@Transactional(rollbackFor = Exception.class)
public class JourneyServiceImpl implements JourneyService {

	@Inject
	private JourneyMapper journeyMapper;
	
	@Override
	public ServiceResult inforReg(HttpServletRequest req, JourneyinfoVO journeyVO) {
		ServiceResult result = null;
		
		// 여행 정보 등록 시, 미리보기 이미지로 파일 업로드할 서버 경로를 지정
		String uploadPath = req.getServletContext().getRealPath("/resources/journeyinfo");
		File file = new File(uploadPath);
		if(!file.exists()) {
			file.mkdirs();
		}
		
		String previewImg = ""; // 여행 정보에 추가될 미리보기 이미지 경로
		try {
			// 넘겨받은 여행정보에서 파일 데이터 가져오기
			MultipartFile previewImgFile = journeyVO.getImgFile();
			
			// 넘겨받은 파일 데이터가 존재할 때
			if(previewImgFile.getOriginalFilename() != null && !previewImgFile.getOriginalFilename().equals("")) {
				String fileName = UUID.randomUUID().toString(); // UUID 파일명 생성
				fileName += "_" + previewImgFile.getOriginalFilename(); // UUID_원본파일명으로 생성
				uploadPath += "/"  + fileName; // /resources/journeyinfo/UUID_원본파일명
				
				previewImgFile.transferTo(new File(uploadPath)); // 해당 위치에 파일 복사
				previewImg = "/resources/journeyinfo/" + fileName; // 파일 복사가 일어난 파일의 위치로 접근하기 위한 URI 설정
			}
			
			journeyVO.setInfoPreviewimg(previewImg);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		int status = journeyMapper.inforReg(journeyVO);
		
		if(status > 0) { // 등록 성공
			result = ServiceResult.OK;
		}else { // 등록 실패
			result = ServiceResult.FAILED;
		}
		
		return result;
	}

	@Override
	public void informationList(Map<String, Object> param) {
		/** 파라미터 조회 */
		
		/** 파라미터 정의 */
		List<JourneyinfoVO> journeyList = new ArrayList<JourneyinfoVO>();
		
		/** 메인로직 처리 */
		// 여행 정보를 리스트로 받아오기
		journeyList = journeyMapper.informationList();
		
		/** 반환자료 저장 */
		param.put("journeyList", journeyList);
	}

	@Override
	public JourneyinfoVO selectJourney(int infoNo) {
		return journeyMapper.selectJourney(infoNo);
	}

	@Override
	public ServiceResult inforModify(HttpServletRequest req, JourneyinfoVO journeyVO) {
		ServiceResult result = null;
		
		// 여행 정보 수정 시, 미리보기 이미지로 파일 업로드할 서버 경로 지정
		String uploadPath = req.getServletContext().getRealPath("/resources/journeyinfo");
		File file = new File(uploadPath);
		if(!file.exists()) {
			file.mkdirs();
		}
		
		String previewImg = ""; // 여행 정보에 추가될 미리보기 이미지 경로
		try {
			// 넘겨받은 여행정보에서 파일 데이터 가져오기
			MultipartFile previewImgFile = journeyVO.getImgFile();
			
			// 넘겨받은 파일 데이터가 존재할 때
			if(previewImgFile.getOriginalFilename() != null && !previewImgFile.getOriginalFilename().equals("")) {
				String fileName = UUID.randomUUID().toString(); // UUID 파일명 생성
				fileName += "_" + previewImgFile.getOriginalFilename(); // UUID_원본파일명으로 생성
				uploadPath += "/" + fileName; // /resources/journeyinfo/UUID_원본파일명
				
				previewImgFile.transferTo(new File(uploadPath)); // 해당 위치에 파일 복사
				previewImg = "/resources/journeyinfo/" + fileName; // 파일 복사가 일어난 파일의 위치로 접근하기 위한 URI 설정
			}
			
			journeyVO.setInfoPreviewimg(previewImg);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		int status = journeyMapper.inforModify(journeyVO);
		if(status > 0) { // 수정 성공
			result = ServiceResult.OK;
		}else {
			result = ServiceResult.FAILED;
		}
		
		return result;
	}

	@Override
	public ServiceResult inforDelete(int infoNo) {
		ServiceResult result = null;
		
		// 여행 정보를 삭제하장
		int status = journeyMapper.deleteInfor(infoNo);
		if(status > 0) {
			result = ServiceResult.OK;
		}else {
			result = ServiceResult.FAILED;
		}
		
		return result;
	}

	@Override
	public List<JourneyinfoVO> searchJourneyList(JourneyinfoVO journeyVO) {
		return journeyMapper.searchJourneyList(journeyVO);
	}

}

package kr.or.ddit.mapper;

import java.util.List;

import kr.or.ddit.users.myplan.vo.JourneyinfoVO;
import kr.or.ddit.vo.RealTimeSenderVO;

public interface JourneyMapper {

	public int inforReg(JourneyinfoVO journeyVO);
	public List<JourneyinfoVO> informationList();
	public JourneyinfoVO selectJourney(int infoNo);
	public int inforModify(JourneyinfoVO journeyVO);
	public int deleteInfor(int infoNo);
	public List<JourneyinfoVO> searchJourneyList(JourneyinfoVO journeyVO);

}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.mapper.JourneyMapper">
	
	<insert id="inforReg" parameterType="journeyinfoVO">
		<selectKey keyProperty="infoNo" order="BEFORE" resultType="int">
			select seq_journeyinfo.nextval from dual
		</selectKey>
		INSERT INTO journeyinfo (
		    info_no,
		    info_name,
		    info_engname,
		    info_description,
		    info_flightyn,
		    info_flight,
		    info_flighttime,
		    info_visayn,
		    info_visaexp,
		    info_visatime,
		    info_voltage,
		    info_timedifer,
		    info_previewimg,
		    info_regdate
		) VALUES (
		    #{infoNo},
		    #{infoName},
		    #{infoEngname},
		    #{infoDescription},
		    #{infoFlightyn},
		    #{infoFlight},
		    #{infoFlighttime},
		    #{infoVisayn},
		    #{infoVisaexp},
		    #{infoVisatime},
		    #{infoVoltage},
		    #{infoTimedifer},
		    #{infoPreviewimg},
		    sysdate
		)
	</insert>
	
	<select id="informationList" resultType="journeyinfoVO">
		SELECT
		    info_no,
		    info_name,
		    info_engname,
		    info_description,
		    info_flightyn,
		    info_flight,
		    info_flighttime,
		    info_visayn,
		    info_visaexp,
		    info_visatime,
		    info_voltage,
		    info_timedifer,
		    info_previewimg,
		    info_regdate
		FROM
		    journeyinfo
		ORDER BY info_no desc
	</select>
	
	<select id="selectJourney" parameterType="int" resultType="journeyinfoVO">
		SELECT
		    info_no,
		    info_name,
		    info_engname,
		    info_description,
		    info_flightyn,
		    info_flight,
		    info_flighttime,
		    info_visayn,
		    info_visaexp,
		    info_visatime,
		    info_voltage,
		    info_timedifer,
		    info_previewimg,
		    info_regdate
		FROM
		    journeyinfo
		WHERE 
			1=1 
		AND
			info_no = #{infoNo}
	</select>
	
	<update id="inforModify" parameterType="journeyinfoVO">
		UPDATE journeyinfo
		SET
		    info_name = #{infoName},
		    info_engname = #{infoEngname},
		    info_description = #{infoDescription},
		    info_flightyn = #{infoFlightyn},
		    info_flight = #{infoFlight},
		    info_flighttime = #{infoFlighttime},
		    info_visayn = #{infoVisayn},
		    info_visaexp = #{infoVisaexp},
		    info_visatime = #{infoVisatime},
		    info_voltage = #{infoVoltage},
		    info_timedifer = #{infoTimedifer},
		    info_regdate = sysdate
		    <if test="infoPreviewimg != null and !infoPreviewimg.equals('')">
            , info_previewimg = #{infoPreviewimg}
        	</if> 
		WHERE 
		    1=1 
		AND 
		    info_no = #{infoNo}
	</update>
	
	<delete id="deleteInfor" parameterType="int">
		DELETE FROM journeyinfo
		WHERE info_no = #{infoNo}
	</delete>
	
	<select id="searchJourneyList" parameterType="journeyinfoVO" resultType="journeyinfoVO">
		SELECT *
		FROM journeyinfo
		WHERE info_name LIKE '%' || #{infoName} || '%'
		   AND UPPER(info_engname) LIKE UPPER('%' || #{infoEngname} || '%')
		ORDER BY info_no desc
	</select>
	
</mapper>