ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 쇼핑몰 프로젝트 --리뷰 수정, 삭제, 아이템 검색, 정렬(화면구현)
    쇼핑몰 프로젝트 2024. 6. 26. 02:42

     

     

    먼저 리뷰를 수정, 삭제 할거다

     

     

    레파지토리

    public ItemReview findOneReview(Long itemReviewId) {
        return em.find(ItemReview.class, itemReviewId);
    }

     

     

    서비스

    public ItemReview findOneItemReview(Long itemReviewId) {
        return itemReviewRepository.findOneReview(itemReviewId);
    }

     

    @Transactional
    public void updateItemReview(Long itemReviewId, ItemReviewDto itemReviewDto) {
    
        ItemReview itemReview = itemReviewRepository.findOneReview(itemReviewId);
    
        if (itemReview == null) {
            throw new IllegalArgumentException("ItemReview not found with id: " + itemReviewId);
        }
    
        Long iRId = itemReview.changeItemReview(
                itemReviewDto.getItemScore(),
                itemReviewDto.getItemReviewName(),
                itemReviewDto.getItemReviewContent()
        );
    
    
        //평점 업데이트
        itemReview.getItem().updateItemRatings();
    
    }
    

     

    디티오

    package ypjs.project.dto.itemdto;
    
    import lombok.Data;
    import lombok.Getter;
    
    import java.time.LocalDateTime;
    
    @Data
    public class ItemReviewDto {
    
        private Long itemId;
        private Long itemReviewId;
        private int itemScore;
        private String itemReviewName;
        private String itemReviewContent;
    
    
        public ItemReviewDto() {}
    
    
        public ItemReviewDto(Long itemId, Long itemReviewId, int itemScore, String itemReviewName, String itemReviewContent) {
            this.itemId = itemId;
            this.itemReviewId = itemReviewId;
            this.itemScore = itemScore;
            this.itemReviewName = itemReviewName;
            this.itemReviewContent = itemReviewContent;
        }
    
    
    
    
    }
    

     

     

     

    컨트롤러

    // 수정보기
    @GetMapping("/ypjs/itemReview/update/{itemReviewId}")
    public String updateItemReview(@PathVariable("itemReviewId") Long itemReviewId, Model model) {
        ItemReview findItemReview = itemReviewService.findOneItemReview(itemReviewId);
    
        ItemReviewDto itemReview = new ItemReviewDto(
                findItemReview.getItem().getItemId(),
                findItemReview.getItemReviewId(),
                findItemReview.getItemScore(),
                findItemReview.getItemReviewName(),
                findItemReview.getItemReviewContent()
    
        );
    
    
    
        model.addAttribute("itemReview", itemReview);
    
        // 반환할 뷰 이름 (템플릿 파일 경로, 예: templates/itemReview/update.html)
        return "itemReview/itemReviewUpdate";
    }
    
    
    
    //수정등록
    @ResponseBody
    @PutMapping("/ypjs/itemReview/update/{itemReviewId}")
    public ResponseEntity updateItemReview(@PathVariable(name ="itemReviewId") Long itemReviewId,
                                           @RequestBody @Valid ItemReviewDto itemReviewDto,
                                           HttpSession session) {
    
        //멤버정보 찾기
        LoginDto.ResponseLogin responseLogin = (LoginDto.ResponseLogin) session.getAttribute("member");
    
    
        itemReviewService.updateItemReview(itemReviewId, itemReviewDto);
        ItemReview findItemReview = itemReviewService.findOneItemReview(itemReviewId);
    
        return ResponseEntity.ok().body(findItemReview.getItem().getItemId());
    
    }

     

     

    응답 방식은 나머지 컨트롤러도 다 저렇게 바꿨다.

     

     

    타임리프에 버튼 추가

    itemReview/itemReviewGet

     <input type="hidden" id="itemId" th:value="${itemReview.itemId}">
                <!-- 수정 및 삭제 버튼 -->
                <div class="container">
                    <div class="row justify-content-end">
                        <div class="col-auto">
                            <a th:href="@{/ypjs/itemReview/update/{itemReviewId}(itemReviewId=${itemReview.itemReviewId})}" class="btn btn-warning">수정하기</a>
                        </div>
                        <div class="col-auto">
    
                            <button type="button"
                                    class="btn btn-danger btn-sm btn-delete-itemReview"
                                    th:data-itemReviewId="${itemReview.itemReviewId}"
    
                                    style="padding: 2px 10px; font-size: 16px; width: 90px; height: 40px;">
                                삭제하기
                            </button>
                        </div>
    
                    </div>
                </div>
            </div>
        </div>
    </div>
    

     

    히든으로 아이템아이디 값 받아와야 삭제 후 원하는 화면(아이템 리뷰 리스트)으로 이동 가능

     

    수정 화면

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org" lang="en">
    <head th:replace="frame/header :: head">
        <title>Zay Shop - Product Listing Page</title>
    </head>
    <body>
    <!--header-->
    <header th:replace="frame/header :: header"></header>
    
    <!-- Start Content -->
    <div class="container py-5">
        리뷰수정
    </div>
    <!-- End Content -->
    
    <!-- jQuery -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <!-- Summernote 스타일 및 스크립트 -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.18/summernote-bs4.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.18/summernote-bs4.min.js"></script>
    
    <!-- JS 파일 포함 -->
    <script src="/js/jquery-1.11.0.min.js"></script>
    <script src="/js/summernote-lite.js"></script>
    <script src="/js/summernote-ko-KR.js"></script>
    <script src="/js/item/itemReview.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.18/summernote.min.js"></script>
    
    
    
    
    
    <!-- Start Contact -->
    <div class="container py-5">
        <div class="row py-5">
            <form class="col-md-9 m-auto" method="put">
                <!-- 폼 요소들 -->
                <div class="row">
    
                    <input type="hidden" id="itemReviewId" th:value="${itemReview.itemReviewId}">
    
    
                    <div class="form-group mb-3">
                        <label for="itemReviewName">제목</label>
                        <input type="text" class="form-control mt-1" id="itemReviewName" name="itemReviewName" th:value="${itemReview.itemReviewName}" placeholder="제목">
                    </div>
                    <div class="form-group mb-3">
                        <label for="itemScore">점수</label>
                        <input type="text" class="form-control mt-1" id="itemScore" name="itemScore" th:value="${itemReview.itemScore}" placeholder="점수">
                    </div>
                    <div class="mb-3">
                        <label for="itemReviewContent">내용</label>
                        <textarea class="form-control" id="itemReviewContent" name="itemReviewContent" th:text="${itemReview.itemReviewContent}" rows="10"></textarea>
                    </div>
    
                    <!-- Summernote 초기화 스크립트 -->
                    <script th:inline="javascript">
                        $(document).ready(function() {
                            $("#itemReviewContent").summernote({
                                height: 600, // 높이 설정
                                placeholder: '내용을 입력하세요...', // 플레이스홀더 설정
                                callbacks: {
                                    onChange: function(contents, $editable) {
                                        // 내용이 변경될 때 처리할 로직 추가 가능
                                    }
                                }
                            });
                        });
                    </script>
    
                    <!-- 글 등록 버튼 -->
                    <div class="row">
                        <div class="col text-end mt-2">
                            <button type="button" id="btn-itemReviewUpdate" class="btn btn-success btn-lg px-3">리뷰수정</button>
                        </div>
                    </div>
                </div>
            </form>
        </div>
    </div>
    <!-- End Contact -->
    
    <footer th:replace="frame/footer :: footer"></footer>
    </body>
    </html>
    
    
    

     

     

    js

    let itemBoardObject = {
        init: function() {
            let _this = this;
    
            $("#btn-itemReviewPost").on("click", function() {
                alert("리뷰등록 버튼이 클릭 됨");
                _this.insert();
            }),
             $("#btn-itemReviewUpdate").on("click", function() {
                        alert("수정이 요청되었습니다.");
                        _this.update();
                    }),
    
             $(document).on("click", ".btn-delete-itemReview", function() {
                       // 클릭된 버튼의 데이터 속성에서 itemReviewId를 가져옴
                       let itemReviewId = $(this).data("itemreviewid");
                       alert("삭제가 요청되었습니다.");
                        // 아이템 리뷰 삭제 함수 호출
                       _this.deleteItemReview(itemReviewId);
                        });
    
    
        },
    
        insert: function() {
            alert("리뷰 등록이 요청되었습니다.");
    
            let itemId = $("#itemId").val();  // URL에 사용할 itemId를 가져옴
    
            let data = {
                itemId: itemId,  // itemId를 데이터에 포함
                memberId: $("#memberId").val(),  // 멤버 ID 추가
                itemReviewName: $("#itemReviewName").val(),
                itemScore: $("#itemScore").val(),
                itemReviewContent: $("#itemReviewContent").val(),
            };
    
            $.ajax({
                type: "POST",
                url: "/ypjs/itemReview/post/" + itemId,  // URL에 itemId를 추가
                data: JSON.stringify(data),
                contentType: "application/json; charset=utf-8",
                success: function(response) {
                    alert("리뷰가 성공적으로 등록되었습니다.");
                    window.location.href = "/ypjs/item/get/" + itemId;  // 성공 후 리디렉션
                },
                error: function(error) {
                    alert("에러 발생: " + JSON.stringify(error));
                }
            });
        },
    
    
         update: function() {
    
            let itemReviewId = $("#itemReviewId").val();
    
    
                let updateData = {
    
                    itemReviewName: $("#itemReviewName").val(),
                    itemScore: $("#itemScore").val(),
                    itemReviewContent: $("#itemReviewContent").val(),
                };
    
                $.ajax({
                    type: "PUT",
    
                    url: "/ypjs/itemReview/update/" + itemReviewId,
                    data: JSON.stringify(updateData),
                    contentType: "application/json; charset=utf-8",
                    success: function(response) {
                    window.location.href = "/ypjs/itemReview/get/" + response ;
    
                    },
                    error: function(error) {
                        alert("에러 발생: " + JSON.stringify(error));
                        // 에러 발생 시 적절히 처리하도록 수정이 필요할 수 있습니다.
                    }
                });
            },
    
    
    
    
             deleteItemReview: function(itemReviewId) {
    
                     let itemId = $("#itemId").val();
    
                     $.ajax({
                         type: "DELETE",
                         url: "/ypjs/itemReview/delete/" + itemReviewId,
                         success: function(response) {
                             alert("리뷰가 성공적으로 삭제되었습니다.");
    
                             window.location.href = "/ypjs/itemReview/get/" + itemId;
                         },
                         error: function(xhr, status, error) {
                             alert("에러 발생: " + error);
                         }
                     });
                 }
    
    
            };
    
    
    
    $(document).ready(function() {
        itemBoardObject.init();
    });
    
    
    
    
    

     

    등록 ,수정, 삭제 같이 

     

     

     

     

    삭제 

    레파지토리

    //리뷰 삭제
    public void deleteItemReview(Long itemReviewId) {
        ItemReview findItemReivew = em.find(ItemReview.class, itemReviewId);
        em.remove(findItemReivew);
    }

     

    서비스

    // 리뷰 삭제
    @Transactional
     public void deleteItemReview(Long itemReviewId) {
         ItemReview itemReview = findOneItemReview(itemReviewId);
         Item item = itemReview.getItem();
    
         itemReviewRepository.deleteItemReview(itemReviewId);
    
         item.removeItemReview(itemReview);
    
         item.updateItemRatings();
    
    
    
     }
    

     

     

    컨트롤러

    //삭제
    @DeleteMapping("/ypjs/itemReview/delete/{itemReviewId}")
    public ResponseEntity deleteItemReview(@PathVariable("itemReviewId") Long itemReviewId){
        itemReviewService.deleteItemReview(itemReviewId);
    
        return ResponseEntity.ok().build();
    }
    

     

     

     

    검색, 정렬

     

    레파지토리 

    //카테고리당 아이템리스트
    public List<Item> findAllItemPagingSortByAndKeyword(Long categoryId, String keyword, Pageable pageable, String sortBy) {
        String queryString = "select distinct i from Item i" +
                " join fetch i.category c" +
                " where i.category.categoryId = :categoryId";
    
        // 검색 조건 추가
        boolean hasKeyword = (keyword != null && !keyword.isEmpty());
        if (hasKeyword) {
            queryString += " and i.itemName like :keyword";
        }
    
    
        queryString += " order by "; // 기본 order by 절을 먼저 추가
        switch (sortBy) {
            case "itemRatings":
                queryString += "i.itemRatings desc, i.itemId desc"; // itemRatings로 정렬, 동일한 rating이면 itemId로 정렬
                break;
            case "likeCount":
                queryString += "i.likeCount desc, i.itemId desc"; // likeCount로 정렬, 동일한 likeCount이면 itemId로 정렬
                break;
            case "itemId":
            default:
                queryString += "i.itemId desc"; // 기본적으로 itemId로 정렬
                break;
        }
    
        TypedQuery<Item> query = em.createQuery(queryString, Item.class)
                .setParameter("categoryId", categoryId)
                .setFirstResult((int) pageable.getOffset())
                .setMaxResults(pageable.getPageSize());
    
        // 검색 키워드 파라미터 설정
        if (hasKeyword) {
            query.setParameter("keyword", "%" + keyword + "%");
        }
    
        return query.getResultList();
    }
    
    
    //아이템 전체리스트
    public List<Item> findAllItem(String keyword, Pageable pageable, String sortBy) {
        // 기본 쿼리
        String queryString = "select i from Item i";
    
        // 검색 조건 추가
        boolean hasKeyword = (keyword != null && !keyword.isEmpty());
        if (hasKeyword) {
            queryString += " where i.itemName like :keyword";
        }
    
        // 정렬 조건
        queryString += " order by ";
        switch (sortBy) {
            case "itemRatings":
                queryString += "i.itemRatings desc, i.itemId desc";
                break;
            case "likeCount":
                queryString += "i.likeCount desc, i.itemId desc";
                break;
            case "itemId":
            default:
                queryString += "i.itemId desc";
                break;
        }
    
        TypedQuery<Item> query = em.createQuery(queryString, Item.class)
                .setFirstResult((int) pageable.getOffset())
                .setMaxResults(pageable.getPageSize());
    
        // 검색 키워드 파라미터 설정
        if (hasKeyword) {
            query.setParameter("keyword", "%" + keyword + "%");
        }
    
        return query.getResultList();
    }
    
    

     

    if문으로 했을 때는 정렬이 안됐는데 switch로 바꾸니까 정렬 됨

     

     

    서비스

    //카테고리당 아이템 조회(정렬,검색,페이징)
    public List<ItemListDto> finaAllItemPagingSortBy(Long categoryId, String keyword, Pageable pageable, String sortBy) {
        List<Item> items = itemRepository.findAllItemPagingSortByAndKeyword(categoryId, keyword, pageable, sortBy);
    
        List<ItemListDto> result = items.stream()
                .map(ItemListDto::new)
                .collect(Collectors.toList());
    
        return result;
    
    }
    
    
    
    //아이템 아이디 전체 조회
    public List<ItemListDto> findAllItem(String keyword, Pageable pageable, String sortBy) {
        List<Item> items = itemRepository.findAllItem(keyword, pageable, sortBy);
    
    
        List<ItemListDto> result = items.stream()
                .map(ItemListDto::new)
                .collect(Collectors.toList());
    
        return result;
    
    }
    

     

     

    컨트롤러

    //카테고리당 아이템 조회(정렬,검색,페이징(페이징받아서 페이징))
    @GetMapping("/ypjs/categoryItem/get/{categoryId}")
    public String getAllCategoryItem(@PathVariable("categoryId") Long categoryId,
                                     @RequestParam(value = "page",defaultValue = "0") int page,
                                     @RequestParam(value = "size",defaultValue = "6") int size,
                                     @RequestParam(value = "sortBy", defaultValue = "itemId") String sortBy,
                                     @RequestParam(value = "keyword", required = false) String keyword,
                             Model model) {
    
        Pageable pageable = PageRequest.of(page, size);
    
        Category category = categoryService.findOneCategory(categoryId);
    
        List<ItemListDto> items = itemService.finaAllItemPagingSortBy(categoryId, keyword, pageable, sortBy);
    
        model.addAttribute("items",items);
        model.addAttribute("category", category);
        model.addAttribute("sortBy", sortBy); // 정렬 옵션을 다시 모델에 추가
        model.addAttribute("keyword", keyword); //검색조건 유지
    
    
    
        return "item/itemCategoryList";
    
    
    }
    
    
    
    //아이템 전체 조회
    @GetMapping("/ypjs/item/get")
    public String getAllItem(
                                     @RequestParam(value = "page",defaultValue = "0") int page,
                                     @RequestParam(value = "size",defaultValue = "6") int size,
                                     @RequestParam(value = "sortBy", defaultValue = "itemId") String sortBy,
                                     @RequestParam(value = "keyword", required = false) String keyword,
                                     Model model) {
    
        Pageable pageable = PageRequest.of(page, size);
    
        List<ItemListDto> items = itemService.findAllItem(keyword, pageable, sortBy);
    
        model.addAttribute("items", items);
        model.addAttribute("sortBy", sortBy); // 정렬 옵션을 다시 모델에 추가
        model.addAttribute("keyword", keyword); //검색조건 유지
    
    
        return "item/itemList";
    
    
    }
    

     

     

     

    타임리프

    item/itemList

    <div class="col-lg-6">
        <!-- 검색 폼 및 정렬 폼 통합 -->
        <form th:action="@{/ypjs/item/get}" method="get" class="input-group">
            <input type="text" id="keyword" name="keyword" class="form-control"
                   placeholder="제목으로 검색하기" th:value="${keyword}">
            <div class="input-group-append">
                <button type="submit" class="btn btn-link text-dark">
                    <i class="fa fa-search"></i>
                </button>
            </div>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            <div class="col-auto">
                <select class="form-control" name="sortBy" id="sortBy" onchange="this.form.submit()">
                    <option value="itemId" th:selected="${sortBy == 'itemId'}">최신순</option>
                    <option value="itemRatings" th:selected="${sortBy == 'itemRatings'}">별점 높은 순</option>
                    <option value="likeCount" th:selected="${sortBy == 'likeCount'}">찜많은순</option>
                </select>
            </div>
        </form>
    </div>

     

     

    item/itemCategoryList

    <div class="col-lg-6">
        <!-- 검색 폼 및 정렬 폼 통합 -->
        <form th:action="@{/ypjs/categoryItem/get/{categoryId}(categoryId=${category.categoryId})}" method="get" class="input-group">
            <input type="text" id="keyword" name="keyword" class="form-control"
                   placeholder="제목으로 검색하기" th:value="${keyword}">
            <div class="input-group-append">
                <button type="submit" class="btn btn-link text-dark">
                    <i class="fa fa-search"></i>
                </button>
            </div>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            <div class="col-auto">
                <select class="form-control" name="sortBy" id="sortBy" onchange="this.form.submit()">
                    <option value="itemId" th:selected="${sortBy == 'itemId'}">최신순</option>
                    <option value="itemRatings" th:selected="${sortBy == 'itemRatings'}">별점 높은 순</option>
                    <option value="likeCount" th:selected="${sortBy == 'likeCount'}">찜많은순</option>
                </select>
            </div>
        </form>
    </div>
    
    
    

     

    추가

     

     

     

     

    모든 아이템 별점 높은 순 

     

     

     

     

    카테고리 4번에 제목 2 별점 높은 순

Designed by Tistory.