ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 쇼핑몰 프로젝트 -- 카테고리, 리뷰(화면구현)
    쇼핑몰 프로젝트 2024. 6. 20. 04:51

     

     

    어제 아이템 전체 조회를 해서 오늘은 카테고리별 아이템 조회를 했다. 

    categoryRepository

    //categoryId 단건조회
    public Category findOneCategory(Long categoryId) {
        if (categoryId == null) {
            throw new IllegalArgumentException("Category ID must not be null");
        }
        Category category = em.find(Category.class, categoryId);
    
        if (category == null) {
            throw new IllegalArgumentException("Category not found for ID: " + categoryId);
        }
        return category;
    }

     

    //카테고리 당 아이템 조회(검색, 정렬, 페이징)
    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 i.itemId desc"; // 최신순으로 정렬 (itemId가 클수록 최신 데이터)
    
        // 추가 정렬 조건
        if ("itemRatings".equals(sortBy)) {
            queryString += ", i.itemRatings desc";
        } else if ("likeCount".equals(sortBy)) {
            queryString += ", i.likeCount desc";
        }
    
        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();
    }

     

    itemService

    //categoryId단건조회
    public Category findOneCategory(Long categoryId) {
        return categoryRepository.findOneCategory(categoryId);
    }

     

     

    //카테고리당 아이템 조회(정렬,검색,페이징)
    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;
    
    }

     

     

    itemController

    //카테고리당 아이템 조회(정렬,검색,페이징(페이징받아서 페이징))
        @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);
    
            categoryService.findOneCategory(categoryId);
    
            List<ItemListDto> items = itemService.finaAllItemPagingSortBy(categoryId, keyword, pageable, sortBy);
    
    //        CategoryOneDto category = new CategoryOneDto(findCategory, items);
    
            model.addAttribute("items",items);
    
    
    
            return "item/itemCategoryList";
    
    
        }

     

    item/itemCategoryList

    <!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>
    
    <style>
        .fixed-size-img {
            width: 300px; /* 원하는 너비로 설정 */
            height: 300px; /* 원하는 높이로 설정 */
            object-fit: cover; /* 이미지를 크기에 맞게 조정 */
        }
    </style>
    
    <body>
    <!--header-->
    <header th:replace="frame/header :: header"></header>
    
    <!-- Start Content -->
    <div class="container py-5">
        <div class="row">
    
            <div class="col-lg-3">
                <h1 class="h2 pb-4">Categories</h1>
                <ul class="list-unstyled templatemo-accordion">
                    <li class="pb-3">
                        <a class="collapsed d-flex justify-content-between h3 text-decoration-none" href="#">
                            Women
                            <i class="fa fa-fw fa-chevron-circle-down mt-1"></i>
                        </a>
                        <ul class="collapse show list-unstyled pl-3">
                            <li><a class="text-decoration-none" th:href="@{/ypjs/categoryItem/get/{categoryId}(categoryId=3)}">Outer</a></li>
                            <li><a class="text-decoration-none" th:href="@{/ypjs/categoryItem/get/{categoryId}(categoryId=4)}">Top</a></li>
                            <li><a class="text-decoration-none" th:href="@{/ypjs/categoryItem/get/{categoryId}(categoryId=5)}">Bottom</a></li>
                        </ul>
                    </li>
                    <li class="pb-3">
                        <a class="collapsed d-flex justify-content-between h3 text-decoration-none" href="#">
                            Man
                            <i class="pull-right fa fa-fw fa-chevron-circle-down mt-1"></i>
                        </a>
                        <ul id="collapseTwo" class="collapse list-unstyled pl-3">
                            <li><a class="text-decoration-none" th:href="@{/ypjs/categoryItem/get/{categoryId}(categoryId=6)}">Outer</a></li>
                            <li><a class="text-decoration-none" th:href="@{/ypjs/categoryItem/get/{categoryId}(categoryId=7)}">Top</a></li>
                            <li><a class="text-decoration-none" th:href="@{/ypjs/categoryItem/get/{categoryId}(categoryId=8)}">Bottom</a></li>
                        </ul>
                    </li>
    
                </ul>
            </div>
    
            <div class="col-lg-9">
                <div class="row">
                    <div class="col-md-6">
                        <ul class="list-inline shop-top-menu pb-3 pt-1">
                            <li class="list-inline-item">
                                <a class="h3 text-dark text-decoration-none mr-3" th:href="@{/ypjs/item/get}">All Items</a>
                            </li>
    
                        </ul>
                    </div>
    
    
                    <div class="col-md-6 pb-4">
                        <div class="d-flex">
                            <select class="form-control">
                                <option>최신순</option>
                                <option>별점높은순</option>
                                <option>찜많은순</option>
                            </select>
                        </div>
                    </div>
                </div>
    
    
                <div class="container-fluid mt-3">
                    <div class="row">
                        <!-- items 리스트의 각 항목을 반복 -->
                        <div th:each="item : ${items}" class="col-md-4">
                            <div class="card mb-4 product-wap rounded-0">
                                <!-- 제품 이미지 -->
                                <div class="card rounded-0">
                                    <a th:href="@{/ypjs/item/get/{itemId}(itemId=${item.itemId})}">
                                        <img class="card-img rounded-0 img-fluid fixed-size-img" th:src="${item.itemFilePath}" alt="product-item">
                                        <!-- 필요한 경우 오버레이나 추가 요소를 여기에 추가할 수 있습니다 -->
                                        <div class="card-img-overlay rounded-0 product-overlay d-flex align-items-center justify-content-center">
                                            <!-- 추가적인 콘텐츠가 필요하다면 여기에 추가할 수 있습니다 -->
                                            <ul class="list-unstyled">
                                                <!-- 리스트의 다른 요소들 -->
                                            </ul>
                                        </div>
                                    </a>
                                </div>
                                <!-- 제품 정보 -->
                                <div class="card-body">
                                    <!-- 제품 링크 -->
                                    <a th:href="@{/ypjs/item/get/{itemId}(itemId=${item.itemId})}" id="itemName" class="font-weight-bold" th:text="${item.itemName}"></a>
    
                                    <!-- 별점 표시 -->
                                    <ul class="list-unstyled d-flex justify-content-center mb-1">
                                        <li>
                                            <i class="text-warning fa fa-star"></i>
                                            <i class="text-warning fa fa-star"></i>
                                            <i class="text-warning fa fa-star"></i>
                                            <i class="text-muted fa fa-star"></i>
                                            <i class="text-muted fa fa-star"></i>
                                        </li>
                                    </ul>
                                    <!-- 가격 표시 -->
                                    <span id="itemPrice" class="font-weight-bold" th:text="${item.itemPrice}"></span>
                                    <span class="font-weight-bold">원</span>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
    
    
    
    
    
    
    
    
            </div>
        </div>
    
    </div>
    </div>
    <!-- End Content -->
    
    <!-- Start Brands -->
    <section class="bg-light py-5">
        <div class="container my-4">
            <div class="row text-center py-3">
                <div class="col-lg-6 m-auto">
                    <h1 class="h1">Our Brands</h1>
                    <p>
                        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
                        Lorem ipsum dolor sit amet.
                    </p>
                </div>
                <div class="col-lg-9 m-auto tempaltemo-carousel">
                    <div class="row d-flex flex-row">
                        <!--Controls-->
                        <div class="col-1 align-self-center">
                            <a class="h1" href="#multi-item-example" role="button" data-bs-slide="prev">
                                <i class="text-light fas fa-chevron-left"></i>
                            </a>
                        </div>
                        <!--End Controls-->
    
                        <!--Carousel Wrapper-->
                        <div class="col">
                            <div class="carousel slide carousel-multi-item pt-2 pt-md-0" id="multi-item-example" data-bs-ride="carousel">
                                <!--Slides-->
                                <div class="carousel-inner product-links-wap" role="listbox">
    
                                    <!--First slide-->
                                    <div class="carousel-item active">
                                        <div class="row">
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_01.png" alt="Brand Logo"></a>
                                            </div>
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_02.png" alt="Brand Logo"></a>
                                            </div>
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_03.png" alt="Brand Logo"></a>
                                            </div>
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_04.png" alt="Brand Logo"></a>
                                            </div>
                                        </div>
                                    </div>
                                    <!--End First slide-->
    
                                    <!--Second slide-->
                                    <div class="carousel-item">
                                        <div class="row">
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_01.png" alt="Brand Logo"></a>
                                            </div>
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_02.png" alt="Brand Logo"></a>
                                            </div>
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_03.png" alt="Brand Logo"></a>
                                            </div>
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_04.png" alt="Brand Logo"></a>
                                            </div>
                                        </div>
                                    </div>
                                    <!--End Second slide-->
    
                                    <!--Third slide-->
                                    <div class="carousel-item">
                                        <div class="row">
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_01.png" alt="Brand Logo"></a>
                                            </div>
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_02.png" alt="Brand Logo"></a>
                                            </div>
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_03.png" alt="Brand Logo"></a>
                                            </div>
                                            <div class="col-3 p-md-5">
                                                <a href="#"><img class="img-fluid brand-img" src="/img/brand_04.png" alt="Brand Logo"></a>
                                            </div>
                                        </div>
                                    </div>
                                    <!--End Third slide-->
    
                                </div>
                                <!--End Slides-->
                            </div>
                        </div>
                        <!--End Carousel Wrapper-->
    
                        <!--Controls-->
                        <div class="col-1 align-self-center">
                            <a class="h1" href="#multi-item-example" role="button" data-bs-slide="next">
                                <i class="text-light fas fa-chevron-right"></i>
                            </a>
                        </div>
                        <!--End Controls-->
                    </div>
                </div>
            </div>
        </div>
    </section>
    <!--End Brands-->
    
    
    <footer th:replace="frame/footer :: footer"></footer>
    
    </body>
    
    </html>

     

     

    카테고리 3번에 해당하는 화면 

     

     

     

     

    카테고리 리스트 전체 조회 

     

    categoryRepository

    // category 전체 조회
    public List<Category> findAll(Long categoryId, String keyword, Pageable pageable) {
        String queryString = "select c from Category c where 1=1";
    
        // 카테고리 아이디로 검색 조건 추가
        if (categoryId != null) {
            queryString += " and c.categoryId = :categoryId";
        }
    
        // 키워드로 카테고리 이름 검색 조건 추가
        if (keyword != null && !keyword.isEmpty()) {
            queryString += " and c.categoryName like :keyword";
        }
    
        // 카테고리 아이디와 키워드가 모두 비어 있는 경우
        if (categoryId == null && (keyword == null || keyword.isEmpty())) {
            // 이 경우, 전체 카테고리를 조회하도록 queryString에 추가 조건 없음
            queryString = "select c from Category c";
        }
    
        TypedQuery<Category> query = em.createQuery(queryString, Category.class)
                .setFirstResult((int) pageable.getOffset())
                .setMaxResults(pageable.getPageSize());
    
        // 매개변수 바인딩
        if (categoryId != null) {
            query.setParameter("categoryId", categoryId);
        }
        if (keyword != null && !keyword.isEmpty()) {
            query.setParameter("keyword", "%" + keyword + "%");
        }
    
        return query.getResultList();
    }
    
    
    
    

     

     

     

     

    categoryService

    //category전체 조회
    public List<CategoryListDto> findAllCategory(Long categoryId, String keyword, Pageable pageable) {
    
       //List<Category> categories = categoryRepository.findAllWithItem();
        List<Category> categories = categoryRepository.findAll(categoryId, keyword, pageable);
    
    
        List<CategoryListDto> result = categories.stream()
                .map(c -> new CategoryListDto(c))
                .collect(Collectors.toList());
    
        return result;
    }
    

     

     

     

    categoryController

    //categoryList보기
    @GetMapping("/ypjs/category/get")
    public String getCategoryList(Model model,
                                  @RequestParam(value = "categoryId", required = false) Long categoryId,
                                  @RequestParam(value = "page", defaultValue = "0") int page,
                                  @RequestParam(value = "size", defaultValue = "8") int size,
                                  @RequestParam(value = "keyword", required = false) String keyword) {
    
        Pageable pageable = PageRequest.of(page, size);
    
        List<CategoryListDto> categories = categoryService.findAllCategory(categoryId, keyword, pageable);
    
        model.addAttribute("categories", categories);
    
        return "category/categoryList";
    }

     

     

    category/categoryList

    <!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>
    
    
    
    
    <!-- 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/category.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="post"  >
                <!-- 폼 요소들 -->
                <div class="row">
    
    
    
                    <style>
                        .category-box {
                            border: 1px solid #ccc;
                            padding: 10px;
                            margin-bottom: 10px;
                        }
    
                        .category-label {
                            font-weight: bold;
                        }
                    </style>
    
                    <div th:each="category : ${categories}" class="category-box">
                        <div>
                            <span class="category-label">카테고리 번호 </span>
                            &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                            <a th:href="@{/ypjs/category/get/{categoryId}(categoryId=${category.categoryId})}" th:text="${category.categoryId}"></a>
                        </div>
                        <div>
                            <span class="category-label">카테고리 부모 번호 </span>
                            &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                            <span th:text="${category.categoryParent}"></span>
                        </div>
                        <div>
                            <span class="category-label">카테고리 이름 </span>
                            &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                            <span th:text="${category.categoryName}"></span>
                        </div>
                    </div>
    
    
    
    
                    <!-- End Contact -->
    
                </div>
            </form>
    
    </div>
    </div>
    
    
    <footer th:replace="frame/footer :: footer"></footer>
    
    </body>
    
    </html>
    

     

     

    여기서 카테고리 보기를 누르면

     

     

    이렇게 쭉 카테고리 리스트가 나온다. 

     



    이제 카테고리를 등록할 거다 

    categoryRepository

    //categoryId 단건조회
    public Category findOneCategory(Long categoryId) {
        if (categoryId == null) {
            throw new IllegalArgumentException("Category ID must not be null");
        }
        Category category = em.find(Category.class, categoryId);
    
        if (category == null) {
            throw new IllegalArgumentException("Category not found for ID: " + categoryId);
        }
        return category;
    }
    

     

    //카테고리 저장
    public void saveCategory(Category  category) {
            em.persist(category);
    
    }

     

     

    categoryService

    //category등록
    @Transactional
    public Category saveCategory(CategoryRequestDto categoryRequestDto) {
        Category parentCategory = categoryRepository.findOneCategory(categoryRequestDto.getCategoryParent());
    
        Category category = new Category(
                parentCategory,
                categoryRequestDto.getCategoryName()
        );
    
        categoryRepository.saveCategory(category);
    
        return category;
    }

     

     

    categoryContoller

    //카테고리 등록 화면
    @GetMapping("/ypjs/category/post")
    public String insert() {return "category/categoryPost";}
    
    
    
    //category등록
    @PostMapping("/ypjs/category/post")
    public CategoryRespnseDto saveCategory(@RequestBody @Valid CategoryRequestDto categoryRequestDtorequest,
                                           HttpSession session){
        //멤버정보 찾기
        LoginDto.ResponseLogin responseLogin = (LoginDto.ResponseLogin) session.getAttribute("member");
    
    
        Category category = categoryService.saveCategory(categoryRequestDtorequest);
    
        return new CategoryRespnseDto(category.getCategoryId(), category.getCategoryParent(), category.getCategoryName());
    }

     

     

    category/categoryPost

    <!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>
    
    <!-- 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/category.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="post">
                <!-- 폼 요소들 -->
                <div class="row">
                    <div class="form-group mb-3">
                        <label for="categoryParent">카테고리 부모 번호</label>
                        <input type="text" class="form-control mt-1" id="categoryParent" name="categoryParent"
                               placeholder="카테고리 부모 번호">
                    </div>
                    <div class="form-group mb-3">
                        <label for="categoryName">카테고리 이름</label>
                        <input type="text" class="form-control mt-1" id="categoryName" name="categoryName"
                               placeholder="카테고리 이름">
                    </div>
    
                    <!-- 글 등록 버튼 -->
                    <div class="row">
                        <div class="col text-end mt-2">
                            <!-- 버튼 id가 btn-categoryPost로 변경되었습니다. -->
                            <button type="button" id="btn-categoryPost" 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>
    

     

     

    category.js

    let categoryBoardObject = {
        init: function() {
            let _this = this;
    
            $("#btn-categoryPost").on("click", function() {
                alert("카테고리 저장 버튼 클릭됨");
                _this.insert();
            }),
    
            $("#btn-categoryUpdate").on("click", function() {
                alert("수정이 요청되었습니다.");
                _this.update();
            }),
              $("#btn-categoryDelete").on("click", () => {
                  alert("삭제가 요청되었습니다.");
                        _this.delete();
                    });
        },
    
        insert: function() {
            alert("카테고리 등록이 요청되었습니다.");
    
            let data = {
                categoryParent: $("#categoryParent").val(),
                categoryName: $("#categoryName").val(),
            };
    
            $.ajax({
                type: "POST",
                url: "/ypjs/category/post",
                data: JSON.stringify(data),
                contentType: "application/json; charset=utf-8",
                success: function(response) {
                    window.location.href = "/ypjs/item/get";
                },
                error: function(error) {
    
                    window.location.href = "/ypjs/item/get";
                }
            });
        },
    
        update: function() {
    
        let categoryId = $("#categoryId").val();
    
            let updateData = {
                categoryId: $("#categoryId").val(),
                categoryParent: $("#categoryParent").val(),
                categoryName: $("#categoryName").val(),
            };
    
            $.ajax({
                type: "PUT",
                // URL 경로 조합 시, 경로와 id 값을 올바르게 분리하고 '/'를 추가합니다.
                url: "/ypjs/category/update/" + categoryId,
                data: JSON.stringify(updateData),
                contentType: "application/json; charset=utf-8",
                success: function(response) {
                    window.location.href = "/ypjs/item/get";
                },
                error: function(error) {
                    alert("에러 발생: " + JSON.stringify(error));
                    // 에러 발생 시 적절히 처리하도록 수정이 필요할 수 있습니다.
                }
            });
        },
         delete: function() {
                // itemId 가져오기
                let categoryId = $("#categoryId").val();
    
                $.ajax({
                    type: "DELETE",
                    url: "/ypjs/category/delete/" + categoryId,
                    success: function(response) {
                        alert(response.data); // 성공 메시지 처리
                        window.location.href = "/test"; // 삭제 후 페이지 이동
                    },
                    error: function(xhr, status, error) {
                        alert("에러 발생: " + error);
                    }
                });
            }
    };
    
    $(document).ready(function() {
        categoryBoardObject.init();
    });
    

     

     

    js는 같이 수정, 등록까지 

     



     

     

    이 화면이 나온다. 

     

     

     

     

    카테고리 단건 조회
    categoryRespository

    //categoryId 단건조회
    public Category findOneCategory(Long categoryId) {
        if (categoryId == null) {
            throw new IllegalArgumentException("Category ID must not be null");
        }
        Category category = em.find(Category.class, categoryId);
    
        if (category == null) {
            throw new IllegalArgumentException("Category not found for ID: " + categoryId);
        }
        return category;
    }
    

     

     

    //(카테고리당 아이템 조회)
    public List<Item> findAllItems(Long categoryId, Pageable pageable) {
        String queryString = "select i from Item i where i.category.categoryId = :categoryId order by i.itemId desc";
    
        TypedQuery<Item> query = em.createQuery(queryString, Item.class)
                .setParameter("categoryId", categoryId)
                .setFirstResult((int) pageable.getOffset())
                .setMaxResults(pageable.getPageSize());
    
        return query.getResultList();
    }

     

     

     

    categoryService

    //categoryId단건조회
    public Category findOneCategory(Long categoryId) {
        return categoryRepository.findOneCategory(categoryId);
    }
    

     

    //카테고리 당 아이템 조회
    public List<ItemListDto> findAllCategoryItem(Long categoryId, Pageable pageable) {
        List<Item> items = itemRepository.findAllItems(categoryId,pageable);
    
        List<ItemListDto> result = items.stream()
                .map(ItemListDto::new)
                .collect(Collectors.toList());
    
        return result;
    }

     

     

     

     

    categoryController

      //category 1개 조회
        @GetMapping("/ypjs/category/get/{categoryId}")
        public String getOneCategory (@PathVariable("categoryId") Long categoryId,
                                       Model model,
                                      @RequestParam(value = "page", defaultValue = "0") int page,
                                      @RequestParam(value = "size", defaultValue = "5") int size) {
    
    
            Pageable pageable = PageRequest.of(page, size);
    
            Category findCategory = categoryService.findOneCategory(categoryId);
    
            List<ItemListDto> items = itemService.findAllCategoryItem(categoryId, pageable);
    
    //        CategoryOneDto category = new CategoryOneDto( findCategory, items);
    
            model.addAttribute("category", findCategory);
            model.addAttribute("items",items);
    
            return "category/categoryGet";
    
    
        }
    

     

     

    category/categoryGet

    <!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>
    
    
    
    
    <!-- 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/category.js"></script>
    <script src="/js/item/item.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="post"  >
                <!-- 폼 요소들 -->
                <div class="row">
    
    
    
    
    
                    <style>
                        .category-box {
                            border: 1px solid #ccc;
                            padding: 10px;
                            margin-bottom: 10px;
                        }
    
                        .category-label {
                            font-weight: bold;
                        }
    
                        .item-box {
        border: 1px solid #ccc;
        padding: 10px;
        margin-bottom: 10px;
    }
    
    .item-info {
        /* Optional: Add additional styles for item information */
    }
    
    .category-label {
        font-weight: bold;
    }
    
    
                    </style>
    
    
    
    
    
    
                    <div class="category-box">
                        <div>
                            <span class="category-label">카테고리 번호:</span>
                            &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                            <span th:text="${category.categoryId}"></span>
                        </div>
                        <div>
                            <span class="category-label">카테고리 부모 번호:</span>
                            &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                            <span th:text="${category.categoryParent.categoryId}"></span>
                        </div>
                        <div>
                            <span class="category-label">카테고리 이름:</span>
                            &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                            <span th:text="${category.categoryName}"></span>
                        </div>
    
    
                        <br>
    
                        <div class="container">
                            <div class="row justify-content-end">
                                <div class="col-auto">
                                    <input type="hidden" id="categoryId" th:value="${category.categoryId}">
                                    <a th:href="@{/ypjs/category/update/{categoryId}(categoryId=${category.categoryId})}" class="btn btn-warning">수정하기</a>
    
                                </div>
                                <div class="col-auto">
                                    <button type="button" id="btn-categoryDelete" class="btn btn-danger">삭제하기</button>
                                </div>
                            </div>
                        </div>
                    </div>
    
    
                    <div th:if="${not #lists.isEmpty(items)}">
                        <br><br><br>
                        <h3>아이템 목록</h3>
                        <br>
                        <div th:each="item : ${items}" class="item-box">
                            <div class="item-info">
                                <div>
                                    <span class="category-label">아이템 이름:</span>
                                    &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                                    <span th:text="${item.itemName}"></span>
                                </div>
                                <div>
                                    <span class="category-label">아이템 내용:</span>
                                    &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                                    <span th:utext="${item.itemContent}"></span>
                                </div>
                                <div>
                                    <span class="category-label">아이템 가격:</span>
                                    &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                                    <span th:text="${item.itemPrice}"></span>
                                </div>
                                <div>
                                    <span class="category-label">아이템 수량:</span>
                                    &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                                    <span th:text="${item.itemStock}"></span>
                                </div>
                                <!-- 필요한 다른 아이템 정보들을 추가 -->
                                <div class="container">
                                    <div class="row justify-content-end">
                                        <div class="col-auto">
                                            <a th:href="@{/ypjs/item/update/{itemId}(itemId=${item.itemId})}"
                                               class="btn btn-warning"
                                               style="padding: 2px 10px; font-size: 12px; width: 90px; height: 40px; text-align: center; display: inline-block; line-height: 40px;">
                                                수정하기
                                            </a>
                                        </div>
                                        &nbsp;
                                        <button type="button"
                                                class="btn btn-danger btn-sm btn-delete-item"
                                                th:attr="data-itemId=${item.itemId}"
                                                style="padding: 2px 10px; font-size: 16px; width: 90px; height: 40px;">
                                            삭제하기
                                        </button>
    
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
    
    
    
                    <!-- End Contact -->
    
    
    </div>
            </form>
                </div>
        </div>
    
    
        <footer th:replace="frame/footer :: footer"></footer>
    
    </body>
    
    </html>
    

     

     

     

    카테고리 번호에 해당하는 모든 아이템이 나온다. 

     

     

     

    카테고리 수정

    categoryRespository

    //categoryId 단건조회
    public Category findOneCategory(Long categoryId) {
        if (categoryId == null) {
            throw new IllegalArgumentException("Category ID must not be null");
        }
        Category category = em.find(Category.class, categoryId);
    
        if (category == null) {
            throw new IllegalArgumentException("Category not found for ID: " + categoryId);
        }
        return category;
    }
    

     

     

    categoryService

    //categoryId단건조회
    public Category findOneCategory(Long categoryId) {
        return categoryRepository.findOneCategory(categoryId);
    }

     

     

     

    categoryController

    //카테고리수정보기
        @GetMapping("/ypjs/category/update/{categoryId}")
        public String updateCategory(@PathVariable("categoryId") Long categoryId, Model model) {
    
            Category findCategory = categoryService.findOneCategory(categoryId);
    
            CategoryUpdateDto category = new CategoryUpdateDto(findCategory.getCategoryId(),
                    findCategory.getCategoryParent().getCategoryId(),
                    findCategory.getCategoryName());
    
            model.addAttribute("category", category);
            return "category/categoryUpdate";
        }
    
    
    
    
        //category수정
        @ResponseBody
        @PutMapping("ypjs/category/update/{categoryId}")
        public CategoryUpdateDto updateCategory(@PathVariable("categoryId") Long categoryId,
                                                @RequestBody @Valid CategoryUpdateDto categoryUpdateDto) {
    
            categoryService.updateCategory(categoryId, categoryUpdateDto);
            Category findCategory = categoryService.findOneCategory(categoryId);
    
    
           return new CategoryUpdateDto(findCategory.getCategoryId(), findCategory.getCategoryParent().getCategoryId(), findCategory.getCategoryName());
       }

     

     

     

    category/categoryUpdate

    <!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>
    
    
    
    
    <!-- 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/category.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="post"  >
                <!-- 폼 요소들 -->
                <div class="row">
    
                    <div class="form-group mb-3">
                        <label for="categoryId">카테고리 번호</label>
                        <input type="text" class="form-control mt-1" id="categoryId" name="categoryId" th:value="${category.categoryId}" placeholder="카테고리 번호">
                    </div>
                    <div class="form-group mb-3">
                        <label for="categoryParent">카테고리 부모 번호</label>
                        <input type="text" class="form-control mt-1" id="categoryParent" name="categoryParent" th:value="${category.categoryParent}" placeholder="카테고리 부모 번호">
                    </div>
                    <div class="form-group mb-3">
                        <label for="categoryName">카테고리 이름</label>
                        <input type="text" class="form-control mt-1" id="categoryName" name="categoryName" th:value="${category.categoryName}" placeholder="카테고리 이름">
                    </div>
    
    
    
    
                    <!-- 글 등록 버튼 -->
                    <div class="row">
                        <div class="col text-end mt-2">
    
                            <button type="button" id="btn-categoryUpdate" class="btn btn-success btn-lg px-3">수정하기</button>
                        </div>
                    </div>
                </div>
            </form>
        </div>
    </div>
    <!-- End Contact -->
    
    
    
    </div>
    </div>
    
    
    <footer th:replace="frame/footer :: footer"></footer>
    
    </body>
    
    </html>
    

     

     

     

    카테고리 삭제는 컨트롤러만 보면 될 듯

    //category삭제
     @DeleteMapping("ypjs/category/delete/{categoryId}")
     public @ResponseBody ResponseDto<?> deleteCategory(@PathVariable("categoryId") Long categoryId) {
         categoryService.deleteCategory(categoryId);
         return new ResponseDto<>(HttpStatus.OK.value(), "카테고리가 삭제되었습니다.");
     }
    

     

     

     

     

     

    리뷰 등록

    reviewRepository

    //상품 하나 조회
    public Item findOne(Long ItemId) {
        return em.find(Item.class, ItemId);
    
    }
    
    //상품 하나 조회
    public Item findOne(Long ItemId) {
        return em.find(Item.class, ItemId);
    
    }
    public Member findOne(Long memberId) {
        return em.find(Member.class, memberId);
    }

     

     

    reviewService

    //단건상품 조회
    public Item findOneItem(Long ItemId) {
    
        return itemRepository.findOne(ItemId);
    }

     

    //리뷰등록
    @Transactional
    public ItemReview saveItemReview(ItemReviewDto itemReviewDto, Long memberId) {
        Item item = itemRepository.findOne(itemReviewDto.getItemId());
        Member member = memberRepository.findOne(memberId);
    
    
        ItemReview itemReview = new ItemReview(
                item,
                member,
                itemReviewDto.getItemScore(),
                itemReviewDto.getItemReviewName(),
                itemReviewDto.getItemReviewContent()
        );
    
        //리뷰 저장
        itemReviewRepository.saveReview(itemReview);
    
        // 새로운 리뷰가 추가된 후 아이템의 리뷰 리스트를 업데이트
        item.getItemReviews().add(itemReview);
    
        //평점 업데이트
        item.updateItemRatings();
    
        itemRepository.saveItem(item);
    
    
        return itemReview;
    }

     

     

    reviewController

      //리뷰등록 화면
        @GetMapping("/ypjs/itemReview/post/{itemId}")
        public String insert(@PathVariable("itemId") Long itemId, Model model) {
    
            Item findItem = itemService.findOneItem(itemId);
    
            model.addAttribute("item", findItem);
    
            return "itemreview/itemReviewPost";}
    
    
    
    
    //리뷰등록
     @ResponseBody
     @PostMapping("/ypjs/itemReview/post/{itemId}")
     public ItemReviewDto saveItemReview(@PathVariable("itemId") Long itemId, HttpSession session, Model model,
                                         @RequestBody @Valid ItemReviewDto requestDto) {
    
         //멤버정보 찾기
         LoginDto.ResponseLogin responseLogin = (LoginDto.ResponseLogin) session.getAttribute("member");
    
         System.out.println("@@@@@@@@@@@@@@@@@@@@@@@"+itemId);
         Item findItem = itemService.findOneItem(itemId);
         //ItemReview itemReview = itemReviewService.saveItemReview(requestDto, responseLogin.getMemberId());
         ItemReview itemReview = itemReviewService.saveItemReview(requestDto, 1L);
    
    
         model.addAttribute("item", findItem);
    
    
    
         return new ItemReviewDto(itemReview.getItem().getItemId(),  itemReview.getItemScore(), itemReview.getItemReviewName(), itemReview.getItemReviewContent());
     }

     

     

    itemreview/itemReviewPost

    <!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="post">
                <!-- 폼 요소들 -->
                <div class="row">
                    <input type="hidden" id="itemId" th:value="${item.itemId}" > <!-- Thymeleaf의 value 속성 사용 -->
                    <input type="hidden" id="memberId" value="1"> <!-- memberId 값 받아와야 됨 -->
    
                    <div class="form-group mb-3">
                        <label for="itemReviewName">제목</label>
                        <input type="text" class="form-control mt-1" id="itemReviewName" name="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" placeholder="점수">
                    </div>
                    <div class="mb-3">
                        <label for="itemReviewContent">내용</label>
                        <textarea class="form-control" id="itemReviewContent" name="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-itemReviewPost" 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>

     

    화면은 있는데 링크연결 아직 안해놓음 

     

     

    리뷰 보기

    reviewRepository

    //페치조인 (아이템 당 리뷰 조회)
    public List<ItemReview> findAllItemReview(Long itemId) {
        return em.createQuery(
                        "select ir from ItemReview ir" +
                               " join fetch ir.item i WHERE i.itemId = :itemId", ItemReview.class)
                .setParameter("itemId", itemId)
                .getResultList();
    }
    

     

     

     

    reviewService

    //아이템 당 리뷰조회
    public List<ItemReviewListDto> findAllItemReview(Long itemId) {
        //List<ItemReview> reviews = itemReviewRepository.findAllItemReview(itemId);
        List<ItemReview> reviews = itemReviewRepository.findAllItemReview(itemId);
    
        List<ItemReviewListDto> result = reviews.stream()
                .map(ItemReviewListDto::new)
                .collect(Collectors.toList());
    
        return result;
    }

     

     

    reviewController

    //아이템 당 리뷰조회
    @GetMapping("/ypjs/itemReview/get/{itemId}")
    public String getAllItemReview(@PathVariable("itemId") Long itemId, Model model) {
    
        itemService.findOneItem(itemId);
    
        List<ItemReviewListDto> itemReviews = itemReviewService.findAllItemReview(itemId);
    
    
        model.addAttribute("itemReviews", itemReviews);
    
        return "itemreview/itemReviewGet";
    }

     

     

     

    itemrevirew/itemReviewGet

    <!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>
    
    
    
    
    <!-- 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/category.js"></script>
    <script src="/js/item/item.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="post"  >
                <!-- 폼 요소들 -->
                <div class="row">
    
    
    
    
    
                    <style>
                        .category-box {
                            border: 1px solid #ccc;
                            padding: 10px;
                            margin-bottom: 10px;
                        }
    
                        .category-label {
                            font-weight: bold;
                        }
    
                        .item-box {
        border: 1px solid #ccc;
        padding: 10px;
        margin-bottom: 10px;
    }
    
    .item-info {
        /* Optional: Add additional styles for item information */
    }
    
    .category-label {
        font-weight: bold;
    }
    
    
                    </style>
    
    
    
    
    
    
                    <div th:if="${not #lists.isEmpty(itemReviews)}">
                        <br><br><br>
                        <h3>리뷰 목록</h3>
                        <br>
                        <div th:each="itemReview : ${itemReviews}" class="item-box">
                            <div class="item-info">
                                <div>
                                    <span class="category-label">아이템 이름:</span>
                                    &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                                    <span th:text="${itemReview.itemReviewName}"></span>
                                </div>
                                <div>
                                    <span class="category-label">별점:</span>
                                    &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                                    <span th:text="${itemReview.itemScore}"></span>
                                </div>
                                <div>
                                    <span class="category-label">아이템 내용:</span>
                                    &nbsp;&nbsp;&nbsp;&nbsp; <span>:</span>&nbsp;&nbsp;&nbsp;&nbsp;
                                    <span th:utext="${itemReview.itemReviewContent}"></span>
                                </div>
    
    
                                <!-- 수정 및 삭제 버튼 -->
    <!--                            <div class="container">-->
    <!--                                <div class="row justify-content-end">-->
    <!--                                    <div class="col-auto">-->
    
    <!--                                        <a th:href="@{/ypjs/itemReview/update/{itemId}(itemId=${item.itemId})}" class="btn btn-warning">수정하기</a>-->
    
    <!--                                    </div>-->
    <!--                                    <div class="col-auto">-->
    <!--                                        <button type="button"-->
    <!--                                                class="btn btn-danger btn-sm btn-delete-item"-->
    <!--                                                th:attr="data-itemReviewId=${itemReview.itemReview}"-->
    <!--                                                style="padding: 2px 10px; font-size: 16px; width: 90px; height: 40px;">-->
    <!--                                            삭제하기-->
    <!--                                        </button>-->
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </form>
        </div>
    </div>
    
    
                    <!-- End Contact -->
    
    
                </div>
            </form>
        </div>
    </div>
    
    
    <footer th:replace="frame/footer :: footer"></footer>
    
    </body>
    
    </html>
    

     

     

    수정, 삭제 버튼도 안먹고 리뷰보기는 아직 미완성

     

     

     

    베트남 여행 일정으로 나머지는 여행갔다와서 할 예정

Designed by Tistory.