2024-04-06 - 필터 다중선택 구현(전체선택 및 전체해제 버튼 x)

·2024년 4월 7일

프로젝트

목록 보기
44/57

📅 2024-04-06


[프로젝트 남은 TODOs]

  • 필터
    • 필터 전체선택 전체해제 버튼
  • 회원
    • 회원 비밀번호 찾기
    • 로그인아이디 찾기
    • 나의 게시글 jsp
  • 검색
    • 조건별 추천검색어에서 '카페'라는 단어가 포함되어있다면 파싱하여 제외시켜 검색시키기
    • 검색결과 없을 경우에 대한 처리
    • 제휴문의 (관리자에게 이메일보내기 기능) 구글폼 사용
  • 사용자 위치기반

완료

  • 카페 스크랩 (나의 찜) 목록 페이지
  • 카페 좋아요 (90%) (수정필요)
    - 사용자 위치기반 카페와의 거리 표시 (구현 x, 기능에서 제외)
    - 검색창
  • 메인페이지 하단
    - 추천카페, 인기카페, 신규카페
  • 필터 자잘한 오류 수정
  • 선택 필터 색상 css 처리
  • 마이페이지 (내가쓴글, 내가한 질문, 나의 댓글, 내가찜한카페 count 가져오기)
  • 필터 다중조건 (다중선택)

필터 버튼 다중선택 및 선택 해제 시 버튼 색상처리

//searchList.jsp 

  // 해당 키워드가 이미 선택되어 있는지 확인
        if (index !== -1) {
            // 이미 선택되어 있다면 해당 키워드를 제거
            selectedKeywords.splice(index, 1);
            $(this).removeClass('active');
        } else {
            // 선택되어 있지 않다면 해당 키워드를 배열에 추가
            selectedKeywords.push(keyword);
            $(this).addClass('active');
        }

1개이상의 키워를 받아서 리스팅하기

키워드를 List에 담아서 처리하기 위해 JSP와 컨트롤러 수정!

//JSP

