chessta0126 / festivalBooking

0 stars 0 forks source link

festival - 공연 등록 #6

Open chessta0126 opened 1 year ago

chessta0126 commented 1 year ago

festivalController

1. 공연 예매 (공연 정보 리스트)

2. 내가 등록한 공연 목록

3. 공연 홍보 글쓰기

4. 공연 홍보 글 상세

FestivalRestController

1. 공연 등록 (/festival/create)

Festival(model)

FestivalBO

insert 공연 추가 + 포스터 이미지 저장 : boolean

FestivalDAO

festivalMapper.xml

jsp

festivalList.jsp (글 목록)

festivalMyList.jsp (내가 작성한 글 목록)

festivalCreate.jsp (공연 작성)

chessta0126 commented 1 year ago

on/off 창 추가 (공연 예매 만료, 예매 중)

https://imivory.tistory.com/15

chessta0126 commented 1 year ago

카카오 지도 - 키워드로 장소 검색

https://apis.map.kakao.com/web/sample/keywordBasic/

  1. 첨부 수정(&libraries=services 추가)

    <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=발급받은 key &libraries=services"></script>
  2. 키워드로 장소 검색

    
    // 마커를 클릭하면 장소명을 표출할 인포윈도우 입니다
    var infowindow = new kakao.maps.InfoWindow({zIndex:1});

// 장소 검색 객체를 생성합니다 var ps = new kakao.maps.services.Places();

// 키워드로 장소를 검색합니다 ps.keywordSearch('홍대입구역', placesSearchCB);

// 키워드 검색 완료 시 호출되는 콜백함수 입니다 function placesSearchCB (data, status, pagination) { if (status === kakao.maps.services.Status.OK) {

    // 검색된 장소 위치를 기준으로 지도 범위를 재설정하기 위해
    // LatLngBounds 객체에 좌표를 추가합니다
    var bounds = new kakao.maps.LatLngBounds();
    for (var i=0; i<data.length; i++) {
        displayMarker(data[i]);    
        bounds.extend(new kakao.maps.LatLng(data[i].y, data[i].x));
    }       

    // 검색된 장소 위치를 기준으로 지도 범위를 재설정합니다
    map.setBounds(bounds);
} 

}

// 지도에 마커를 표시하는 함수입니다 function displayMarker(place) { // 마커를 생성하고 지도에 표시합니다 var marker = new kakao.maps.Marker({ map: map, position: new kakao.maps.LatLng(place.y, place.x) });

// 마커에 클릭이벤트를 등록합니다
kakao.maps.event.addListener(marker, 'click', function() {
    // 마커를 클릭하면 장소명이 인포윈도우에 표출됩니다
    infowindow.setContent('<div style="padding:5px;font-size:12px;">' + place.place_name + '</div>');
    infowindow.open(map, marker);
});

}

chessta0126 commented 1 year ago
chessta0126 commented 1 year ago

비회원 예매

modal의 비회원 예매 클릭 시 sweetAlert2로 input 값을 받을 수 있게 함 bookName 입력이 완료되면 phoneNumber를 입력 받고, phoneNumber 까지 입력되면 AJAX로 넘길 준비를 하기 위해 변수를 설정한다.

(async () => {
    const { value: bookName } = await Swal.fire({
        title: '예매자의 이름을 입력하세요.',
        input: 'text',
        inputPlaceholder: '이름을 입력하세요..'
    })

    // 이후 처리되는 내용.
    if (bookName) {
        const { value: phoneNumber } = await Swal.fire({
            title: '연락처를 입력하세요.',
            input: 'text',
            inputPlaceholder: '연락처를 입력하세요..'
        })

        if (phoneNumber) { // 전화번호까지 입력 완료되었을 때 변수 설정, 예매 final 확인
            let festivalId = ${festival.id};
        let headCount = $('#headCount option:selected').val();
        let payMoney = $('#payMoney').text();
        let isMember = false;
        if(isMember){
            isMember = 1;
        } else{
            isMember = 0;
        }

            Swal.fire({
                title: '예매 하시겠습니까?',
                text: "수량 : " + headCount + "매 , 가격 : " + payMoney + "원",
                icon: 'warning',
                showCancelButton: true,
                confirmButtonColor: '#3085d6',
                cancelButtonColor: '#d33',
                confirmButtonText: '예',
                cancelButtonText: '아니오'
            }).then((result) => { 
                if (result.isConfirmed) { // 예매 확정(insert)
            // AJAX 전송
            $.ajax({
                type:'POST'
                ,url:'/book/addBooking'
                , data: {"festivalId":festivalId, "payMoney":payMoney, "headCount":headCount, "isMember":isMember, "bookName":bookName,"phoneNumber":phoneNumber}
                , success: function(data) {
                    if (data.code == 1) {
                        // 성공
                        Swal.fire({
                                    title : '예매가 완료되었습니다.',
                                    text : '예매완료 버튼 / 마이페이지 > 예매 확인 탭 등에서 예약을 수정하실 수 있습니다.',
                                    icon: 'success'
                        }).then((result) => { 
                                if (result.isConfirmed) {
                            location.reload();
                                }
                        });
                    } else{
                        // 실패
                        alert("[error] 예매에 실패했습니다. \n 담당자에게 문의해주세요");
                    }
                }
                , error : function(jqXHR, textStatus, errorThrown) {
                    var errorMsg = jqXHR.responseJSON.status;
                    alert(errorMsg + ":" + textStatus);
                }
            });
                }
            });
        }
        }
    })()
});
chessta0126 commented 1 year ago

