Skip to content

Commit

Permalink
ShoppingCart-dev-007-search-feature (#162)
Browse files Browse the repository at this point in the history
* update npm pkg

* be add search controller, fe call be search api

* add search logic in repo, service, controller

* fix jpa repo custom sql, log filter product

* be fix controller result, fe print result

* add Search Results at home.vue

* fe fix NavigationDuplicated at search bar, add searchResults at app, update Navbar

* update props in home.vue

* fix ProductBox show null if no desc, make search product work

* be remove log, Autowired, fe format code, remove print

* fe update search placeholder, be add repo unit test, h2 dep
  • Loading branch information
yennanliu authored Jul 23, 2024
1 parent f8cd5c4 commit cfdac5b
Show file tree
Hide file tree
Showing 11 changed files with 454 additions and 216 deletions.
7 changes: 7 additions & 0 deletions ShoppingCart/Backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@
<artifactId>lombok</artifactId>
</dependency>

<!-- for repository unit test -->
<!-- <dependency>-->
<!-- <groupId>com.h2database</groupId>-->
<!-- <artifactId>h2</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->

</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.yen.ShoppingCart.controller;

import com.yen.ShoppingCart.model.Product;
import com.yen.ShoppingCart.model.dto.product.ProductDto;
import com.yen.ShoppingCart.service.CategoryService;
import com.yen.ShoppingCart.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/search")
public class SearchController {

@Autowired
ProductService productService;

@GetMapping("/api")
public ResponseEntity<List<ProductDto>> searchProducts(@RequestParam("query") String query) {
List<Product> products = productService.searchProducts(query);
return new ResponseEntity<List<ProductDto>>(getProductDtoFromProduct(products), HttpStatus.OK);
}

private List<ProductDto> getProductDtoFromProduct(List<Product> products){
List<ProductDto> body = new ArrayList<>();
for (Product product : products){
ProductDto dto = new ProductDto();
dto.setId(product.getId());
dto.setName(product.getName());
dto.setImageURL(product.getImageURL());
dto.setPrice(product.getPrice());
dto.setCategoryId(product.getCategory().getId());
body.add(dto);
}
return body;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@

import com.yen.ShoppingCart.model.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface ProductRepository extends JpaRepository<Product, Integer> {

List<Product> findByNameContainingIgnoreCase(@Param("name") String name);

// custom SQL with JpaRepository
// https://github.com/yennanliu/til?tab=readme-ov-file#20240215
@Query(value= "SELECT * FROM products p WHERE LOWER(p.name) LIKE LOWER(CONCAT('%', :name, '%'))", nativeQuery = true)
List<Product> searchProductsByName(@Param("name") String name);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class ProductService {

@Autowired
Expand Down Expand Up @@ -68,5 +71,11 @@ public Product getProductById(Integer productId) throws ProductNotExistException
return optionalProduct.get();
}

public List<Product> searchProducts(String query) {

log.info(">>> (searchProducts) query = {}", query);
List<Product> products = productRepository.searchProductsByName(query);
return productRepository.searchProductsByName(query);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//package com.yen.ShoppingCart.repository;
//
//import com.yen.ShoppingCart.model.Product;
//import org.junit.jupiter.api.BeforeEach;
//import org.junit.jupiter.api.Test;
//import org.junit.jupiter.api.extension.ExtendWith;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
//import org.springframework.test.context.junit.jupiter.SpringExtension;
//
//import java.util.List;
//
//import static org.assertj.core.api.Assertions.assertThat;
//
//@ExtendWith(SpringExtension.class)
//@DataJpaTest
//public class ProductRepositoryTest {
//
// @Autowired
// private ProductRepository productRepository;
//
// @BeforeEach
// public void setUp() {
// Product product1 = new Product();
// product1.setName("Apple iPhone");
// product1.setDescription("Latest model of iPhone");
// product1.setPrice(999.99);
//
// Product product2 = new Product();
// product2.setName("Samsung Galaxy");
// product2.setDescription("Latest model of Samsung Galaxy");
// product2.setPrice(899.99);
//
// Product product3 = new Product();
// product3.setName("Google Pixel");
// product3.setDescription("Latest model of Google Pixel");
// product3.setPrice(799.99);
//
// productRepository.save(product1);
// productRepository.save(product2);
// productRepository.save(product3);
// }
//
// @Test
// public void testSearchProductsByName() {
// List<Product> results = productRepository.searchProductsByName("iphone");
// assertThat(results).hasSize(1);
// assertThat(results.get(0).getName()).isEqualTo("Apple iPhone");
//
// results = productRepository.searchProductsByName("galaxy");
// assertThat(results).hasSize(1);
// assertThat(results.get(0).getName()).isEqualTo("Samsung Galaxy");
//
// results = productRepository.searchProductsByName("google");
// assertThat(results).hasSize(1);
// assertThat(results.get(0).getName()).isEqualTo("Google Pixel");
// }
//
// @Test
// public void testSearchProductsByNameIgnoreCase() {
// List<Product> results = productRepository.searchProductsByName("IPHONE");
// assertThat(results).hasSize(1);
// assertThat(results.get(0).getName()).isEqualTo("Apple iPhone");
//
// results = productRepository.searchProductsByName("GALAXY");
// assertThat(results).hasSize(1);
// assertThat(results.get(0).getName()).isEqualTo("Samsung Galaxy");
//
// results = productRepository.searchProductsByName("GOOGLE");
// assertThat(results).hasSize(1);
// assertThat(results.get(0).getName()).isEqualTo("Google Pixel");
// }
//
// @Test
// public void testSearchProductsByPartialName() {
// List<Product> results = productRepository.searchProductsByName("gal");
// assertThat(results).hasSize(1);
// assertThat(results.get(0).getName()).isEqualTo("Samsung Galaxy");
// }
//
// @Test
// public void testSearchProductsByNameNotFound() {
// List<Product> results = productRepository.searchProductsByName("nokia");
// assertThat(results).isEmpty();
// }
//}
Loading

0 comments on commit cfdac5b

Please sign in to comment.