From cfdac5bfb17f2ecd773905f04ec2770e9c7b2a75 Mon Sep 17 00:00:00 2001 From: yennj12 Date: Tue, 23 Jul 2024 17:23:18 +0800 Subject: [PATCH] ShoppingCart-dev-007-search-feature (#162) * 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 --- ShoppingCart/Backend/pom.xml | 7 + .../controller/SearchController.java | 44 ++++ .../repository/ProductRepository.java | 10 + .../ShoppingCart/service/ProductService.java | 9 + .../repository/ProductRepositoryTest.java | 86 ++++++++ .../Frondend/ecommerce-ui/package-lock.json | 107 +++++----- .../Frondend/ecommerce-ui/package.json | 4 +- .../Frondend/ecommerce-ui/src/App.vue | 12 +- .../ecommerce-ui/src/components/Navbar.vue | 60 ++++-- .../src/components/Product/ProductBox.vue | 130 +++++------ .../Frondend/ecommerce-ui/src/views/Home.vue | 201 ++++++++++-------- 11 files changed, 454 insertions(+), 216 deletions(-) create mode 100644 ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/controller/SearchController.java create mode 100644 ShoppingCart/Backend/src/test/java/com/yen/ShoppingCart/repository/ProductRepositoryTest.java diff --git a/ShoppingCart/Backend/pom.xml b/ShoppingCart/Backend/pom.xml index b9da52083..aee788865 100644 --- a/ShoppingCart/Backend/pom.xml +++ b/ShoppingCart/Backend/pom.xml @@ -104,6 +104,13 @@ lombok + + + + + + + diff --git a/ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/controller/SearchController.java b/ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/controller/SearchController.java new file mode 100644 index 000000000..7d570e227 --- /dev/null +++ b/ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/controller/SearchController.java @@ -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> searchProducts(@RequestParam("query") String query) { + List products = productService.searchProducts(query); + return new ResponseEntity>(getProductDtoFromProduct(products), HttpStatus.OK); + } + + private List getProductDtoFromProduct(List products){ + List 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; + } + +} diff --git a/ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/repository/ProductRepository.java b/ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/repository/ProductRepository.java index d12a374d5..adb9df082 100644 --- a/ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/repository/ProductRepository.java +++ b/ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/repository/ProductRepository.java @@ -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 { + List 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 searchProductsByName(@Param("name") String name); } \ No newline at end of file diff --git a/ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/service/ProductService.java b/ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/service/ProductService.java index 41874c4f5..07d2054cb 100644 --- a/ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/service/ProductService.java +++ b/ShoppingCart/Backend/src/main/java/com/yen/ShoppingCart/service/ProductService.java @@ -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 @@ -68,5 +71,11 @@ public Product getProductById(Integer productId) throws ProductNotExistException return optionalProduct.get(); } + public List searchProducts(String query) { + + log.info(">>> (searchProducts) query = {}", query); + List products = productRepository.searchProductsByName(query); + return productRepository.searchProductsByName(query); + } } diff --git a/ShoppingCart/Backend/src/test/java/com/yen/ShoppingCart/repository/ProductRepositoryTest.java b/ShoppingCart/Backend/src/test/java/com/yen/ShoppingCart/repository/ProductRepositoryTest.java new file mode 100644 index 000000000..d3e4c0a26 --- /dev/null +++ b/ShoppingCart/Backend/src/test/java/com/yen/ShoppingCart/repository/ProductRepositoryTest.java @@ -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 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 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 results = productRepository.searchProductsByName("gal"); +// assertThat(results).hasSize(1); +// assertThat(results.get(0).getName()).isEqualTo("Samsung Galaxy"); +// } +// +// @Test +// public void testSearchProductsByNameNotFound() { +// List results = productRepository.searchProductsByName("nokia"); +// assertThat(results).isEmpty(); +// } +//} \ No newline at end of file diff --git a/ShoppingCart/Frondend/ecommerce-ui/package-lock.json b/ShoppingCart/Frondend/ecommerce-ui/package-lock.json index 8cd9b11aa..d908497f7 100644 --- a/ShoppingCart/Frondend/ecommerce-ui/package-lock.json +++ b/ShoppingCart/Frondend/ecommerce-ui/package-lock.json @@ -8,8 +8,8 @@ "name": "ecommerce-ui", "version": "0.1.0", "dependencies": { - "@stripe/stripe-js": "^2.2.0", - "axios": "^1.6.2", + "@stripe/stripe-js": "^2.4.0", + "axios": "^1.7.2", "core-js": "^3.8.3", "sweetalert": "^2.1.2", "vue": "^2.6.14", @@ -2159,9 +2159,9 @@ "dev": true }, "node_modules/@stripe/stripe-js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.2.0.tgz", - "integrity": "sha512-YyXQbsXvnNRJ6MofFhCLIQ4W7UpfkfSOQhjIaHEiCMBv3IBxhzugXiYNNzceGTK/7DL31v7HtTnkJ+FI+6AIow==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.4.0.tgz", + "integrity": "sha512-WFkQx1mbs2b5+7looI9IV1BLa3bIApuN3ehp9FP58xGg7KL9hCHDECgW3BwO9l9L+xBPVAD7Yjn1EhGe6EDTeA==" }, "node_modules/@trysound/sax": { "version": "0.2.0", @@ -2303,6 +2303,7 @@ "version": "20.10.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", + "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -3518,11 +3519,11 @@ } }, "node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -3838,6 +3839,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dev": true, "dependencies": { "function-bind": "^1.1.2", "get-intrinsic": "^1.2.1", @@ -4958,6 +4960,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, "dependencies": { "get-intrinsic": "^1.2.1", "gopd": "^1.0.1", @@ -6243,9 +6246,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -6350,6 +6353,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6382,6 +6386,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dev": true, "dependencies": { "function-bind": "^1.1.2", "has-proto": "^1.0.1", @@ -6475,6 +6480,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -6522,6 +6528,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, "dependencies": { "get-intrinsic": "^1.2.2" }, @@ -6533,6 +6540,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -6544,6 +6552,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -6561,6 +6570,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -8129,6 +8139,7 @@ "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9278,6 +9289,7 @@ "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, "dependencies": { "side-channel": "^1.0.4" }, @@ -9865,6 +9877,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, "dependencies": { "define-data-property": "^1.1.1", "get-intrinsic": "^1.2.1", @@ -9927,6 +9940,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -10228,18 +10242,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stripe": { - "version": "14.7.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-14.7.0.tgz", - "integrity": "sha512-A6XWH76K0K7IgEBz4odIVxjhkdPduSPafZju6ltAFU0oMbWJlfeaDyMTfRJ9vcYA9zqENfwRizExD/2nZ4rQ1A==", - "dependencies": { - "@types/node": ">=8.1.0", - "qs": "^6.11.0" - }, - "engines": { - "node": ">=12.*" - } - }, "node_modules/stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", @@ -10624,7 +10626,8 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -13204,9 +13207,9 @@ "dev": true }, "@stripe/stripe-js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.2.0.tgz", - "integrity": "sha512-YyXQbsXvnNRJ6MofFhCLIQ4W7UpfkfSOQhjIaHEiCMBv3IBxhzugXiYNNzceGTK/7DL31v7HtTnkJ+FI+6AIow==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.4.0.tgz", + "integrity": "sha512-WFkQx1mbs2b5+7looI9IV1BLa3bIApuN3ehp9FP58xGg7KL9hCHDECgW3BwO9l9L+xBPVAD7Yjn1EhGe6EDTeA==" }, "@trysound/sax": { "version": "0.2.0", @@ -13345,6 +13348,7 @@ "version": "20.10.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.0.tgz", "integrity": "sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==", + "dev": true, "requires": { "undici-types": "~5.26.4" } @@ -14302,11 +14306,11 @@ } }, "axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", "requires": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -14540,6 +14544,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dev": true, "requires": { "function-bind": "^1.1.2", "get-intrinsic": "^1.2.1", @@ -15354,6 +15359,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, "requires": { "get-intrinsic": "^1.2.1", "gopd": "^1.0.1", @@ -16338,9 +16344,9 @@ "dev": true }, "follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==" + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" }, "form-data": { "version": "4.0.0", @@ -16404,7 +16410,8 @@ "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true }, "functional-red-black-tree": { "version": "1.0.1", @@ -16428,6 +16435,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dev": true, "requires": { "function-bind": "^1.1.2", "has-proto": "^1.0.1", @@ -16497,6 +16505,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, "requires": { "get-intrinsic": "^1.1.3" } @@ -16532,6 +16541,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, "requires": { "get-intrinsic": "^1.2.2" } @@ -16539,12 +16549,14 @@ "has-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true }, "hash-sum": { "version": "2.0.0", @@ -16556,6 +16568,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, "requires": { "function-bind": "^1.1.2" } @@ -17733,7 +17746,8 @@ "object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==" + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true }, "object-keys": { "version": "1.1.1", @@ -18529,6 +18543,7 @@ "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, "requires": { "side-channel": "^1.0.4" } @@ -18970,6 +18985,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, "requires": { "define-data-property": "^1.1.1", "get-intrinsic": "^1.2.1", @@ -19017,6 +19033,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, "requires": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -19259,15 +19276,6 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, - "stripe": { - "version": "14.7.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-14.7.0.tgz", - "integrity": "sha512-A6XWH76K0K7IgEBz4odIVxjhkdPduSPafZju6ltAFU0oMbWJlfeaDyMTfRJ9vcYA9zqENfwRizExD/2nZ4rQ1A==", - "requires": { - "@types/node": ">=8.1.0", - "qs": "^6.11.0" - } - }, "stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", @@ -19550,7 +19558,8 @@ "undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", diff --git a/ShoppingCart/Frondend/ecommerce-ui/package.json b/ShoppingCart/Frondend/ecommerce-ui/package.json index 0ed117baf..8a651c944 100644 --- a/ShoppingCart/Frondend/ecommerce-ui/package.json +++ b/ShoppingCart/Frondend/ecommerce-ui/package.json @@ -8,8 +8,8 @@ "lint": "vue-cli-service lint" }, "dependencies": { - "@stripe/stripe-js": "^2.2.0", - "axios": "^1.6.2", + "@stripe/stripe-js": "^2.4.0", + "axios": "^1.7.2", "core-js": "^3.8.3", "sweetalert": "^2.1.2", "vue": "^2.6.14", diff --git a/ShoppingCart/Frondend/ecommerce-ui/src/App.vue b/ShoppingCart/Frondend/ecommerce-ui/src/App.vue index 24a67aebe..89e05d5ac 100644 --- a/ShoppingCart/Frondend/ecommerce-ui/src/App.vue +++ b/ShoppingCart/Frondend/ecommerce-ui/src/App.vue @@ -3,10 +3,11 @@
- + - +
- + @@ -146,15 +150,16 @@ + }, +}; + \ No newline at end of file +.embed-responsive .card-img-top { + object-fit: cover; +} + +a { + text-decoration: none; +} + +.card-title { + color: #484848; + font-size: 1.1rem; + font-weight: 400; +} + +.card-title:hover { + font-weight: bold; +} + +.card-text { + font-size: 0.9rem; +} + +#edit-product { + float: right; +} + \ No newline at end of file diff --git a/ShoppingCart/Frondend/ecommerce-ui/src/views/Home.vue b/ShoppingCart/Frondend/ecommerce-ui/src/views/Home.vue index c6113c136..1c38ee4ac 100644 --- a/ShoppingCart/Frondend/ecommerce-ui/src/views/Home.vue +++ b/ShoppingCart/Frondend/ecommerce-ui/src/views/Home.vue @@ -1,100 +1,131 @@ + + + +import ProductBox from "../components/Product/ProductBox"; +import CategoryBox from "../components/Category/CategoryBox"; +export default { + name: "Home", + components: { ProductBox, CategoryBox }, + props: ["baseURL", "products", "categories", "searchResults"], + data() { + return { + category_size: 0, + product_size: 0, + }; + }, + mounted() { + // this.category_size = this.categories.length; + // this.category_size = Math.min(6, this.category_size); + // this.product_size = this.products.length; + // this.product_size = Math.min(8, this.product_size); + }, +}; + \ No newline at end of file +.page-holder { + min-height: 100vh; +} + +.bg-cover { + background-size: cover !important; +} + +#background-div { + background: url(../assets/home3.png); +} + +#heading { + text-decoration: none; + font-family: "Roboto", sans-serif; + font-weight: 400; + opacity: 0.8; + font-family: "Josefin Sans", sans-serif; +} + +#content { + opacity: 0.8; +} + +h2 { + font-family: "Josefin Sans", sans-serif; +} + \ No newline at end of file