공연 삭제 시 순환 참조 발생

festival과 book을 연결하여 bookView로 담는 과정에서 bookBO가 그 일을 처리하게 설정했는데, 이때 festivalBO를 역으로 참조했었다.

festival을 삭제할 때 그에 딸린 예매 내역을 전부 삭제하려고 bookBO를 참조하다가 순환 참조 발생

-> bookView에 관련된 로직을 bookBO에서 festivalBO로 옮기고, bookBO는 1:n에서 1에 해당하는 festivalBO를 역으로 참조하지 않게 한다.

chessta0126 commented 1 year ago

입력 내용이 HTML에서 보여질 때 엔터가 적용되지 않는 문제

textarea로 insert한 내용을 수정할 때는 똑같이 textarea 내부에 내려받기 때문에 엔터가 적용된 상태로 잘 전달되지만, textarea가 아닌 div 안에서 내용을 보여줄 때는 엔터가 적용되지 않아 다 붙어 나온다.

-> div가 아닌 pre 태그 내부에 내용을 담으면 엔터까지 그대로 보여준다.

다른 방법으로 해결하는 법 https://offbyone.tistory.com/326

chessta0126 commented 1 year ago
chessta0126 commented 1 year ago

Festival 객체에서 boolean 변수가 EL문법으로 호출되지 않는 문제

Controller에서 model로 festival 정보를 내려주는데, boolean 변수인 isTimeOver를 jsp에서 ${festival.isTimeOver}로 호출했을 경우 찾을 수 없다며 에러가 뜬다. (다른 변수들은 같은 방법으로 잘 가져와진다.)

-> 여전히 찾을 수 없다고 에러가 뜬다.

festivalMyList. jsp에서는 festival 객체를 List에 담아 내리는 문제가 발생

-> 변수가 아닌 메서드로 호출해봄

<c:when test="${!festival.isTimeOver()}">

-> 정상 작동으로 문제 해결

chessta0126 commented 1 year ago

예매 가격 입력 - input 박스에 숫자만 입력되도록 설정

input type = "number"로 지정

https://hianna.tistory.com/413

chessta0126 commented 1 year ago

공연 시간 통제

String 처리 했었으나, 문자열이 들어올 우려가 있어

input type = "number"

로 숫자만 입력 가능하도록 하고 시, 분으로 input창을 2개씩 나누어 받았다.

기존 startTime은 2개의 input 값을 합친 것으로 바꾸었고,

  1. 수정 시 분리해서 가져올 수 있도록 split을 사용하기 위해 띄어쓰기를 넣었다.
  2. Hour를 기입하지 않았을 경우에는 alert을 띄우고, Minute은 0분일 수 있으므로 기입하지 않았을 경우 자동 0으로 처리, festivalDetail에서 띄울 때는 미관상 0분을 제거한다.
    let startTimeHour = $('#startTimeHour').val().trim();
    let startTimeMinute = $('#startTimeMinute').val().trim();
    if(startTimeMinute == ''){
    startTimeMinute = 0;
    }
    let startTime = startTimeHour + "시 " + startTimeMinute + "분";

$('#endTimeHour').attr('value',"${festival.endTime.split('시')[0]}"); $('#endTimeMinute').attr('value',"${festival.endTime.split(' ')[1].split('분')[0]}");