$(document).ready(function() {
	var selectedKeywords = []; // 선택된 키워드를 저장할 배열
	
    // 필터 버튼 클릭 이벤트 핸들러 등록
    $(".filterButton").on("click", function(event) {
    	var keyword = $(this).find(".text-wrapper").text(); // 클릭한 버튼의 텍스트에서 키워드 추출
        var index = selectedKeywords.indexOf(keyword); // 선택된 키워드 배열에서 해당 키워드의 인덱스 확인

        // 해당 키워드가 이미 선택되어 있는지 확인
        if (index !== -1) {
            // 이미 선택되어 있다면 해당 키워드를 제거
            selectedKeywords.splice(index, 1);
            $(this).removeClass('active');
        } else {
            // 선택되어 있지 않다면 해당 키워드를 배열에 추가
            selectedKeywords.push(keyword);
            $(this).addClass('active');
        }
        
        currentPage = 1; // 페이지를 1로 설정하여 필터가 변경되었음을 나타냄
        loadFilteredCafes(selectedKeywords, currentPage); // 필터된 카페들을 불러오는 함수 호출
    });

	$('.pagination').on('click', 'a', function(event) {
    	event.preventDefault(); // 기본 동작 방지 (페이지 이동 막기)
        currentPage = parseInt($(this).attr('href').split('=')[1]); // 클릭한 페이지 번호 추출
        
     	// 필터링된 카페 목록을 요청하는 함수 호출
        loadFilteredCafes(selectedKeywords, currentPage);
        
     	// 페이지 맨 위로 스크롤
        window.scrollTo({
            top: 0,
            behavior: "smooth"
        });
    });
//컨트롤러

	@RequestMapping("/usr/findcafe/filterCafes")
	@ResponseBody
	public Map<String, Object> filterCafes(@RequestBody Map<String, Object> filterData) {

		Map<String, Object> returnMap = new HashMap<>();
		List<String> selectedKeywords = new ArrayList<String>();
		
		//String keyword = filterData.get("keyword"); // 키워드 다중선택 아닌 단일선택 시 
		//List<String> selectedKeywords = (List<String>) filterData.get("selectedKeywords"); // 키워드 선택하지 않았을 경우 리스트 보이지 않음 (키워드가 빈값 일 때 String) 
		Object selectedKeywordsObject = filterData.get("selectedKeywords"); // 키워드 선택 안했을 때 String으로 넘어오고, 키워드 선택 했을 땐 List로 넘어와서 변수타입을 Object로 선언.

		if (selectedKeywordsObject instanceof String == false) { // 키워드 선택 안했을 시 빈값이 String으로 들어와서 String(빈값) 여부 판단 후 빈값인 경우 전체카페 리스트 보여줌
		    selectedKeywords = (List<String>) selectedKeywordsObject;
		}
		
		
		
		int page = Integer.parseInt(filterData.get("page").toString());
		List<Cafe> cafesList;

		cafeRepository.updateReviewCount();

		int cafesCount = 0;
		if (selectedKeywords.isEmpty()) {
			cafesCount = cafeService.getCafesCount();
		} else {
			cafesCount = cafeService.getCafesCountKeyword(selectedKeywords);
		}

		int itemsInAPage = 5;

		if (selectedKeywords.isEmpty()) { //키워드가 선택 되지 않았을 경우에 대한 전체카페 리스팅
			cafesList = cafeService.getForPrintCafes(itemsInAPage, page);
		} else { //키워드가 선택 되었을 경우에 대한 키워드별 카페 리스팅
			cafesList = cafeService.getForPrintCafesKeyword(itemsInAPage, page, selectedKeywords);
		}

		returnMap.put("cafesTotalCount", cafesCount);
		returnMap.put("cafesCurrentList", cafesList);

		return returnMap;
	}

그런데 Repository에서 마이바티스를 foreach문으로 수정하는 과정에서 계속 에러가 뜸!
며칠전에도 같은 문제로 키워드 다중선택 구현중 단일선택으로 원복했던 적이 있었는데..ㅜㅜ
계속 Repository에서 마이바티스 쿼리에서 삽질했던 원인은.. <script>태그로 감싸지 않았기 때문이었음;;; 정말 너무 없이 없고 황당한 실수였었다..
무튼, 배열형태로 넘기고 싶을 땐 마이바티스에서는 foreach 사용하면 된다!

//레파지토리

 	@Select("""
			<script>
			     SELECT id, name, address, cafeScrapCount, reviewCount, hashtag, cafeImgUrl1
			     FROM cafe
				 WHERE
			     <foreach collection="selectedKeywords" item="keyword" separator="OR" open="(" close=")">
				    `name` LIKE CONCAT('%', #{keyword}, '%')
				    OR `address` LIKE CONCAT('%', #{keyword}, '%')
				    OR `hashtag` LIKE CONCAT('%', #{keyword}, '%')
				</foreach>
			     GROUP BY id
			     ORDER BY id DESC
			     <if test="limitFrom >= 0 ">
			         LIMIT #{limitFrom}, #{limitTake}
			     </if>
			</script>
			""")
	public List<Cafe> getForPrintCafesKeyword(int limitFrom, int limitTake, List<String> selectedKeywords);

여기 foreach문 안에서 separator="OR"을 사용한 이유는,
selectedKeywords = {'유성구', '모던', '단체'} 라고 가정했을 때:

1번째 item인 keyword에 유성구 세팅
OR
2번째 item인 keyword에 모던 세팅
OR
3번째 item인 keyword에 단체 세팅
이라는 뜻!

	(`name` LIKE CONCAT('%', '유성구', '%')
       OR `address` LIKE CONCAT('%', '유성구', '%')
       OR `hashtag` LIKE CONCAT('%', '유성구', '%')
   ) 
   OR 
   (`name` LIKE CONCAT('%', '모던', '%')
       OR `address` LIKE CONCAT('%', '모던', '%')
       OR `hashtag` LIKE CONCAT('%', '모던', '%')
   ) 
 	OR
   (`name` LIKE CONCAT('%', '단체', '%')
		OR `address` LIKE CONCAT('%', '단체', '%')
		OR `hashtag` LIKE CONCAT('%', '단체', '%')
   ) 

정규표현식 사용하여 필터버튼으로 선택된 키워드 카페 리스트에서 색상처리

//선택된 키워드와 일치하는 텍스트에 스타일 적용하는 함수
function applyStyleToMatchingText(selectedKeywords) {
    // 각 카페 아이템에 대해 반복
    $(".equal-filter").each(function() {
        var cafeItem = $(this);
        var text = cafeItem.text(); // 카페 아이템의 텍스트 가져오기

        // 선택된 키워드와 일치하는 부분에 스타일 적용
        selectedKeywords.forEach(function(keyword) {
          	// 대소문자 구분 없이 일치하는 모든 부분 찾기 위한 정규표현식(Regular Expression) 생성 
            var regex = new RegExp(keyword, "gi"); 
         	// 일치하는 부분에 스타일 적용
            text = text.replace(regex, '<span style="color: red;">$&</span>'); 
          
        });

        cafeItem.html(text); // 스타일이 적용된 텍스트로 카페 아이템 업데이트
    });
}

RegExp는 이런거래!

필터에서 전체선택 전체해제 처리만 해결하면 필터기능은 끝이나겠구나 ㅠㅠ
필터구현은... 설계부터 까다로워...

profile
hello world

0개의 댓글