├── client ├── .gitignore ├── .dockerignore ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── icon72.ico │ ├── icon96.ico │ ├── logo256.png │ ├── logo512.png │ ├── manifest.json │ └── index.html ├── src │ ├── history.js │ ├── constants │ │ ├── http_error_codes.js │ │ ├── react_routes.js │ │ ├── cookies.js │ │ ├── api_routes.js │ │ ├── stateCodes.js │ │ └── constants.js │ ├── images │ │ ├── badRequest400.png │ │ ├── pageNotFound404.png │ │ ├── emptyCheckoutCart.png │ │ ├── internalServer500.png │ │ └── searchMatchesNotFound404.png │ ├── components │ │ ├── ui │ │ │ ├── headers.js │ │ │ ├── error │ │ │ │ ├── badRequest.js │ │ │ │ ├── internalServerError.js │ │ │ │ ├── GenericErrorMsg.js │ │ │ │ ├── renderErrorImage.js │ │ │ │ ├── httpError.js │ │ │ │ ├── emptyShoppingBag.js │ │ │ │ ├── pageNotFound.js │ │ │ │ └── searchMatchesNotFound.js │ │ │ ├── documentTitle.js │ │ │ ├── BackgroundDisabledSpinner.js │ │ │ ├── spinner.js │ │ │ ├── breadcrumbs.js │ │ │ ├── reduxTextField.js │ │ │ ├── modal.js │ │ │ ├── modalConfirmation.js │ │ │ ├── radioButtonGroup.js │ │ │ └── alertModal.js │ │ ├── routes │ │ │ ├── checkout │ │ │ │ ├── stripeInput.js │ │ │ │ ├── summaryCard.js │ │ │ │ └── continueButton.js │ │ │ ├── navbar │ │ │ │ ├── bagButton.js │ │ │ │ ├── sideBar.js │ │ │ │ └── mobileMenu.js │ │ │ ├── signin │ │ │ │ └── GoogleAuthButton.js │ │ │ ├── cancelPayment.js │ │ │ ├── home │ │ │ │ ├── homeMenuIcons.js │ │ │ │ └── verticalSlider.js │ │ │ ├── product │ │ │ │ ├── filterSideNavbar │ │ │ │ │ ├── checkboxSearchBar.js │ │ │ │ │ ├── clearAllButton.js │ │ │ │ │ └── priceCheckBox.js │ │ │ │ ├── filterDropdown.js │ │ │ │ └── filterPagination.js │ │ │ ├── signup │ │ │ │ └── signUp.js │ │ │ └── priceDetails.js │ │ └── app.js │ ├── styles │ │ ├── materialUI │ │ │ ├── webFormStyles.js │ │ │ ├── checkoutFormStyles.js │ │ │ ├── tabStyles.js │ │ │ └── filterNavBarStyles.js │ │ ├── index.css │ │ └── semanticUI │ │ │ ├── commonStyles.css │ │ │ └── customStyles.js │ ├── setupTests.js │ ├── __tests__ │ │ └── App.test.js │ ├── logger │ │ ├── loggerTypes.js │ │ ├── LoggerConfig.js │ │ └── Logger.js │ ├── reducers │ │ ├── events │ │ │ └── eventReducer.js │ │ └── index.js │ ├── helper │ │ ├── toggleId.js │ │ └── updateQueryString.js │ ├── hooks │ │ ├── useCartTotal.js │ │ ├── useClickAway.js │ │ └── useAddProductsToShoppingBag.js │ ├── api │ │ └── service_api.js │ ├── ErrorBoundary.js │ └── index.js ├── Dockerfile ├── server.js ├── .env-sample └── package.json ├── mysql-db └── user.sql ├── server ├── payment-service │ ├── heroku.yml │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ ├── application.properties │ │ │ │ └── logback-spring.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── ujjaval │ │ │ │ └── ecommerce │ │ │ │ └── paymentservice │ │ │ │ ├── dto │ │ │ │ ├── CardToken.java │ │ │ │ └── PaymentStatus.java │ │ │ │ ├── PaymentServiceApplication.java │ │ │ │ ├── config │ │ │ │ └── CORSFilter.java │ │ │ │ └── controller │ │ │ │ └── PaymentController.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── ujjaval │ │ │ └── ecommerce │ │ │ └── paymentservice │ │ │ └── PaymentServiceApplicationTests.java │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── .gitignore │ ├── Dockerfile-prod │ ├── Dockerfile-dev │ └── pom.xml ├── search-suggestion-service │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ ├── application-prod.properties │ │ │ │ ├── application-dev.properties │ │ │ │ ├── application.properties │ │ │ │ └── logback-spring.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── ujjaval │ │ │ │ └── ecommerce │ │ │ │ └── searchsuggestionservice │ │ │ │ ├── service │ │ │ │ └── SearchSuggestionService.java │ │ │ │ ├── dto │ │ │ │ └── SearchSuggestionKeywordInfo.java │ │ │ │ ├── config │ │ │ │ └── CorsConfig.java │ │ │ │ ├── SearchSuggestionServiceApplication.java │ │ │ │ ├── util │ │ │ │ └── Permutation.java │ │ │ │ └── controller │ │ │ │ └── SearchSuggestionController.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── ujjaval │ │ │ └── ecommerce │ │ │ └── searchsuggestionservice │ │ │ └── SearchSuggestionServiceApplicationTests.java │ ├── heroku.yml │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── .gitignore │ ├── Dockerfile-prod │ └── Dockerfile-dev ├── common-data-service │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ ├── application-prod.properties │ │ │ │ ├── fake_data │ │ │ │ │ ├── sortby-data.txt │ │ │ │ │ ├── price-range-data.txt │ │ │ │ │ └── .DS_Store │ │ │ │ ├── application-dev.properties │ │ │ │ ├── application.properties │ │ │ │ └── logback-spring.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── ujjaval │ │ │ │ └── ecommerce │ │ │ │ └── commondataservice │ │ │ │ ├── service │ │ │ │ └── interfaces │ │ │ │ │ ├── LoadFakeDataService.java │ │ │ │ │ └── CommonDataService.java │ │ │ │ ├── dao │ │ │ │ └── sql │ │ │ │ │ ├── info │ │ │ │ │ ├── BankInfoRepository.java │ │ │ │ │ ├── OrderInfoRepository.java │ │ │ │ │ ├── AddressInfoRepository.java │ │ │ │ │ ├── ContactInfoRepository.java │ │ │ │ │ ├── queryhelpers │ │ │ │ │ │ └── context │ │ │ │ │ │ │ └── ParamsToQueryContext.java │ │ │ │ │ └── ProductInfoRepository.java │ │ │ │ │ ├── images │ │ │ │ │ ├── BrandImagesRepository.java │ │ │ │ │ ├── ApparelImagesRepository.java │ │ │ │ │ └── CarouselImagesRepository.java │ │ │ │ │ └── categories │ │ │ │ │ ├── GenderCategoryRepository.java │ │ │ │ │ ├── SortByCategoryRepository.java │ │ │ │ │ ├── PriceRangeCategoryRepository.java │ │ │ │ │ ├── ProductBrandCategoryRepository.java │ │ │ │ │ └── ApparelCategoryRepository.java │ │ │ │ ├── dto │ │ │ │ ├── BrandsAndApparelsDTO.java │ │ │ │ ├── FilterAttributesDTO.java │ │ │ │ ├── ProductInfoDTO.java │ │ │ │ ├── SearchSuggestionForTwoAttrDTO.java │ │ │ │ ├── SearchSuggestionForThreeAttrDTO.java │ │ │ │ ├── BrandImagesDTO.java │ │ │ │ ├── FilterAttributesWithTotalItemsDTO.java │ │ │ │ └── ApparelImagesDTO.java │ │ │ │ ├── utils │ │ │ │ └── resulttransformers │ │ │ │ │ └── IListResultTransformer.java │ │ │ │ ├── config │ │ │ │ ├── AppConfig.java │ │ │ │ ├── CorsConfig.java │ │ │ │ ├── DevRedisConfig.java │ │ │ │ └── ProdRedisConfig.java │ │ │ │ ├── model │ │ │ │ ├── HomeTabsDataResponse.java │ │ │ │ ├── MainScreenResponse.java │ │ │ │ ├── SearchSuggestionResponse.java │ │ │ │ └── FilterAttributesResponse.java │ │ │ │ ├── entity │ │ │ │ └── sql │ │ │ │ │ ├── categories │ │ │ │ │ ├── SortByCategory.java │ │ │ │ │ ├── PriceRangeCategory.java │ │ │ │ │ ├── GenderCategory.java │ │ │ │ │ ├── ApparelCategory.java │ │ │ │ │ └── ProductBrandCategory.java │ │ │ │ │ ├── images │ │ │ │ │ ├── CarouselImages.java │ │ │ │ │ ├── BrandImages.java │ │ │ │ │ └── ApparelImages.java │ │ │ │ │ └── info │ │ │ │ │ ├── ContactInfo.java │ │ │ │ │ ├── AddressInfo.java │ │ │ │ │ ├── OrderInfo.java │ │ │ │ │ └── BankInfo.java │ │ │ │ └── CommonDataServiceApplication.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── ujjaval │ │ │ └── ecommerce │ │ │ └── commondataservice │ │ │ └── CommonDataServiceApplicationTests.java │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── heroku.yml │ ├── .gitignore │ ├── Dockerfile-prod │ └── Dockerfile-dev ├── authentication-service │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ ├── application-prod.properties │ │ │ │ ├── application-dev.properties │ │ │ │ ├── application.properties │ │ │ │ └── logback-spring.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── ujjaval │ │ │ │ └── ecommerce │ │ │ │ └── authenticationservice │ │ │ │ ├── model │ │ │ │ ├── AuthenticationRequest.java │ │ │ │ ├── AccountCreationResponse.java │ │ │ │ ├── AuthenticationResponse.java │ │ │ │ └── AccountCreationRequest.java │ │ │ │ ├── AuthenticationServiceApplication.java │ │ │ │ ├── service │ │ │ │ ├── AuthDataService.java │ │ │ │ ├── CustomUserDetailsService.java │ │ │ │ └── AuthDataServiceImpl.java │ │ │ │ ├── config │ │ │ │ ├── CorsConfigurer.java │ │ │ │ └── SecurityConfigurer.java │ │ │ │ ├── entity │ │ │ │ └── UserInfo.java │ │ │ │ ├── util │ │ │ │ ├── Md5Util.java │ │ │ │ └── JwtUtil.java │ │ │ │ ├── dao │ │ │ │ └── UserInfoRepository.java │ │ │ │ └── filter │ │ │ │ └── JwtRequestFilter.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── ujjaval │ │ │ └── ecommerce │ │ │ └── authenticationservice │ │ │ └── AuthenticationServiceApplicationTests.java │ ├── heroku.yml │ ├── .mvn │ │ └── wrapper │ │ │ ├── maven-wrapper.jar │ │ │ └── maven-wrapper.properties │ ├── .gitignore │ ├── Dockerfile-prod │ └── Dockerfile-dev └── seller-account-service │ ├── src │ ├── main │ │ ├── .DS_Store │ │ ├── java │ │ │ ├── .DS_Store │ │ │ └── com │ │ │ │ ├── .DS_Store │ │ │ │ └── ujjaval │ │ │ │ ├── .DS_Store │ │ │ │ └── ecommerce │ │ │ │ ├── .DS_Store │ │ │ │ └── selleraccountservice │ │ │ │ ├── .DS_Store │ │ │ │ ├── entity │ │ │ │ ├── .DS_Store │ │ │ │ ├── nosql │ │ │ │ │ ├── SellerReview.java │ │ │ │ │ ├── SellerAccountNotification.java │ │ │ │ │ ├── SellerMessage.java │ │ │ │ │ ├── SellerMessageDetails.java │ │ │ │ │ └── SellerBulkInfo.java │ │ │ │ └── sql │ │ │ │ │ └── SellerInfo.java │ │ │ │ ├── dao │ │ │ │ ├── sql │ │ │ │ │ └── SellerInfoRepository.java │ │ │ │ └── nosql │ │ │ │ │ └── SellerBulkInfoRepository.java │ │ │ │ ├── SellerAccountServiceApplication.java │ │ │ │ ├── model │ │ │ │ └── UserInfo.java │ │ │ │ ├── service │ │ │ │ └── SellerAccountDataService.java │ │ │ │ └── controller │ │ │ │ └── SellerAccountController.java │ │ └── resources │ │ │ └── application.properties │ └── test │ │ └── java │ │ └── com │ │ └── ujjaval │ │ └── ecommerce │ │ └── selleraccountservice │ │ └── SellerAccountServiceApplicationTests.java │ ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties │ └── .gitignore ├── stop-all.sh ├── wait-for-mysql.sh ├── start-all.sh ├── .gitignore └── .env-sample /client/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .env 3 | .DS_Store 4 | 5 | -------------------------------------------------------------------------------- /client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .env 4 | -------------------------------------------------------------------------------- /mysql-db/user.sql: -------------------------------------------------------------------------------- 1 | GRANT ALL PRIVILEGES ON *.* TO 'mysqluser'@'%'; 2 | -------------------------------------------------------------------------------- /server/payment-service/heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | web: Dockerfile-prod -------------------------------------------------------------------------------- /server/search-suggestion-service/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/search-suggestion-service/heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | web: Dockerfile-prod -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/icon72.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/client/public/icon72.ico -------------------------------------------------------------------------------- /client/public/icon96.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/client/public/icon96.ico -------------------------------------------------------------------------------- /client/public/logo256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/client/public/logo256.png -------------------------------------------------------------------------------- /client/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/client/public/logo512.png -------------------------------------------------------------------------------- /client/src/history.js: -------------------------------------------------------------------------------- 1 | import {createBrowserHistory} from 'history'; 2 | 3 | export default createBrowserHistory(); 4 | -------------------------------------------------------------------------------- /server/search-suggestion-service/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | #spring.data.redis.repositories.enabled=false -------------------------------------------------------------------------------- /server/payment-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=payment-service 2 | server.port=${PORT} -------------------------------------------------------------------------------- /client/src/constants/http_error_codes.js: -------------------------------------------------------------------------------- 1 | export const INTERNAL_SERVER_ERROR_CODE = 500; 2 | export const BAD_REQUEST_ERROR_CODE = 400; -------------------------------------------------------------------------------- /server/common-data-service/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect -------------------------------------------------------------------------------- /client/src/images/badRequest400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/client/src/images/badRequest400.png -------------------------------------------------------------------------------- /server/authentication-service/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect -------------------------------------------------------------------------------- /client/src/images/pageNotFound404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/client/src/images/pageNotFound404.png -------------------------------------------------------------------------------- /client/src/images/emptyCheckoutCart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/client/src/images/emptyCheckoutCart.png -------------------------------------------------------------------------------- /client/src/images/internalServer500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/client/src/images/internalServer500.png -------------------------------------------------------------------------------- /server/common-data-service/src/main/resources/fake_data/sortby-data.txt: -------------------------------------------------------------------------------- 1 | 1|What's New 2 | 2|Popularity 3 | 3|Price: Low To High 4 | 4|Price: High To Low -------------------------------------------------------------------------------- /server/authentication-service/heroku.yml: -------------------------------------------------------------------------------- 1 | setup: 2 | addons: 3 | - plan: cleardb 4 | as: DATABASE 5 | build: 6 | docker: 7 | web: Dockerfile-prod -------------------------------------------------------------------------------- /client/src/images/searchMatchesNotFound404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/client/src/images/searchMatchesNotFound404.png -------------------------------------------------------------------------------- /server/common-data-service/src/main/resources/fake_data/price-range-data.txt: -------------------------------------------------------------------------------- 1 | 1|Under $50 2 | 2|$50-$100 3 | 3|$100-$200 4 | 4|$200-$300 5 | 5|$300-$400 6 | 6|Above $400 -------------------------------------------------------------------------------- /server/seller-account-service/src/main/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/seller-account-service/src/main/.DS_Store -------------------------------------------------------------------------------- /server/payment-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/payment-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/seller-account-service/src/main/java/.DS_Store -------------------------------------------------------------------------------- /stop-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Stop and delete the containers 4 | docker-compose down 5 | 6 | # Deleting network 7 | docker network rm spring-cloud-microservices 8 | -------------------------------------------------------------------------------- /server/common-data-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/common-data-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/seller-account-service/src/main/java/com/.DS_Store -------------------------------------------------------------------------------- /server/authentication-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/authentication-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /server/seller-account-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/seller-account-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /server/search-suggestion-service/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/search-suggestion-service/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /server/common-data-service/src/main/resources/fake_data/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/common-data-service/src/main/resources/fake_data/.DS_Store -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/seller-account-service/src/main/java/com/ujjaval/.DS_Store -------------------------------------------------------------------------------- /client/src/constants/react_routes.js: -------------------------------------------------------------------------------- 1 | export const HOME_ROUTE = '/' 2 | export const PRODUCTS_ROUTE = '/products' 3 | export const CHECKOUT_ROUTE = '/checkout' 4 | export const DETAILS_ROUTE = '/products/details' -------------------------------------------------------------------------------- /server/common-data-service/heroku.yml: -------------------------------------------------------------------------------- 1 | setup: 2 | addons: 3 | - plan: cleardb 4 | as: DATABASE 5 | - plan: heroku-redis 6 | as: DATABASE 7 | build: 8 | docker: 9 | web: Dockerfile-prod -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/seller-account-service/src/main/java/com/ujjaval/ecommerce/.DS_Store -------------------------------------------------------------------------------- /client/src/constants/cookies.js: -------------------------------------------------------------------------------- 1 | export const AUTH_DETAILS_COOKIE = "AUTH_DETAILS_COOKIE"; 2 | export const SHOPPERS_PRODUCT_INFO_COOKIE = 'SHOPPERS_PRODUCT_INFO_COOKIE'; 3 | export const CART_TOTAL_COOKIE = "CART_TOTAL_COOKIE"; -------------------------------------------------------------------------------- /server/search-suggestion-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=search-suggestion-service 2 | server.port=${PORT} 3 | spring.profiles.active=${ACTIVE_PROFILE} 4 | #spring.cache.redis.time-to-live=10 -------------------------------------------------------------------------------- /client/src/components/ui/headers.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NavBarHeader = (props) => { 4 | return ( 5 |

{props.title.toUpperCase()}

6 | ) 7 | } 8 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.generate-ddl=true 2 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 3 | spring.jpa.hibernate.ddl-auto=create-drop 4 | spring.data.redis.repositories.enabled=false -------------------------------------------------------------------------------- /server/common-data-service/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.generate-ddl=true 2 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 3 | #spring.jpa.hibernate.ddl-auto=create-drop 4 | spring.data.redis.repositories.enabled=false 5 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/.DS_Store -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/entity/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WHAHA-HA/spring-boot-react-ecommerce/HEAD/server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/entity/.DS_Store -------------------------------------------------------------------------------- /server/payment-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /server/authentication-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /server/common-data-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/service/interfaces/LoadFakeDataService.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.service.interfaces; 2 | 3 | public interface LoadFakeDataService { 4 | 5 | boolean loadTestData(); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /server/seller-account-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /client/src/styles/materialUI/webFormStyles.js: -------------------------------------------------------------------------------- 1 | import {makeStyles} from "@material-ui/core/styles"; 2 | 3 | const useWebFormStyles = makeStyles((theme) => ({ 4 | typographyRootHeader: { 5 | fontWeight: '5px' 6 | } 7 | })); 8 | 9 | export default useWebFormStyles; 10 | -------------------------------------------------------------------------------- /server/search-suggestion-service/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /client/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /client/src/styles/materialUI/checkoutFormStyles.js: -------------------------------------------------------------------------------- 1 | 2 | export const checkoutFormStyles = theme => ({ 3 | root: { 4 | '& > *': { 5 | marginLeft: theme.spacing(3), 6 | }, 7 | }, 8 | formControlLabel: { 9 | width: "inherit" 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /wait-for-mysql.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | cmd="$@" 6 | 7 | echo "starting" 8 | 9 | until mysql -h$DB_HOST -u$DB_USER -p$DB_PASS -e '\q'; do 10 | >&2 echo "MySQL is unavailable - sleeping" 11 | sleep 2 12 | done 13 | 14 | echo "Done" 15 | 16 | echo "MySQL is up - executing command = $cmd" 17 | 18 | exec $cmd 19 | -------------------------------------------------------------------------------- /client/src/__tests__/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from '../components/app'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /client/src/components/ui/error/badRequest.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import badRequestImage from '../../../images/badRequest400.png' 3 | import {RenderErrorImage} from "./renderErrorImage"; 4 | 5 | export const BadRequest = () => { 6 | 7 | return ( 8 | 9 | ); 10 | }; -------------------------------------------------------------------------------- /client/src/components/ui/documentTitle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Helmet from 'react-helmet'; 3 | 4 | const DocumentTitle = ({ title }) => { 5 | const defaultTitle = 'Shoppers'; 6 | return ( 7 | 8 | {title ? title : defaultTitle} 9 | 10 | ); 11 | }; 12 | 13 | export { DocumentTitle }; -------------------------------------------------------------------------------- /server/payment-service/src/main/java/com/ujjaval/ecommerce/paymentservice/dto/CardToken.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.paymentservice.dto; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @NoArgsConstructor 8 | @AllArgsConstructor 9 | @ToString 10 | public class CardToken { 11 | String id; 12 | Long amount; 13 | String currency; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /server/payment-service/src/test/java/com/ujjaval/ecommerce/paymentservice/PaymentServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.paymentservice; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class PaymentServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /client/src/components/ui/error/internalServerError.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import internalServerErrorImage from '../../../images/internalServer500.png' 3 | import {RenderErrorImage} from "./renderErrorImage"; 4 | 5 | export const InternalServerError = () => { 6 | 7 | return ( 8 | 9 | ); 10 | }; -------------------------------------------------------------------------------- /server/common-data-service/src/test/java/com/ujjaval/ecommerce/commondataservice/CommonDataServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class CommonDataServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/model/AuthenticationRequest.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.model; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @NoArgsConstructor 8 | @AllArgsConstructor 9 | @ToString 10 | public class AuthenticationRequest { 11 | 12 | private String username; 13 | private String password; 14 | } 15 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/info/BankInfoRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.info; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.info.BankInfo; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface BankInfoRepository extends JpaRepository { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/info/OrderInfoRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.info; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.info.OrderInfo; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface OrderInfoRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/dao/sql/SellerInfoRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice.dao.sql; 2 | 3 | import com.ujjaval.ecommerce.selleraccountservice.entity.sql.SellerInfo; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface SellerInfoRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /client/src/constants/api_routes.js: -------------------------------------------------------------------------------- 1 | export const HOME_PAGE_DATA_API = "/home"; 2 | export const TABS_DATA_API = "/tabs"; 3 | export const PRODUCT_BY_ID_DATA_API = "/products?product_id="; 4 | export const PRODUCT_BY_CATEGORY_DATA_API = "/products"; 5 | export const SEARCH_SUGGESTION_API = "/search-suggestion?q="; 6 | export const DEFAULT_SEARCH_SUGGESTION_API = "/default-search-suggestion"; 7 | export const FILTER_ATTRIBUTES_API = "/filter"; -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/info/AddressInfoRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.info; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.info.AddressInfo; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface AddressInfoRepository extends JpaRepository { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/info/ContactInfoRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.info; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.info.ContactInfo; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | 7 | public interface ContactInfoRepository extends JpaRepository { 8 | } 9 | -------------------------------------------------------------------------------- /server/seller-account-service/src/test/java/com/ujjaval/ecommerce/selleraccountservice/SellerAccountServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SellerAccountServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/model/AccountCreationResponse.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.model; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @NoArgsConstructor 8 | @AllArgsConstructor 9 | @ToString 10 | public class AccountCreationResponse { 11 | private String account_creation_status; 12 | private String error_msg; 13 | } 14 | -------------------------------------------------------------------------------- /server/authentication-service/src/test/java/com/ujjaval/ecommerce/authenticationservice/AuthenticationServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class AuthenticationServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/entity/nosql/SellerReview.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice.entity.nosql; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @AllArgsConstructor 8 | @ToString 9 | public class SellerReview { 10 | 11 | private double rating; 12 | 13 | private String comment; 14 | 15 | private String timestamp; 16 | 17 | } -------------------------------------------------------------------------------- /client/src/logger/loggerTypes.js: -------------------------------------------------------------------------------- 1 | import Logger from './Logger'; 2 | 3 | export const LoggerTypes = { 4 | MAIN_SCREEN_LOGGER: 1, 5 | FILTER_SCREEN_LOGGER: 2 6 | } 7 | 8 | export const LoggerRegisterInfo = [ 9 | { 10 | id: LoggerTypes.MAIN_SCREEN_LOGGER, 11 | level: Logger.Levels.INFO 12 | }, 13 | { 14 | id: LoggerTypes.FILTER_SCREEN_LOGGER, 15 | level: Logger.Levels.DEBUG 16 | }, 17 | ] -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/model/AuthenticationResponse.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.model; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @NoArgsConstructor 8 | @AllArgsConstructor 9 | @ToString 10 | public class AuthenticationResponse { 11 | 12 | private String jwt; 13 | private String error; 14 | private String firstName; 15 | } -------------------------------------------------------------------------------- /server/search-suggestion-service/src/test/java/com/ujjaval/ecommerce/searchsuggestionservice/SearchSuggestionServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.searchsuggestionservice; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SearchSuggestionServiceApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/dao/nosql/SellerBulkInfoRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice.dao.nosql; 2 | 3 | import com.ujjaval.ecommerce.selleraccountservice.entity.nosql.SellerBulkInfo; 4 | import org.springframework.data.mongodb.repository.MongoRepository; 5 | 6 | public interface SellerBulkInfoRepository extends MongoRepository { 7 | } 8 | -------------------------------------------------------------------------------- /client/src/styles/index.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | max-width: 100%; 3 | height: 100% !important; 4 | padding: 0; 5 | margin: 0; 6 | } 7 | 8 | body ::-webkit-scrollbar { 9 | width:0 !important; 10 | height: 0 !important; 11 | } 12 | 13 | #customDropdown { 14 | font-weight: bold; 15 | } 16 | 17 | input { 18 | font-size: 1.2rem !important; 19 | } 20 | 21 | .ui.button.googleButtonStyle { 22 | width: 100%; 23 | height: 40px; 24 | } -------------------------------------------------------------------------------- /client/src/components/routes/checkout/stripeInput.js: -------------------------------------------------------------------------------- 1 | import React, { useRef, useImperativeHandle } from 'react' 2 | 3 | export const StripeInput = ({ component: Component, inputRef, ...other }) => { 4 | const elementRef = useRef(); 5 | useImperativeHandle(inputRef, () => ({ 6 | focus: () => elementRef.current.focus 7 | })); 8 | 9 | return ( 10 | (elementRef.current = element)} {...other} /> 11 | ); 12 | } -------------------------------------------------------------------------------- /client/src/components/ui/BackgroundDisabledSpinner.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Dimmer, Loader} from "semantic-ui-react"; 3 | import log from 'loglevel'; 4 | 5 | export default function BackgroundDisabledSpinner() { 6 | log.info(`[BackgroundDisabledSpinner] Rendering BackgroundDisabledSpinner Component...`) 7 | return ( 8 | 9 | Loading 10 | 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /client/src/components/ui/error/GenericErrorMsg.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import log from 'loglevel' 3 | import {Grid} from "@material-ui/core"; 4 | 5 | export const GenericErrorMsg = () => { 6 | 7 | log.info('[GenericErrorMsg] Rendering GenericErrorMsg Component') 8 | return ( 9 | 10 |

Oops! Something went wrong....

11 |
12 | ) 13 | } -------------------------------------------------------------------------------- /client/src/styles/semanticUI/commonStyles.css: -------------------------------------------------------------------------------- 1 | 2 | /* Quantity Dropdown Styling */ 3 | .ui.menu > div { 4 | width: auto !important; 5 | min-width: auto !important; 6 | } 7 | 8 | #quantity-dropdown > .text { 9 | font-weight: bold !important; 10 | } 11 | 12 | #quantity-dropdown > .icon { 13 | margin-left: 5px !important; 14 | } 15 | 16 | #quantity-dropdown > .menu > div { 17 | padding: 5px 15px 5px 17px !important; 18 | } 19 | 20 | /*****************************/ 21 | 22 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dto/BrandsAndApparelsDTO.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dto; 2 | 3 | import lombok.*; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | 8 | @Getter 9 | @Setter 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | @ToString 13 | public class BrandsAndApparelsDTO implements Serializable { 14 | List brands; 15 | List apparels; 16 | } 17 | -------------------------------------------------------------------------------- /client/Dockerfile: -------------------------------------------------------------------------------- 1 | # Base Package 2 | FROM node:14 3 | 4 | MAINTAINER Ujjaval Desai 5 | 6 | # Create app directory 7 | WORKDIR /usr/src/app 8 | 9 | # Install app dependencies 10 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 11 | # where available (npm@5+) 12 | COPY ./client/package*.json ./ 13 | 14 | RUN npm install 15 | 16 | # Bundle app source 17 | COPY . . 18 | 19 | #RUN yarn install 20 | 21 | # Initiate npm start 22 | CMD [ "npm", "run-script", "start_docker_dev" ] -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/model/AccountCreationRequest.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.model; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @NoArgsConstructor 8 | @AllArgsConstructor 9 | @ToString 10 | public class AccountCreationRequest { 11 | private String username; 12 | private String password; 13 | private String lastname; 14 | private String firstname; 15 | private String email; 16 | } 17 | -------------------------------------------------------------------------------- /server/common-data-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /server/seller-account-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /server/authentication-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | logs/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dto/FilterAttributesDTO.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.io.Serializable; 9 | 10 | @Getter 11 | @Setter 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class FilterAttributesDTO implements Serializable { 15 | Integer id; 16 | String value; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/entity/nosql/SellerAccountNotification.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice.entity.nosql; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @NoArgsConstructor 8 | @AllArgsConstructor 9 | @ToString 10 | public class SellerAccountNotification { 11 | 12 | private int severityLevel; 13 | 14 | private boolean starred; 15 | 16 | private String notificationMsg; 17 | 18 | private String timestamp; 19 | } 20 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/SellerAccountServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SellerAccountServiceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SellerAccountServiceApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /start-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Stop and delete the containers 4 | #docker-compose down 5 | 6 | # Stop and delete the containers 7 | docker-compose stop 8 | 9 | # Deleting network if available 10 | docker network rm spring-cloud-microservices 11 | 12 | # Creating network for services 13 | docker network create spring-cloud-microservices 14 | 15 | # Increasing default HTTP Timeout from 60 to 300 16 | export COMPOSE_HTTP_TIMEOUT=300 17 | 18 | # Start all services in background with -d flag 19 | docker-compose up --build 20 | -------------------------------------------------------------------------------- /client/src/components/ui/error/renderErrorImage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Grid} from "@material-ui/core"; 3 | 4 | export const RenderErrorImage = (props) => { 5 | 6 | return ( 7 | 9 | 10 | {props.name} 11 | 12 | 13 | ); 14 | }; -------------------------------------------------------------------------------- /client/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const path = require('path'); 3 | const port = process.env.PORT || 3000; 4 | const app = express(); 5 | 6 | // the __dirname is the current directory from where the script is running 7 | app.use(express.static(__dirname)); 8 | app.use(express.static(path.join(__dirname, 'build'))); 9 | app.get('/ping', function (req, res) { 10 | return res.send('pong'); 11 | }); 12 | app.get('/*', function (req, res) { 13 | res.sendFile(path.join(__dirname, 'build', 'index.html')); 14 | }); 15 | app.listen(port); -------------------------------------------------------------------------------- /client/src/components/ui/spinner.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import CircularProgress from '@material-ui/core/CircularProgress'; 3 | import {Box} from "@material-ui/core"; 4 | 5 | export default function Spinner({textComponent = null}) { 6 | return ( 7 | 9 | 10 | 11 | {textComponent} 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dto/ProductInfoDTO.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dto; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.info.ProductInfo; 4 | import lombok.*; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | @Getter 10 | @Setter 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | @ToString 14 | public class ProductInfoDTO implements Serializable { 15 | 16 | private Long totalCount; 17 | private List products; 18 | } -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/entity/nosql/SellerMessage.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice.entity.nosql; 2 | 3 | import lombok.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | @Getter 10 | @Setter 11 | @ToString 12 | public class SellerMessage { 13 | 14 | private Map> msgThreadMap; 15 | 16 | public SellerMessage() { 17 | 18 | msgThreadMap = new HashMap<>(); 19 | } 20 | } -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/model/UserInfo.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Setter 8 | @Getter 9 | @AllArgsConstructor 10 | public class UserInfo { 11 | private int id; 12 | 13 | private String firstName; 14 | 15 | private String lastName; 16 | 17 | private String userName; 18 | 19 | private String password; 20 | 21 | private String email; 22 | } 23 | -------------------------------------------------------------------------------- /server/payment-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /server/search-suggestion-service/src/main/java/com/ujjaval/ecommerce/searchsuggestionservice/service/SearchSuggestionService.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.searchsuggestionservice.service; 2 | 3 | import com.ujjaval.ecommerce.searchsuggestionservice.dto.SearchSuggestionKeywordInfo; 4 | import java.util.List; 5 | 6 | public interface SearchSuggestionService { 7 | void loadSearchSuggestionToMap(); 8 | 9 | List searchKeywordFromMap(String q); 10 | 11 | List getDefaultSearchSuggestions(); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /client/src/reducers/events/eventReducer.js: -------------------------------------------------------------------------------- 1 | import {HANDLE_TAB_HOVER_EVENT} from "../../actions/types"; 2 | import log from "loglevel"; 3 | 4 | export const tabHoverEventReducer = (state 5 | = {index: false, hover: false, tabColor: "black"}, action) => { 6 | switch (action.type) { 7 | case HANDLE_TAB_HOVER_EVENT: 8 | log.debug(`[TAB_HOVER_EVENT_REDUCER]: action.payload = ${JSON.stringify(action.payload)}`) 9 | return action.payload; 10 | 11 | default: 12 | return state; 13 | } 14 | }; -------------------------------------------------------------------------------- /server/search-suggestion-service/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /client/src/helper/toggleId.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | export const toggleId = (id, value, list) => { 4 | let valueExist = false 5 | let ids = [] 6 | 7 | // eslint-disable-next-line array-callback-return 8 | let filteredList = list.filter(obj => { 9 | if (obj.id !== id) { 10 | ids.push(obj.id) 11 | return obj; 12 | } 13 | valueExist = true 14 | }) 15 | 16 | if (valueExist) { 17 | return {list: filteredList, ids} 18 | } else { 19 | ids.push(id) 20 | list.push({id: id, value: value}); 21 | return {list, ids} 22 | } 23 | } -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/AuthenticationServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 6 | 7 | @SpringBootApplication 8 | public class AuthenticationServiceApplication { 9 | 10 | public static void main(String[] args) { 11 | SpringApplication.run(AuthenticationServiceApplication.class, args); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dto/SearchSuggestionForTwoAttrDTO.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.io.Serializable; 9 | 10 | @Getter 11 | @Setter 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class SearchSuggestionForTwoAttrDTO implements Serializable { 15 | Integer attr1_id; 16 | String attr1_type; 17 | Integer attr2_id; 18 | String attr2_type; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/service/SellerAccountDataService.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice.service; 2 | 3 | 4 | import com.ujjaval.ecommerce.selleraccountservice.entity.nosql.SellerBulkInfo; 5 | import com.ujjaval.ecommerce.selleraccountservice.entity.sql.SellerInfo; 6 | 7 | public interface SellerAccountDataService { 8 | 9 | public SellerInfo findSellerById(Integer sellerId); 10 | 11 | public void save(); 12 | 13 | public void saveInMongo(); 14 | 15 | public SellerBulkInfo findMongoAddressById(); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/entity/nosql/SellerMessageDetails.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice.entity.nosql; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @NoArgsConstructor 8 | @AllArgsConstructor 9 | @ToString 10 | public class SellerMessageDetails { 11 | private int msgSeqNum; 12 | 13 | private int status; 14 | 15 | private String msgBody; 16 | 17 | private String msgSubject; 18 | 19 | private String senderName; 20 | 21 | private String timestamp; 22 | 23 | private boolean starred; 24 | } 25 | -------------------------------------------------------------------------------- /client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /server/search-suggestion-service/src/main/java/com/ujjaval/ecommerce/searchsuggestionservice/dto/SearchSuggestionKeywordInfo.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.searchsuggestionservice.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class SearchSuggestionKeywordInfo { 9 | String keyword; 10 | StringBuilder link; 11 | Integer rank; 12 | 13 | public SearchSuggestionKeywordInfo(String keyword, StringBuilder link, Integer rank) { 14 | this.keyword = keyword; 15 | this.link = new StringBuilder(link); 16 | this.rank = rank; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/images/BrandImagesRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.images; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.images.BrandImages; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | 7 | import java.util.List; 8 | 9 | public interface BrandImagesRepository extends JpaRepository { 10 | 11 | @Query(value = "SELECT DISTINCT b FROM BrandImages b") 12 | List getAllData(); 13 | } 14 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/images/ApparelImagesRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.images; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.images.ApparelImages; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | 7 | import java.util.List; 8 | 9 | public interface ApparelImagesRepository extends JpaRepository { 10 | 11 | @Query(value = "SELECT DISTINCT c FROM ApparelImages c") 12 | List getAllData(); 13 | } 14 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/images/CarouselImagesRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.images; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.images.CarouselImages; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | 7 | import java.util.List; 8 | 9 | public interface CarouselImagesRepository extends JpaRepository { 10 | 11 | @Query(value = "SELECT DISTINCT c FROM CarouselImages c") 12 | List getAllData(); 13 | } 14 | -------------------------------------------------------------------------------- /client/src/components/routes/navbar/bagButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import log from "loglevel"; 3 | import LocalMallIcon from "@material-ui/icons/LocalMall"; 4 | import {Badge} from "@material-ui/core"; 5 | import {useSelector} from "react-redux"; 6 | 7 | export default function BagButton() { 8 | const addToCart = useSelector(state => state.addToCartReducer) 9 | 10 | log.info(`[BagButton]: Rendering BagButton Component`) 11 | return ( 12 | 14 | 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/service/AuthDataService.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.service; 2 | 3 | import com.ujjaval.ecommerce.authenticationservice.entity.UserInfo; 4 | 5 | import java.security.NoSuchAlgorithmException; 6 | 7 | public interface AuthDataService { 8 | 9 | UserInfo findByUsername(String username); 10 | 11 | UserInfo findByEmail(String email); 12 | 13 | void deleteByUsernamePassword(String username, String password) throws NoSuchAlgorithmException; 14 | 15 | void createUserProfile(UserInfo userInfo) throws NoSuchAlgorithmException; 16 | } 17 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dto/SearchSuggestionForThreeAttrDTO.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | 8 | import java.io.Serializable; 9 | 10 | @Getter 11 | @Setter 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class SearchSuggestionForThreeAttrDTO implements Serializable { 15 | Integer attr1_id; 16 | String attr1_type; 17 | Integer attr2_id; 18 | String attr2_type; 19 | Integer attr3_id; 20 | String attr3_type; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/utils/resulttransformers/IListResultTransformer.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.utils.resulttransformers; 2 | 3 | import org.hibernate.transform.ResultTransformer; 4 | 5 | import java.util.List; 6 | 7 | @FunctionalInterface 8 | public interface IListResultTransformer extends ResultTransformer { 9 | 10 | /** 11 | * Default implementation returning the tuples list as-is. 12 | * 13 | * @param tuples tuples list 14 | * @return tuples list 15 | */ 16 | @Override 17 | default List transformList(List tuples) { 18 | return tuples; 19 | } 20 | } -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dto/BrandImagesDTO.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dto; 2 | 3 | import lombok.*; 4 | 5 | import java.io.Serializable; 6 | 7 | @Getter 8 | @Setter 9 | @NoArgsConstructor 10 | @ToString 11 | public class BrandImagesDTO implements Serializable { 12 | 13 | private String title; 14 | 15 | private String imageLocalPath; 16 | 17 | private String imageURL; 18 | 19 | private BrandCategoryDTO brandInfo; 20 | 21 | } 22 | 23 | @Getter 24 | @Setter 25 | @NoArgsConstructor 26 | @ToString 27 | class BrandCategoryDTO implements Serializable { 28 | private int id; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/config/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.config; 2 | 3 | import org.modelmapper.ModelMapper; 4 | import org.modelmapper.convention.MatchingStrategies; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class AppConfig { 10 | 11 | @Bean 12 | public ModelMapper modelMapper() { 13 | ModelMapper modelMapper = new ModelMapper(); 14 | modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.LOOSE); 15 | return modelMapper; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /server/payment-service/src/main/java/com/ujjaval/ecommerce/paymentservice/PaymentServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.paymentservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 7 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 8 | 9 | @SpringBootApplication 10 | public class PaymentServiceApplication { 11 | public static void main(String[] args) { 12 | SpringApplication.run(PaymentServiceApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /client/src/components/ui/error/httpError.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {BAD_REQUEST_ERROR_CODE, INTERNAL_SERVER_ERROR_CODE} from "../../../constants/http_error_codes"; 3 | import {InternalServerError} from "./internalServerError"; 4 | import {BadRequest} from "./badRequest"; 5 | import log from 'loglevel'; 6 | 7 | export const HTTPError = props => { 8 | log.info(`[HTTPError] props.statusCode = ${props.statusCode}`) 9 | 10 | switch (props.statusCode) { 11 | case INTERNAL_SERVER_ERROR_CODE: 12 | return 13 | case BAD_REQUEST_ERROR_CODE: 14 | return 15 | default: 16 | return null 17 | } 18 | }; -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/categories/GenderCategoryRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.categories; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.GenderCategory; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | 7 | import java.util.List; 8 | 9 | public interface GenderCategoryRepository extends JpaRepository { 10 | 11 | @Query(value = "SELECT g FROM GenderCategory g") 12 | List getAllData(); 13 | 14 | GenderCategory findByType(String gender); 15 | } 16 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/categories/SortByCategoryRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.categories; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.SortByCategory; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | 7 | import java.util.List; 8 | 9 | public interface SortByCategoryRepository extends JpaRepository { 10 | 11 | @Query(value = "SELECT s FROM SortByCategory s") 12 | List getAllData(); 13 | 14 | SortByCategory findByType(String type); 15 | } 16 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=authentication-service 2 | server.port=${PORT} 3 | spring.profiles.active=${ACTIVE_PROFILE} 4 | spring.datasource.url=jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_SCHEMA}?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC 5 | spring.datasource.username=${DB_USER} 6 | spring.datasource.password=${DB_PASS} 7 | 8 | # debugging purpose 9 | spring.jpa.properties.hibernate.format_sql=true 10 | logging.level.org.hibernate.SQL=DEBUG 11 | logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE 12 | logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG 13 | logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dto/FilterAttributesWithTotalItemsDTO.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | import java.io.Serializable; 8 | 9 | @Getter 10 | @Setter 11 | @NoArgsConstructor 12 | public class FilterAttributesWithTotalItemsDTO implements Serializable { 13 | 14 | Integer id; 15 | String value; 16 | Long totalItems; 17 | 18 | public FilterAttributesWithTotalItemsDTO(Integer id, String value, Long totalItems) { 19 | this.id = id; 20 | this.value = value; 21 | this.totalItems = totalItems; 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/categories/PriceRangeCategoryRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.categories; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.PriceRangeCategory; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | 7 | import java.util.List; 8 | 9 | public interface PriceRangeCategoryRepository extends JpaRepository { 10 | 11 | @Query(value = "SELECT p FROM PriceRangeCategory p") 12 | List getAllData(); 13 | 14 | PriceRangeCategory findByType(String type); 15 | } 16 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/categories/ProductBrandCategoryRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.categories; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.ProductBrandCategory; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | 7 | import java.util.List; 8 | 9 | public interface ProductBrandCategoryRepository extends JpaRepository { 10 | 11 | @Query(value = "SELECT p FROM ProductBrandCategory p") 12 | List getAllData(); 13 | 14 | ProductBrandCategory findByType(String brandName); 15 | } 16 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/entity/nosql/SellerBulkInfo.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice.entity.nosql; 2 | 3 | import lombok.*; 4 | import org.springframework.data.annotation.Id; 5 | import org.springframework.data.mongodb.core.mapping.Document; 6 | 7 | import java.util.ArrayList; 8 | 9 | @Getter 10 | @Setter 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | @ToString 14 | @Document 15 | public class SellerBulkInfo { 16 | 17 | @Id 18 | private int id; 19 | 20 | private SellerMessage sellerMessage; 21 | 22 | private ArrayList sellerReview; 23 | 24 | private ArrayList sellerAccountNotification; 25 | } 26 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/config/CorsConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 5 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | 8 | @Configuration 9 | @EnableWebMvc 10 | public class CorsConfigurer implements WebMvcConfigurer 11 | { 12 | @Override 13 | public void addCorsMappings(CorsRegistry registry) { 14 | registry.addMapping("/**") 15 | .allowedMethods("GET", "POST"); 16 | } 17 | } -------------------------------------------------------------------------------- /server/payment-service/src/main/java/com/ujjaval/ecommerce/paymentservice/dto/PaymentStatus.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.paymentservice.dto; 2 | 3 | import lombok.*; 4 | 5 | @Getter 6 | @Setter 7 | @NoArgsConstructor 8 | @ToString 9 | public class PaymentStatus { 10 | 11 | boolean payment_failed; 12 | Long order_id; 13 | String charge_id; 14 | String txn_id; 15 | String receipt_url; 16 | 17 | public PaymentStatus(Long order_id, boolean payment_failed, String charge_id, String txn_id, String receipt_url) { 18 | this.order_id = order_id; 19 | this.payment_failed = payment_failed; 20 | this.charge_id = charge_id; 21 | this.txn_id = txn_id; 22 | this.receipt_url = receipt_url; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=common-data-service 2 | server.port=${PORT} 3 | spring.profiles.active=${ACTIVE_PROFILE} 4 | spring.datasource.url=jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_SCHEMA}?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC 5 | spring.datasource.username=${DB_USER} 6 | spring.datasource.password=${DB_PASS} 7 | 8 | spring.cache.redis.time-to-live=10 9 | 10 | # debugging purpose 11 | spring.jpa.properties.hibernate.format_sql=true 12 | #logging.level.org.hibernate.SQL=DEBUG 13 | #logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE 14 | #logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG 15 | #logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | .env 4 | 5 | # Client 6 | # dependencies 7 | /client/node_modules 8 | /client/.pnp 9 | /client/.pnp.js 10 | 11 | # testing 12 | /client/coverage 13 | 14 | # production 15 | /build 16 | 17 | # misc 18 | .DS_Store 19 | client/.env 20 | client/.env.local 21 | client/.env.development.local 22 | client/.env.test.local 23 | client/.env.production.local 24 | .idea/ 25 | node_modules/ 26 | package-lock.json 27 | 28 | client/npm-debug.log* 29 | client/yarn-debug.log* 30 | client/yarn-error.log* 31 | 32 | # server 33 | server/common-data-service/src/main/resources/static/images/ 34 | server/authentication-service/.idea/ 35 | server/common-data-service/.idea/ 36 | server/seller-account-service/.idea/ 37 | -------------------------------------------------------------------------------- /.env-sample: -------------------------------------------------------------------------------- 1 | MYSQL_ROOT_PASSWORD=mypass 2 | MYSQL_DATABASE=ecommerce_app_database 3 | MYSQL_USER=mysqluser 4 | MYSQL_PASSWORD=mypass 5 | 6 | DB_PORT=3306 7 | DB_SCHEMA=ecommerce_app_database 8 | DB_USER=mysqluser 9 | DB_PASS=mypass 10 | 11 | REACT_APP_STRIPE_PUBLISH_KEY=pk_test_51H805Oa3n3j3JVXUotWOsdf223PXI2ZehJ0s4QSQK0WjEJer78w87wer8h2u3bo32sTVcxyh5bDuulBildNrp 12 | REACT_APP_GOOGLE_AUTH_CLIENT_ID=23432543654-m4s23i3dsf72938gubrj32n8932ro9knqudv.apps.googleusercontent.com 13 | REACT_APP_PORT=3000 14 | 15 | REACT_CLIENT_URL=http://localhost:3000 16 | REACT_APP_ENVIRONMENT=dev 17 | ACTIVE_PROFILE=dev 18 | 19 | REDIS_PASSWORD=mypass 20 | REDIS_PORT=6379 21 | 22 | AUTHENTICATION_SERVICE_PORT=7000 23 | PAYMENT_SERVICE_PORT=9050 24 | COMMON_DATA_SERVICE_PORT=9000 25 | SEARCH_SUGGESTION_SERVICE_PORT=10000 26 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/model/HomeTabsDataResponse.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.model; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.dto.BrandsAndApparelsDTO; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | import java.io.Serializable; 10 | 11 | @Getter 12 | @Setter 13 | @NoArgsConstructor 14 | @ToString 15 | public class HomeTabsDataResponse implements Serializable { 16 | 17 | private BrandsAndApparelsDTO men; 18 | private BrandsAndApparelsDTO women; 19 | private BrandsAndApparelsDTO boys; 20 | private BrandsAndApparelsDTO girls; 21 | private BrandsAndApparelsDTO essentials; 22 | private BrandsAndApparelsDTO homeAndLiving; 23 | } -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/config/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 5 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | 8 | @Configuration 9 | @EnableWebMvc 10 | public class CorsConfig implements WebMvcConfigurer 11 | { 12 | @Override 13 | public void addCorsMappings(CorsRegistry registry) { 14 | registry.addMapping("/**"); 15 | //registry.addMapping("/**").allowedOrigins("https://shoppers-ecom-app.herokuapp.com") 16 | // .allowedMethods("GET", "POST"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /server/search-suggestion-service/src/main/java/com/ujjaval/ecommerce/searchsuggestionservice/config/CorsConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.searchsuggestionservice.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 5 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | 8 | @Configuration 9 | @EnableWebMvc 10 | public class CorsConfig implements WebMvcConfigurer 11 | { 12 | @Override 13 | public void addCorsMappings(CorsRegistry registry) { 14 | registry.addMapping("/**").allowedOrigins("https://shoppers-ecom-app.herokuapp.com") 15 | .allowedMethods("GET", "POST", "OPTIONS", "DELETE"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/categories/SortByCategory.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.categories; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import javax.persistence.Entity; 9 | import javax.persistence.GeneratedValue; 10 | import javax.persistence.GenerationType; 11 | import javax.persistence.Id; 12 | import java.io.Serializable; 13 | 14 | @Getter 15 | @Setter 16 | @NoArgsConstructor 17 | @ToString 18 | @Entity 19 | public class SortByCategory implements Serializable { 20 | @Id 21 | private int id; 22 | 23 | private String type; 24 | 25 | public SortByCategory(int id, String type) { 26 | this.id = id; 27 | this.type = type; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/CommonDataServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.controller.CommonDataController; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cache.annotation.EnableCaching; 7 | import org.springframework.context.ConfigurableApplicationContext; 8 | 9 | @SpringBootApplication 10 | @EnableCaching 11 | public class CommonDataServiceApplication { 12 | 13 | public static void main(final String[] args) { 14 | ConfigurableApplicationContext context = SpringApplication.run(CommonDataServiceApplication.class, args); 15 | context.getBean(CommonDataController.class).fillWithTestData(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/entity/sql/SellerInfo.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice.entity.sql; 2 | 3 | import lombok.*; 4 | 5 | import javax.persistence.*; 6 | 7 | @Getter 8 | @Setter 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @ToString 12 | @Entity 13 | public class SellerInfo { 14 | 15 | @Id 16 | private int id; 17 | 18 | private int userId; 19 | 20 | private double balance; 21 | 22 | private float rating; 23 | 24 | private String companyName; 25 | 26 | private boolean verificationStatus; 27 | 28 | private int accountType; 29 | 30 | private String lastLoginTime; 31 | 32 | private int totalActiveOrders; 33 | 34 | private int totalCancelledOrders; 35 | 36 | private int totalDeliveredOrders; 37 | 38 | private int totalOrders; 39 | } 40 | -------------------------------------------------------------------------------- /client/src/hooks/useCartTotal.js: -------------------------------------------------------------------------------- 1 | import {useEffect} from "react"; 2 | import log from "loglevel"; 3 | import {addToCartReducer} from "../reducers/screens/commonScreenReducer"; 4 | import Cookies from "js-cookie"; 5 | import {CART_TOTAL} from "../actions/types"; 6 | import {CART_TOTAL_COOKIE} from "../constants/cookies"; 7 | import {useDispatch} from "react-redux"; 8 | 9 | export function useCartTotal() { 10 | const dispatch = useDispatch() 11 | 12 | useEffect(() => { 13 | log.info("[useCartTotal] Component will mount...") 14 | 15 | let cartTotal = Cookies.get(CART_TOTAL_COOKIE) 16 | if (cartTotal) { 17 | cartTotal = JSON.parse(cartTotal) 18 | dispatch({ 19 | type: CART_TOTAL, 20 | payload: parseInt(cartTotal) 21 | }) 22 | } 23 | 24 | // eslint-disable-next-line 25 | }, [addToCartReducer]) 26 | } -------------------------------------------------------------------------------- /server/search-suggestion-service/src/main/java/com/ujjaval/ecommerce/searchsuggestionservice/SearchSuggestionServiceApplication.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.searchsuggestionservice; 2 | 3 | import com.ujjaval.ecommerce.searchsuggestionservice.controller.SearchSuggestionController; 4 | import org.json.JSONException; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.ConfigurableApplicationContext; 8 | 9 | import java.io.IOException; 10 | 11 | @SpringBootApplication 12 | public class SearchSuggestionServiceApplication { 13 | 14 | public static void main(String[] args) { 15 | ConfigurableApplicationContext context = SpringApplication.run(SearchSuggestionServiceApplication.class, args); 16 | context.getBean(SearchSuggestionController.class).loadSearchSuggestions(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /client/src/api/service_api.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const { 4 | REACT_APP_COMMON_DATA_SERVICE_PORT, 5 | REACT_APP_AUTHENTICATION_SERVICE_PORT, 6 | REACT_APP_SEARCH_SUGGESTION_SERVICE_PORT, 7 | REACT_APP_COMMON_DATA_SERVICE_URL, 8 | REACT_APP_AUTHENTICATION_SERVICE_URL, 9 | REACT_APP_SEARCH_SUGGESTION_SERVICE_URL 10 | } = process.env 11 | 12 | export const authServiceAPI = axios.create({ 13 | baseURL: REACT_APP_AUTHENTICATION_SERVICE_URL || `http://localhost:${REACT_APP_AUTHENTICATION_SERVICE_PORT}` 14 | }) 15 | 16 | export const commonServiceAPI = axios.create({ 17 | baseURL: REACT_APP_COMMON_DATA_SERVICE_URL || `http://localhost:${REACT_APP_COMMON_DATA_SERVICE_PORT}` 18 | }) 19 | 20 | export const searchSuggestionServiceAPI = axios.create({ 21 | baseURL: REACT_APP_SEARCH_SUGGESTION_SERVICE_URL || `http://localhost:${REACT_APP_SEARCH_SUGGESTION_SERVICE_PORT}` 22 | }) -------------------------------------------------------------------------------- /client/src/components/ui/error/emptyShoppingBag.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import emptyCheckoutCartImage from '../../../images/emptyCheckoutCart.png' 3 | import {RenderErrorImage} from "./renderErrorImage"; 4 | import {Button, Grid} from "@material-ui/core"; 5 | 6 | export const EmptyShoppingBag = (props) => { 7 | 8 | return ( 9 | <> 10 | 11 | 12 | 13 | 18 | 19 | 20 | 21 | ); 22 | }; -------------------------------------------------------------------------------- /client/.env-sample: -------------------------------------------------------------------------------- 1 | REACT_APP_STRIPE_PUBLISH_KEY=pk_test_5dsf4534jkmn4nm345QSQK0WjEJKx1PNH3mJxeUkA45345345Vcxyh5bDuulBildNrp3MWn005xEkAdJ4 2 | REACT_APP_GOOGLE_AUTH_CLIENT_ID=357808142500-sdfsndln4oh5345435.apps.googleusercontent.com 3 | 4 | # Add below ports if you are running on your machine 5 | REACT_APP_AUTHENTICATION_SERVICE_PORT=7000 6 | REACT_APP_PAYMENT_SERVICE_PORT=9050 7 | REACT_APP_COMMON_DATA_SERVICE_PORT=9000 8 | REACT_APP_SEARCH_SUGGESTION_SERVICE_PORT=10000 9 | REACT_APP_COMMON_DATA_SERVICE_IP=localhost 10 | 11 | # Add URL if you dont want to use port. 12 | # Higher priority is given to URL over PORTs. 13 | REACT_APP_AUTHENTICATION_SERVICE_URL= 14 | REACT_APP_COMMON_DATA_SERVICE_URL= 15 | REACT_APP_PAYMENT_SERVICE_URL= 16 | REACT_APP_SEARCH_SUGGESTION_SERVICE_URL= 17 | 18 | REACT_APP_ENVIRONMENT= 19 | -------------------------------------------------------------------------------- /server/payment-service/Dockerfile-prod: -------------------------------------------------------------------------------- 1 | # Docker multi-stage build 2 | 3 | # 1. Building the App with Maven 4 | FROM maven:3-jdk-11 5 | 6 | ADD . /payment_service_staging 7 | 8 | WORKDIR /payment_service_staging 9 | 10 | # Just echo so we can see, if everything is there 11 | RUN ls -l 12 | 13 | # Run Maven build 14 | RUN mvn clean install -DskipTests 15 | 16 | # 2. Just using the build artifact and then removing the build-container 17 | FROM openjdk:11-jdk 18 | 19 | VOLUME /tmp 20 | 21 | # Add Spring Boot payment-service.jar to Container 22 | COPY --from=0 /payment_service_staging/target/payment-service.jar payment-service.jar 23 | 24 | # Fire up our Spring Boot app by default 25 | CMD ["sh", "-c", "java -Dserver.port=$PORT -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -XX:+UseContainerSupport -Dspring.profiles.active=$ACTIVE_PROFILE -Djava.security.egd=file:/dev/./urandom -jar payment-service.jar" ] 26 | 27 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/info/queryhelpers/context/ParamsToQueryContext.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.info.queryhelpers.context; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | 7 | import java.util.HashMap; 8 | import java.util.List; 9 | 10 | @Getter 11 | @Setter 12 | @NoArgsConstructor 13 | public class ParamsToQueryContext { 14 | String sortBy; 15 | HashMap mapParams; 16 | List conditions; 17 | String[] pageInfo; 18 | 19 | public ParamsToQueryContext(String sortBy, HashMap mapParams, 20 | List conditions, String[] pageInfo) { 21 | this.sortBy = sortBy; 22 | this.mapParams = mapParams; 23 | this.conditions = conditions; 24 | this.pageInfo = pageInfo; 25 | } 26 | } -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/categories/ApparelCategoryRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.categories; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.ApparelCategory; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | 7 | import java.util.List; 8 | 9 | public interface ApparelCategoryRepository extends JpaRepository { 10 | 11 | @Query(value = "SELECT c FROM ApparelImages c where c.apparelCategory.type=?1 and" + 12 | " c.genderCategory.type=?2") 13 | ApparelCategory findByClothesTypeAndGender(String clothesType, String Gender); 14 | 15 | @Query(value = "SELECT c FROM ApparelCategory c") 16 | List getAllData(); 17 | 18 | ApparelCategory findByType(String title); 19 | } 20 | -------------------------------------------------------------------------------- /server/payment-service/Dockerfile-dev: -------------------------------------------------------------------------------- 1 | # Docker multi-stage build 2 | 3 | # 1. Building the App with Maven 4 | FROM maven:3-jdk-11 5 | 6 | ADD ./server/payment-service /payment_service_staging 7 | 8 | WORKDIR /payment_service_staging 9 | 10 | # Just echo so we can see, if everything is there 11 | RUN ls -l 12 | 13 | # Run Maven build 14 | RUN mvn clean install -DskipTests 15 | 16 | # 2. Just using the build artifact and then removing the build-container 17 | FROM openjdk:11-jdk 18 | 19 | VOLUME /tmp 20 | 21 | # Add Spring Boot payment-service.jar to Container 22 | COPY --from=0 /payment_service_staging/target/payment-service.jar payment-service.jar 23 | 24 | # Fire up our Spring Boot app by default 25 | CMD ["sh", "-c", "java -Dserver.port=$PORT -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -XX:+UseContainerSupport -Dspring.profiles.active=$ACTIVE_PROFILE -Djava.security.egd=file:/dev/./urandom -jar payment-service.jar" ] 26 | 27 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/entity/UserInfo.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.entity; 2 | 3 | import lombok.*; 4 | 5 | import javax.persistence.*; 6 | 7 | @Getter 8 | @Setter 9 | @NoArgsConstructor 10 | @ToString 11 | @Entity 12 | public class UserInfo { 13 | 14 | @Id 15 | @GeneratedValue(strategy=GenerationType.IDENTITY) 16 | private int userId; 17 | 18 | private String firstName; 19 | 20 | private String lastName; 21 | 22 | private String username; 23 | 24 | private String password; 25 | 26 | private String email; 27 | 28 | public UserInfo(String firstName, String lastName, String username, String password, String email) { 29 | this.firstName = firstName; 30 | this.lastName = lastName; 31 | this.username = username; 32 | this.password = password; 33 | this.email = email; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /server/common-data-service/Dockerfile-prod: -------------------------------------------------------------------------------- 1 | # Docker multi-stage build 2 | 3 | # 1. Building the App with Maven 4 | FROM maven:3-jdk-11 5 | 6 | ADD . /common_data_service_staging 7 | 8 | WORKDIR /common_data_service_staging 9 | 10 | # Just echo so we can see, if everything is there 11 | RUN ls -l 12 | 13 | # Run Maven build 14 | RUN mvn clean install -DskipTests 15 | 16 | # 2. Just using the build artifact and then removing the build-container 17 | FROM openjdk:11-jdk 18 | 19 | VOLUME /tmp 20 | 21 | # Add Spring Boot common-data-service.jar to Container 22 | COPY --from=0 /common_data_service_staging/target/common-data-service.jar common-data-service.jar 23 | 24 | # Fire up our Spring Boot app by default 25 | CMD ["sh", "-c", "java -Dserver.port=$PORT -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -XX:+UseContainerSupport -Dspring.profiles.active=$ACTIVE_PROFILE -Djava.security.egd=file:/dev/./urandom -jar common-data-service.jar" ] 26 | 27 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dto/ApparelImagesDTO.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dto; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.io.Serializable; 9 | 10 | @Getter 11 | @Setter 12 | @NoArgsConstructor 13 | @ToString 14 | public class ApparelImagesDTO implements Serializable { 15 | 16 | private String title; 17 | 18 | private String imageLocalPath; 19 | 20 | private String imageURL; 21 | 22 | private ApparelDTO apparelInfo; 23 | 24 | private GenderDTO genderInfo; 25 | 26 | } 27 | 28 | @Getter 29 | @Setter 30 | @NoArgsConstructor 31 | @ToString 32 | class ApparelDTO implements Serializable { 33 | private int id; 34 | } 35 | 36 | @Getter 37 | @Setter 38 | @NoArgsConstructor 39 | @ToString 40 | class GenderDTO implements Serializable { 41 | private int id; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /server/authentication-service/Dockerfile-prod: -------------------------------------------------------------------------------- 1 | # Docker multi-stage build 2 | 3 | # 1. Building the App with Maven 4 | FROM maven:3-jdk-11 5 | 6 | ADD . /authentication_service_staging 7 | 8 | WORKDIR /authentication_service_staging 9 | 10 | # Just echo so we can see, if everything is there 11 | RUN ls -l 12 | 13 | # Run Maven build 14 | RUN mvn clean install -DskipTests 15 | 16 | # 2. Just using the build artifact and then removing the build-container 17 | FROM openjdk:11-jdk 18 | 19 | VOLUME /tmp 20 | 21 | # Add Spring Boot authentication-service.jar to Container 22 | COPY --from=0 /authentication_service_staging/target/authentication-service.jar authentication-service.jar 23 | 24 | # Fire up our Spring Boot app by default 25 | CMD ["sh", "-c", "java -Dserver.port=$PORT -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -XX:+UseContainerSupport -Dspring.profiles.active=$ACTIVE_PROFILE -Djava.security.egd=file:/dev/./urandom -jar authentication-service.jar" ] 26 | 27 | -------------------------------------------------------------------------------- /client/src/styles/materialUI/tabStyles.js: -------------------------------------------------------------------------------- 1 | import {makeStyles} from "@material-ui/core/styles"; 2 | 3 | const useTabStyles = makeStyles((theme) => ({ 4 | root: { 5 | flexGrow: 1, 6 | }, 7 | paperRoot: { 8 | '& > *': { 9 | width: theme.spacing(45), 10 | height: theme.spacing(45), 11 | }, 12 | position: "fixed", 13 | zIndex: 1201 14 | }, 15 | listItemTextRoot: { 16 | '&:hover': { 17 | fontWeight: 500 18 | }, 19 | color: "black", 20 | }, 21 | tabRoot: { 22 | width: "auto", 23 | height: 80, 24 | flexGrow: 1, 25 | [theme.breakpoints.up('lg')]: { 26 | minWidth: 50, 27 | }, 28 | }, 29 | tabsWrapper: { 30 | fontWeight: "600", 31 | color: "black", 32 | [theme.breakpoints.up('md')]: { 33 | fontSize: "1rem", 34 | } 35 | }, 36 | })); 37 | 38 | export default useTabStyles; -------------------------------------------------------------------------------- /server/common-data-service/Dockerfile-dev: -------------------------------------------------------------------------------- 1 | # Docker multi-stage build 2 | 3 | # 1. Building the App with Maven 4 | FROM maven:3-jdk-11 5 | 6 | ADD ./server/common-data-service /common_data_service_staging 7 | 8 | WORKDIR /common_data_service_staging 9 | 10 | # Just echo so we can see, if everything is there 11 | RUN ls -l 12 | 13 | # Run Maven build 14 | RUN mvn clean install -DskipTests 15 | 16 | # 2. Just using the build artifact and then removing the build-container 17 | FROM openjdk:11-jdk 18 | 19 | VOLUME /tmp 20 | 21 | # Add Spring Boot common-data-service.jar to Container 22 | COPY --from=0 /common_data_service_staging/target/common-data-service.jar common-data-service.jar 23 | 24 | # Fire up our Spring Boot app by default 25 | CMD ["sh", "-c", "java -Dserver.port=$PORT -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -XX:+UseContainerSupport -Dspring.profiles.active=$ACTIVE_PROFILE -Djava.security.egd=file:/dev/./urandom -jar common-data-service.jar" ] 26 | 27 | -------------------------------------------------------------------------------- /client/src/ErrorBoundary.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from "react"; 2 | import {GenericErrorMsg} from "./components/ui/error/GenericErrorMsg"; 3 | 4 | class ErrorBoundary extends Component { 5 | 6 | constructor(props) { 7 | super(props); 8 | 9 | this.state = { 10 | hasError: false 11 | } 12 | } 13 | 14 | static getDerivedStateFromError(error) { 15 | return { 16 | hasError: true 17 | } 18 | } 19 | 20 | componentDidCatch(error, errorInfo) { 21 | // You can also log the error to an error reporting service 22 | // logErrorToMyService(error, errorInfo); 23 | console.log(`error = ${error}, errorInfo = ${JSON.stringify(errorInfo)}`) 24 | } 25 | 26 | render() { 27 | if (this.state.hasError) { 28 | return ( 29 | 30 | ) 31 | } 32 | return this.props.children 33 | } 34 | } 35 | 36 | export default ErrorBoundary; -------------------------------------------------------------------------------- /server/authentication-service/Dockerfile-dev: -------------------------------------------------------------------------------- 1 | # Docker multi-stage build 2 | 3 | # 1. Building the App with Maven 4 | FROM maven:3-jdk-11 5 | 6 | ADD ./server/authentication-service /authentication_service_staging 7 | 8 | WORKDIR /authentication_service_staging 9 | 10 | # Just echo so we can see, if everything is there 11 | RUN ls -l 12 | 13 | # Run Maven build 14 | RUN mvn clean install -DskipTests 15 | 16 | # 2. Just using the build artifact and then removing the build-container 17 | FROM openjdk:11-jdk 18 | 19 | VOLUME /tmp 20 | 21 | # Add Spring Boot authentication-service.jar to Container 22 | COPY --from=0 /authentication_service_staging/target/authentication-service.jar authentication-service.jar 23 | 24 | # Fire up our Spring Boot app by default 25 | CMD ["sh", "-c", "java -Dserver.port=$PORT -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -XX:+UseContainerSupport -Dspring.profiles.active=$ACTIVE_PROFILE -Djava.security.egd=file:/dev/./urandom -jar authentication-service.jar" ] -------------------------------------------------------------------------------- /client/src/components/ui/error/pageNotFound.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Grid, Button} from "@material-ui/core"; 3 | import pageNotFoundImage from '../../../images/pageNotFound404.png' 4 | import history from "../../../history"; 5 | import {RenderErrorImage} from "./renderErrorImage"; 6 | 7 | export const PageNotFound = () => { 8 | const onHomeBtnClick = () => { 9 | history.push(`/`); 10 | } 11 | 12 | return ( 13 | <> 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | ) 26 | ; 27 | }; -------------------------------------------------------------------------------- /server/search-suggestion-service/Dockerfile-prod: -------------------------------------------------------------------------------- 1 | # Docker multi-stage build 2 | 3 | # 1. Building the App with Maven 4 | FROM maven:3-jdk-11 5 | 6 | ADD . /search_suggestion_service_staging 7 | 8 | WORKDIR /search_suggestion_service_staging 9 | 10 | # Just echo so we can see, if everything is there 11 | RUN ls -l 12 | 13 | # Run Maven build 14 | RUN mvn clean install -DskipTests 15 | 16 | # 2. Just using the build artifact and then removing the build-container 17 | FROM openjdk:11-jdk 18 | 19 | VOLUME /tmp 20 | 21 | # Add Spring Boot search-suggestion-service.jar to Container 22 | COPY --from=0 /search_suggestion_service_staging/target/search-suggestion-service.jar search-suggestion-service.jar 23 | 24 | # Fire up our Spring Boot app by default 25 | CMD ["sh", "-c", "java -Dserver.port=$PORT -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -XX:+UseContainerSupport -Dspring.profiles.active=$ACTIVE_PROFILE -Djava.security.egd=file:/dev/./urandom -jar search-suggestion-service.jar" ] 26 | 27 | -------------------------------------------------------------------------------- /client/src/components/ui/error/searchMatchesNotFound.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Box} from "@material-ui/core"; 3 | import searchMatchesNotFoundImage from '../../../images/searchMatchesNotFound404.png' 4 | 5 | export const SearchMatchesNotFound = () => { 6 | 7 | return ( 8 | 13 | 14 | searchMatchesNotFoundImage 15 | 16 | 17 | We couldn't find any matches! 18 | 19 | 20 | Please check the spelling or try searching something else 21 | 22 | 23 | ); 24 | }; -------------------------------------------------------------------------------- /client/src/helper/updateQueryString.js: -------------------------------------------------------------------------------- 1 | export const updateQueryString = (history, attributeToUpdate, id, idList) => { 2 | let route = history.location.pathname 3 | let queryStr = history.location.search 4 | 5 | if (history.location.search.search(attributeToUpdate) === -1) { 6 | return `${route}${queryStr}::${attributeToUpdate}=${id}` 7 | } else { 8 | 9 | let attributes = queryStr.split("::") 10 | let newQueryStr = [] 11 | for (let i = 0; i < attributes.length; ++i) { 12 | if (attributes[i].search(attributeToUpdate) !== -1) { 13 | if (idList.length > 0) { 14 | newQueryStr.push(attributes[i].replace( 15 | new RegExp(`${attributeToUpdate}=(.*)`), 16 | `${attributeToUpdate}=${idList.toString()}`)) 17 | } 18 | continue 19 | } 20 | newQueryStr.push(attributes[i]) 21 | } 22 | 23 | return newQueryStr.join("::") 24 | } 25 | } -------------------------------------------------------------------------------- /server/search-suggestion-service/Dockerfile-dev: -------------------------------------------------------------------------------- 1 | # Docker multi-stage build 2 | 3 | # 1. Building the App with Maven 4 | FROM maven:3-jdk-11 5 | 6 | ADD ./server/search-suggestion-service /search_suggestion_service_staging 7 | 8 | WORKDIR /search_suggestion_service_staging 9 | 10 | # Just echo so we can see, if everything is there 11 | RUN ls -l 12 | 13 | # Run Maven build 14 | RUN mvn clean install -DskipTests 15 | 16 | # 2. Just using the build artifact and then removing the build-container 17 | FROM openjdk:11-jdk 18 | 19 | VOLUME /tmp 20 | 21 | # Add Spring Boot search-suggestion-service.jar to Container 22 | COPY --from=0 /search_suggestion_service_staging/target/search-suggestion-service.jar search-suggestion-service.jar 23 | 24 | # Fire up our Spring Boot app by default 25 | CMD ["sh", "-c", "java -Dserver.port=$PORT -Xmx300m -Xss512k -XX:CICompilerCount=2 -Dfile.encoding=UTF-8 -XX:+UseContainerSupport -Dspring.profiles.active=$ACTIVE_PROFILE -Djava.security.egd=file:/dev/./urandom -jar search-suggestion-service.jar" ] 26 | 27 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/util/Md5Util.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.util; 2 | 3 | import javax.xml.bind.DatatypeConverter; 4 | import java.security.MessageDigest; 5 | import java.security.NoSuchAlgorithmException; 6 | 7 | public class Md5Util { 8 | 9 | public static Md5Util singletonInstance = null; 10 | private String data; 11 | 12 | private Md5Util() { 13 | } 14 | 15 | public static Md5Util getInstance() { 16 | if(singletonInstance == null) { 17 | return new Md5Util(); 18 | } 19 | return singletonInstance; 20 | } 21 | 22 | public String getMd5Hash(String data) throws NoSuchAlgorithmException { 23 | MessageDigest md = MessageDigest.getInstance("MD5"); 24 | md.update(data.getBytes()); 25 | byte[] digest = md.digest(); 26 | String hash = DatatypeConverter 27 | .printHexBinary(digest).toLowerCase(); 28 | return hash; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /client/src/styles/materialUI/filterNavBarStyles.js: -------------------------------------------------------------------------------- 1 | import {makeStyles} from "@material-ui/core/styles"; 2 | 3 | const drawerWidth = 240; 4 | 5 | export const useFilterNavBarStyles = makeStyles((theme) => ({ 6 | root: { 7 | display: 'flex', 8 | }, 9 | drawer: { 10 | [theme.breakpoints.up('sm')]: { 11 | width: drawerWidth, 12 | flexShrink: 0, 13 | }, 14 | }, 15 | menuButton: { 16 | marginRight: theme.spacing(2), 17 | [theme.breakpoints.up('sm')]: { 18 | display: 'none', 19 | }, 20 | }, 21 | // necessary for content to be below app bar 22 | toolbar: theme.mixins.toolbar, 23 | drawerPaper: { 24 | top: 80, 25 | width: drawerWidth, 26 | height: "calc(100% - 80px)", 27 | overflow: "none", 28 | overflowY: "auto", 29 | display: "block", 30 | }, 31 | content: { 32 | flexGrow: 1, 33 | backgroundColor: theme.palette.background.default, 34 | paddingTop: "85px", 35 | }, 36 | })); -------------------------------------------------------------------------------- /client/src/components/routes/signin/GoogleAuthButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {connect} from "react-redux"; 3 | import {Button, Icon} from "semantic-ui-react"; 4 | import {signInUsingOAuth} from "../../../actions" 5 | import log from 'loglevel'; 6 | 7 | class GoogleAuthButton extends React.Component { 8 | onSignInClick = () => { 9 | log.info(`[GoogleAuthButton] google button is clicked`) 10 | this.props.signInUsingOAuth(this.props.googleAuthReducer.oAuth) 11 | }; 12 | 13 | render() { 14 | log.info('[GoogleAuthButton] Rendering GoogleAuthButton Component') 15 | return ( 16 | 19 | ) 20 | } 21 | } 22 | 23 | const mapStateToProps = (state) => { 24 | return { 25 | googleAuthReducer: state.googleAuthReducer 26 | } 27 | } 28 | 29 | export default connect(mapStateToProps, {signInUsingOAuth})(GoogleAuthButton); -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/categories/PriceRangeCategory.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.categories; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.ujjaval.ecommerce.commondataservice.entity.sql.info.ProductInfo; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.Setter; 8 | import lombok.ToString; 9 | 10 | import javax.persistence.*; 11 | import java.io.Serializable; 12 | import java.util.List; 13 | 14 | @Getter 15 | @Setter 16 | @NoArgsConstructor 17 | @ToString 18 | @Entity 19 | public class PriceRangeCategory implements Serializable { 20 | @Id 21 | private int id; 22 | 23 | private String type; 24 | 25 | @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "priceRangeCategory") 26 | @JsonIgnore 27 | private List productInfos; 28 | 29 | public PriceRangeCategory(int id, String type) { 30 | this.id = id; 31 | this.type = type; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /client/src/styles/semanticUI/customStyles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import {Dimmer, Segment, Dropdown, Menu} from 'semantic-ui-react'; 3 | 4 | export const StyledSegment = styled(Segment)({ 5 | border: 'none !important', 6 | margin: '0 !important', 7 | padding: '0 !important', 8 | }); 9 | 10 | export const StyledDimmer = styled(Dimmer)({ 11 | padding: '0 !important', 12 | backgroundColor: 'rgba(0,0,0,0.2) !important', 13 | }); 14 | 15 | export const StyledSearchBarDimmer = styled(Dimmer)({ 16 | height: '100vh !important', 17 | }); 18 | 19 | export const StyledLargeDropdown = styled(Dropdown)({ 20 | width: "225px" 21 | }); 22 | 23 | export const StyledSmallMenu = styled(Menu)({ 24 | minHeight: "inherit !important", 25 | minWidth: "inherit !important", 26 | width: "inherit !important", 27 | }); 28 | 29 | export const StyledSmallDropdown = styled(Dropdown)({ 30 | width: "60px", 31 | height: "inherit !important", 32 | maxHeight: "17px !important", 33 | fontSize: "0.8rem", 34 | padding: "2px !important" 35 | }); -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/images/CarouselImages.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.images; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import javax.persistence.Entity; 9 | import javax.persistence.GeneratedValue; 10 | import javax.persistence.GenerationType; 11 | import javax.persistence.Id; 12 | import java.io.Serializable; 13 | 14 | @Getter 15 | @Setter 16 | @NoArgsConstructor 17 | @ToString 18 | @Entity 19 | public class CarouselImages implements Serializable { 20 | @Id 21 | @GeneratedValue(strategy= GenerationType.IDENTITY) 22 | private int id; 23 | 24 | private String link; 25 | 26 | private String imageLocalPath; 27 | 28 | private String imageURL; 29 | 30 | public CarouselImages(String link, String imageLocalPath, String imageURL) { 31 | this.link = link; 32 | this.imageLocalPath = imageLocalPath; 33 | this.imageURL = imageURL; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /client/src/logger/LoggerConfig.js: -------------------------------------------------------------------------------- 1 | import Logger from './Logger'; 2 | import {LoggerRegisterInfo} from './loggerTypes' 3 | 4 | class LoggerConfig { 5 | 6 | static loggerMap 7 | 8 | static enableAll() { 9 | Logger.globalLoggerLevel = Logger.Levels.ERROR 10 | } 11 | 12 | static enableAllWithSpecificLevel(level) { 13 | Logger.globalLoggerLevel = level 14 | } 15 | 16 | static disableAll() { 17 | Logger.globalLoggerLevel = Logger.Levels.DISABLE 18 | } 19 | 20 | static getLogger(id) { 21 | if (this.loggerMap.has(id)) { 22 | return this.loggerMap.get(id) 23 | } 24 | } 25 | 26 | static setLoggerMap() { 27 | if(!this.loggerMap) { 28 | this.loggerMap = new Map() 29 | } 30 | } 31 | 32 | static subscribeAllLoggers() { 33 | this.setLoggerMap() 34 | LoggerRegisterInfo.map(({id, level}) => { 35 | // console.log("Subscribing Logger id = " + id + ", Level = " + level) 36 | this.loggerMap.set(id, new Logger(level)) 37 | }) 38 | } 39 | } 40 | 41 | export default LoggerConfig; -------------------------------------------------------------------------------- /client/src/hooks/useClickAway.js: -------------------------------------------------------------------------------- 1 | import{ useEffect } from "react"; 2 | import log from "loglevel"; 3 | 4 | /** 5 | * Hook that alerts clicks outside of the passed ref 6 | */ 7 | export function useClickAway(ref, closeHandler) { 8 | useEffect(() => { 9 | /** 10 | * Alert if clicked on outside of element 11 | */ 12 | 13 | function handleClickOutside(event) { 14 | try { 15 | if (event.target.getAttribute("class") && 16 | event.target.getAttribute("class").localeCompare("MuiBackdrop-root") === 0) { 17 | closeHandler() 18 | } 19 | } catch (e) { 20 | log.error(`[useClickAway] event.target.getAttribute("class") is empty`) 21 | } 22 | } 23 | 24 | // Bind the event listener 25 | document.addEventListener("mousedown", handleClickOutside); 26 | return () => { 27 | // Unbind the event listener on clean up 28 | document.removeEventListener("mousedown", handleClickOutside); 29 | }; 30 | 31 | // eslint-disable-next-line 32 | }, [ref]); 33 | } -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/info/ContactInfo.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.info; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | import javax.persistence.*; 10 | import java.util.List; 11 | 12 | @Getter 13 | @Setter 14 | @NoArgsConstructor 15 | @ToString 16 | @Entity 17 | public class ContactInfo { 18 | 19 | @Id 20 | @GeneratedValue(strategy= GenerationType.IDENTITY) 21 | private int id; 22 | 23 | private String email; 24 | 25 | private String office; 26 | 27 | private String mobile; 28 | 29 | private String other; 30 | 31 | @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "contactInfo") 32 | @JsonIgnore 33 | private List banks; 34 | 35 | public ContactInfo(String email, String office, String mobile, String other) { 36 | this.email = email; 37 | this.office = office; 38 | this.mobile = mobile; 39 | this.other = other; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/model/MainScreenResponse.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.model; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.dto.BrandImagesDTO; 4 | import com.ujjaval.ecommerce.commondataservice.dto.ApparelImagesDTO; 5 | import com.ujjaval.ecommerce.commondataservice.entity.sql.images.CarouselImages; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | import lombok.ToString; 10 | 11 | import java.io.Serializable; 12 | import java.util.List; 13 | 14 | @Getter 15 | @Setter 16 | @NoArgsConstructor 17 | @ToString 18 | public class MainScreenResponse implements Serializable { 19 | 20 | private List brands; 21 | private List apparels; 22 | private List carousels; 23 | 24 | public MainScreenResponse(List brands, 25 | List apparels, 26 | List carousels) { 27 | this.brands = brands; 28 | this.apparels = apparels; 29 | this.carousels = carousels; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/images/BrandImages.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.images; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.ProductBrandCategory; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | import javax.persistence.*; 10 | 11 | @Getter 12 | @Setter 13 | @NoArgsConstructor 14 | @ToString 15 | @Entity 16 | public class BrandImages { 17 | @Id 18 | @GeneratedValue(strategy= GenerationType.IDENTITY) 19 | private int id; 20 | 21 | private String title; 22 | 23 | private String imageLocalPath; 24 | 25 | private String imageURL; 26 | 27 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 28 | @JoinColumn(name = "brand_id", referencedColumnName = "id") 29 | private ProductBrandCategory productBrandCategory; 30 | 31 | public BrandImages(String title, String imageLocalPath, String imageURL) { 32 | this.title = title; 33 | this.imageLocalPath = imageLocalPath; 34 | this.imageURL = imageURL; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/service/interfaces/CommonDataService.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.service.interfaces; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.dto.ProductInfoDTO; 4 | import com.ujjaval.ecommerce.commondataservice.entity.sql.info.ProductInfo; 5 | import com.ujjaval.ecommerce.commondataservice.model.FilterAttributesResponse; 6 | import com.ujjaval.ecommerce.commondataservice.model.HomeTabsDataResponse; 7 | import com.ujjaval.ecommerce.commondataservice.model.MainScreenResponse; 8 | import com.ujjaval.ecommerce.commondataservice.model.SearchSuggestionResponse; 9 | 10 | import java.util.HashMap; 11 | import java.util.List; 12 | 13 | public interface CommonDataService { 14 | 15 | MainScreenResponse getHomeScreenData(String apiName); 16 | 17 | FilterAttributesResponse getFilterAttributesByProducts(String queryParams); 18 | 19 | ProductInfoDTO getProductsByCategories(String queryParams); 20 | 21 | HashMap getProductsById(String queryParams); 22 | 23 | HomeTabsDataResponse getBrandsAndApparelsByGender(String apiName); 24 | 25 | SearchSuggestionResponse getSearchSuggestionList(); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /client/src/components/ui/breadcrumbs.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Typography from '@material-ui/core/Typography'; 3 | import Breadcrumbs from '@material-ui/core/Breadcrumbs'; 4 | import {Link} from "react-router-dom"; 5 | import log from 'loglevel'; 6 | 7 | export default function BreadcrumbsSection(props) { 8 | const renderLinks = () => { 9 | log.info(`[BreadcrumbsSection] props.linkList = ${props.linkList}`) 10 | // we dont need link for the active page breadcrumb 11 | // eslint-disable-next-line array-callback-return 12 | return props.linkList.splice(0, props.linkList.length-1).map(({name, link}) => { 13 | if(link.length > 0) { 14 | return ( 15 | 16 | {name} 17 | 18 | ) 19 | } 20 | }) 21 | } 22 | 23 | log.info(`[BreadcrumbsSection] Rendering BreadcrumbsSection Component`) 24 | 25 | return ( 26 | 27 | {renderLinks()} 28 | {props.linkList[props.linkList.length - 1].name} 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/categories/GenderCategory.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.categories; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.ujjaval.ecommerce.commondataservice.entity.sql.info.ProductInfo; 5 | import com.ujjaval.ecommerce.commondataservice.entity.sql.images.ApparelImages; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | import lombok.ToString; 10 | 11 | import javax.persistence.*; 12 | import java.io.Serializable; 13 | import java.util.List; 14 | 15 | @Getter 16 | @Setter 17 | @NoArgsConstructor 18 | @ToString 19 | @Entity 20 | public class GenderCategory implements Serializable { 21 | @Id 22 | private int id; 23 | 24 | private String type; 25 | 26 | @OneToMany(mappedBy = "genderCategory") 27 | @JsonIgnore 28 | private List productInfos; 29 | 30 | @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "genderCategory") 31 | @JsonIgnore 32 | private List apparelImages; 33 | 34 | public GenderCategory(int id, String type) { 35 | this.id = id; 36 | this.type = type; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/service/CustomUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.service; 2 | 3 | import com.ujjaval.ecommerce.authenticationservice.entity.UserInfo; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.security.core.userdetails.User; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | import org.springframework.security.core.userdetails.UserDetailsService; 8 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.Arrays; 12 | 13 | @Service 14 | public class CustomUserDetailsService implements UserDetailsService { 15 | 16 | @Autowired 17 | private AuthDataService authDataService; 18 | 19 | @Override 20 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 21 | UserInfo userInfo = authDataService.findByUsername(username); 22 | System.out.println("Username = " + userInfo.getUsername() + ", Password = " + userInfo.getPassword()); 23 | return new User(userInfo.getUsername(), userInfo.getPassword(), Arrays.asList()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/model/SearchSuggestionResponse.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.model; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.dto.SearchSuggestionForThreeAttrDTO; 4 | import com.ujjaval.ecommerce.commondataservice.dto.SearchSuggestionForTwoAttrDTO; 5 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.ApparelCategory; 6 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.GenderCategory; 7 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.ProductBrandCategory; 8 | import lombok.*; 9 | 10 | import java.io.Serializable; 11 | import java.util.List; 12 | 13 | @Getter 14 | @Setter 15 | @AllArgsConstructor 16 | @ToString 17 | public class SearchSuggestionResponse implements Serializable { 18 | List genderKeywords; 19 | List brandKeywords; 20 | List apparelKeywords; 21 | List genderApparelKeywords; 22 | List genderBrandKeywords; 23 | List apparelBrandKeywords; 24 | List threeAttrKeywords; 25 | List productKeywords; 26 | } 27 | -------------------------------------------------------------------------------- /client/src/components/routes/cancelPayment.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import log from 'loglevel' 3 | import {Grid} from "@material-ui/core"; 4 | import {Link} from "react-router-dom"; 5 | import {CHECKOUT_ROUTE} from "../../constants/react_routes"; 6 | import {DocumentTitle} from "../ui/documentTitle"; 7 | 8 | export const CancelPayment = () => { 9 | 10 | log.info('[CancelPayment] Rendering SuccessPayment Component') 11 | return ( 12 | 14 | 15 | 16 | 17 | 19 | Payment Cancelled. Sorry your payment is declined. 20 | 21 | 22 | Try again later or use different payment method. 23 | 24 | 25 | 26 | Go back to Checkout. 27 | 28 | 29 | ) 30 | } -------------------------------------------------------------------------------- /server/search-suggestion-service/src/main/java/com/ujjaval/ecommerce/searchsuggestionservice/util/Permutation.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.searchsuggestionservice.util; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | 9 | @Getter 10 | @Setter 11 | public class Permutation { 12 | private List output; 13 | 14 | public Permutation(String[] input) { 15 | if(input.length == 0 ) { 16 | return; 17 | } 18 | output = new LinkedList<>(); 19 | permute(input, 0, input.length - 1); 20 | } 21 | 22 | public void permute(String[] input, int l, int r) 23 | { 24 | if (l == r) { 25 | output.add(String.join(" ", input)); 26 | } 27 | else 28 | { 29 | for (int i = l; i <= r; i++) 30 | { 31 | input = swap(input,l,i); 32 | permute(input, l+1, r); 33 | input = swap(input,l,i); 34 | } 35 | } 36 | } 37 | 38 | private String[] swap(String[] stringArr, int i, int j) 39 | { 40 | String temp = stringArr[i] ; 41 | stringArr[i] = stringArr[j]; 42 | stringArr[j] = temp; 43 | return stringArr; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/categories/ApparelCategory.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.categories; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.ujjaval.ecommerce.commondataservice.entity.sql.info.ProductInfo; 5 | import com.ujjaval.ecommerce.commondataservice.entity.sql.images.ApparelImages; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | import lombok.ToString; 10 | 11 | import javax.persistence.*; 12 | import java.io.Serializable; 13 | import java.util.List; 14 | 15 | @Getter 16 | @Setter 17 | @NoArgsConstructor 18 | @ToString 19 | @Entity 20 | public class ApparelCategory implements Serializable { 21 | @Id 22 | @GeneratedValue(strategy= GenerationType.IDENTITY) 23 | private int id; 24 | 25 | private String type; 26 | 27 | @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "apparelCategory") 28 | @JsonIgnore 29 | private List productInfos; 30 | 31 | @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "apparelCategory") 32 | @JsonIgnore 33 | private List apparelImages; 34 | 35 | public ApparelCategory(String type) { 36 | this.type = type; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/categories/ProductBrandCategory.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.categories; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.ujjaval.ecommerce.commondataservice.entity.sql.info.ProductInfo; 5 | import com.ujjaval.ecommerce.commondataservice.entity.sql.images.BrandImages; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | import lombok.ToString; 10 | 11 | import javax.persistence.*; 12 | import java.io.Serializable; 13 | import java.util.List; 14 | 15 | @Getter 16 | @Setter 17 | @NoArgsConstructor 18 | @ToString 19 | @Entity 20 | public class ProductBrandCategory implements Serializable { 21 | @Id 22 | @GeneratedValue(strategy= GenerationType.IDENTITY) 23 | private int id; 24 | 25 | private String type; 26 | 27 | @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "productBrandCategory") 28 | @JsonIgnore 29 | private List productInfos; 30 | 31 | @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "productBrandCategory") 32 | @JsonIgnore 33 | private List brandImages; 34 | 35 | public ProductBrandCategory(String type) { 36 | this.type = type; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /client/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './components/app'; 4 | import '../src/styles/index.css' 5 | 6 | import reducers from './reducers'; 7 | import {Provider} from "react-redux"; 8 | import {createStore, applyMiddleware, compose} from "redux"; 9 | import thunk from "redux-thunk"; 10 | import 'semantic-ui-css/semantic.min.css' 11 | import '../src/styles/library/swiper/swiper.css'; 12 | import '../src/styles/library/swiper/swiper.min.css'; 13 | import log from 'loglevel'; 14 | import ErrorBoundary from "./ErrorBoundary"; 15 | 16 | let composeEnhancers 17 | 18 | // enable logs & redux only in production. 19 | if (process.env.REACT_APP_ENVIRONMENT === "dev") { 20 | 21 | // by default set the level to info 22 | log.setLevel("info") 23 | composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose(); 24 | } else { 25 | console.log = console.error = console.warn = function () {} 26 | log.disableAll(true) 27 | composeEnhancers = compose(); 28 | } 29 | 30 | 31 | const store = createStore( 32 | reducers, 33 | composeEnhancers(applyMiddleware(thunk)) 34 | ); 35 | 36 | ReactDOM.render( 37 | 38 | 39 | 40 | 41 | , 42 | document.getElementById('root') 43 | ); -------------------------------------------------------------------------------- /client/src/components/ui/reduxTextField.js: -------------------------------------------------------------------------------- 1 | import {TextField} from "@material-ui/core"; 2 | import InputAdornment from "@material-ui/core/InputAdornment"; 3 | import React from "react"; 4 | 5 | const textFieldStyles = { 6 | width: "100%", 7 | height: "fit-content", 8 | marginTop: "20px" 9 | } 10 | 11 | export const renderReduxTextField = ( 12 | {placeholder, icon, type, shrink, selectField, input, label, meta: {touched, error}, ...custom}) => { 13 | 14 | let errorExist = touched && error && error !== ""; 15 | return ( 16 | 32 | {icon} 33 | 34 | ) 35 | } : null 36 | } 37 | {...input} 38 | {...custom} 39 | /> 40 | ); 41 | } -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/info/AddressInfo.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.info; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import lombok.ToString; 8 | 9 | import javax.persistence.*; 10 | import java.util.List; 11 | 12 | @Getter 13 | @Setter 14 | @NoArgsConstructor 15 | @ToString 16 | @Entity 17 | public class AddressInfo { 18 | 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.IDENTITY) 21 | private int id; 22 | 23 | private String firstLine; 24 | 25 | private String secondLine; 26 | 27 | private String zipCode; 28 | 29 | private String state; 30 | 31 | private String country; 32 | 33 | @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "addressInfo") 34 | @JsonIgnore 35 | private List banks; 36 | 37 | @OneToOne(mappedBy = "addressInfo") 38 | private OrderInfo order; 39 | 40 | public AddressInfo(String firstLine, String secondLine, String zipCode, String state, String country) { 41 | this.firstLine = firstLine; 42 | this.secondLine = secondLine; 43 | this.zipCode = zipCode; 44 | this.state = state; 45 | this.country = country; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/java/com/ujjaval/ecommerce/selleraccountservice/controller/SellerAccountController.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.selleraccountservice.controller; 2 | 3 | import com.ujjaval.ecommerce.selleraccountservice.entity.nosql.SellerBulkInfo; 4 | import com.ujjaval.ecommerce.selleraccountservice.entity.sql.SellerInfo; 5 | import com.ujjaval.ecommerce.selleraccountservice.service.SellerAccountDataService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | @RestController 12 | public class SellerAccountController { 13 | 14 | @Autowired 15 | private SellerAccountDataService sellerAccountDataService; 16 | 17 | @GetMapping("/save") 18 | public void saveAddress() { 19 | sellerAccountDataService.save(); 20 | } 21 | 22 | @GetMapping("/seller/{id}") 23 | public SellerInfo getAddress(@PathVariable int id) { 24 | return sellerAccountDataService.findSellerById(id); 25 | } 26 | 27 | @GetMapping("/seller-bulk/{id}") 28 | public SellerBulkInfo getAddress() { 29 | sellerAccountDataService.saveInMongo(); 30 | return sellerAccountDataService.findMongoAddressById(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/model/FilterAttributesResponse.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.model; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.dto.FilterAttributesWithTotalItemsDTO; 4 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.SortByCategory; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.Setter; 8 | import lombok.ToString; 9 | 10 | import java.io.Serializable; 11 | import java.util.List; 12 | 13 | @Getter 14 | @Setter 15 | @NoArgsConstructor 16 | @ToString 17 | public class FilterAttributesResponse implements Serializable { 18 | 19 | private List brands; 20 | private List genders; 21 | private List apparels; 22 | private List sortby; 23 | private List prices; 24 | 25 | public FilterAttributesResponse(List brands, List genders, 26 | List apparels, List prices) { 27 | this.brands = brands; 28 | this.genders = genders; 29 | this.apparels = apparels; 30 | this.prices = prices; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/info/OrderInfo.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.info; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import javax.persistence.*; 9 | import java.io.Serializable; 10 | 11 | @Getter 12 | @Setter 13 | @NoArgsConstructor 14 | @ToString 15 | @Entity 16 | public class OrderInfo implements Serializable { 17 | 18 | @Id 19 | @GeneratedValue(strategy= GenerationType.IDENTITY) 20 | private int id; 21 | 22 | private int customerId; 23 | 24 | private String timestamp; 25 | 26 | private String deliveryStatus; 27 | 28 | private String trackPackageLink; 29 | 30 | @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 31 | @JoinColumn(name = "address_id", referencedColumnName = "id") 32 | private AddressInfo addressInfo; 33 | 34 | @ManyToOne(fetch = FetchType.LAZY) 35 | @JoinColumn(name = "product_id") 36 | private OrderInfo orderInfo; 37 | 38 | public OrderInfo(int customerId, String timestamp, String deliveryStatus, String trackPackageLink, OrderInfo orderInfo) { 39 | this.customerId = customerId; 40 | this.timestamp = timestamp; 41 | this.deliveryStatus = deliveryStatus; 42 | this.trackPackageLink = trackPackageLink; 43 | this.orderInfo = orderInfo; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /client/src/constants/stateCodes.js: -------------------------------------------------------------------------------- 1 | export const stateCodes = { 2 | "AL": "Alabama", 3 | "AK": "Alaska", 4 | "AZ": "Arizona", 5 | "AR": "Arkansas", 6 | "CA": "California", 7 | "CO": "Colorado", 8 | "CT": "Connecticut", 9 | "DE": "Delaware", 10 | "DC": "District of Columbia", 11 | "FL": "Florida", 12 | "GA": "Georgia", 13 | "HI": "Hawaii", 14 | "ID": "Idaho", 15 | "IL": "Illinois", 16 | "IN": "Indiana", 17 | "IA": "Iowa", 18 | "KS": "Kansas", 19 | "KY": "Kentucky", 20 | "LA": "Louisiana", 21 | "ME": "Maine", 22 | "MD": "Maryland", 23 | "MA": "Massachusetts", 24 | "MI": "Michigan", 25 | "MN": "Minnesota", 26 | "MS": "Mississippi", 27 | "MO": "Missouri", 28 | "MT": "Montana", 29 | "NE": "Nebraska", 30 | "NV": "Nevada", 31 | "NH": "New Hampshire", 32 | "NJ": "New Jersey", 33 | "NM": "New Mexico", 34 | "NY": "New York", 35 | "NC": "North Carolina", 36 | "ND": "North Dakota", 37 | "OH": "Ohio", 38 | "OK": "Oklahoma", 39 | "OR": "Oregon", 40 | "PA": "Pennsylvania", 41 | "PR": "Puerto Rico", 42 | "RI": "Rhode Island", 43 | "SC": "South Carolina", 44 | "SD": "South Dakota", 45 | "TN": "Tennessee", 46 | "TX": "Texas", 47 | "UT": "Utah", 48 | "VT": "Vermont", 49 | "VA": "Virginia", 50 | "WA": "Washington", 51 | "WV": "West Virginia", 52 | "WI": "Wisconsin", 53 | "WY": "Wyoming" 54 | } -------------------------------------------------------------------------------- /client/src/components/routes/home/homeMenuIcons.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Grid from '@material-ui/core/Grid'; 3 | import {Link} from "react-router-dom"; 4 | import log from 'loglevel'; 5 | import {MAX_PRODUCTS_PER_PAGE} from "../../../constants/constants"; 6 | import {useSelector} from "react-redux"; 7 | 8 | const HomeMenuIcons = () => { 9 | const homeAPIData = useSelector(state => state.homePageDataReducer) 10 | 11 | const renderImageList = (imageList) => { 12 | 13 | // filter out images which are related to home icons. 14 | imageList = imageList.filter(image => image.imageLocalPath.search("icon") !== -1) 15 | 16 | // map the image path and link 17 | return imageList.map(info => { 18 | return ( 19 | 20 | 21 | {info.imageLocalPath} 23 | 24 | 25 | ) 26 | }); 27 | }; 28 | 29 | log.info("[HomeMenuIcons]: Rendering HomeMenuIcons Component") 30 | 31 | return ( 32 | 33 | {renderImageList(homeAPIData.data.carousels)} 34 | 35 | ) 36 | }; 37 | export default HomeMenuIcons; -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/info/BankInfo.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.info; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import javax.persistence.*; 9 | 10 | @Getter 11 | @Setter 12 | @NoArgsConstructor 13 | @ToString 14 | @Entity 15 | public class BankInfo { 16 | 17 | @Id 18 | @GeneratedValue(strategy = GenerationType.IDENTITY) 19 | private int id; 20 | 21 | private int customerId; 22 | 23 | private int sellerId; 24 | 25 | private String firstName; 26 | 27 | private String lastName; 28 | 29 | private String bankName; 30 | 31 | private String routingNumber; 32 | 33 | private String accountNumber; 34 | 35 | @ManyToOne 36 | @JoinColumn(name = "address_id") 37 | private AddressInfo addressInfo; 38 | 39 | @ManyToOne 40 | @JoinColumn(name = "contact_id") 41 | private ContactInfo contactInfo; 42 | 43 | public BankInfo(int customerId, int sellerId, String firstName, String lastName, String bankName, String routingNumber, String accountNumber) { 44 | this.customerId = customerId; 45 | this.sellerId = sellerId; 46 | this.firstName = firstName; 47 | this.lastName = lastName; 48 | this.bankName = bankName; 49 | this.routingNumber = routingNumber; 50 | this.accountNumber = accountNumber; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /server/seller-account-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=seller-account-service 2 | server.port=7500 3 | spring.datasource.url=jdbc:mysql://localhost:3306/ecommerce_data?useSSL=false&serverTimezone=UTC 4 | spring.datasource.username=springstudent 5 | spring.datasource.password=springstudent 6 | #spring.datasource.url=jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:6603}/${DB_SCHEMA}?autoReconnect=true&failOverReadOnly=false&maxReconnects=2 7 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 8 | #spring.data.mongodb.uri=mongodb://0.0.0.0:27017/ecommerce_data 9 | #spring.data.mongodb.uri=mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test 10 | spring.data.mongodb.host=0.0.0.0 11 | spring.data.mongodb.port=27017 12 | spring.data.mongodb.database=ecommerce_data 13 | spring.data.mongodb.username=springstudent 14 | spring.data.mongodb.password=springstudent 15 | #spring.datasource.initialization-mode=always 16 | #spring.jpa.hibernate.ddl-auto=create-drop 17 | spring.jpa.generate-ddl=true 18 | spring.profiles.active=dev 19 | 20 | # debugging purpose 21 | spring.jpa.properties.hibernate.format_sql=true 22 | logging.level.org.hibernate.SQL=DEBUG 23 | logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE 24 | logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG 25 | logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE 26 | logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/entity/sql/images/ApparelImages.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.entity.sql.images; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.ApparelCategory; 5 | import com.ujjaval.ecommerce.commondataservice.entity.sql.categories.GenderCategory; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | import lombok.ToString; 10 | 11 | import javax.persistence.*; 12 | 13 | @Getter 14 | @Setter 15 | @NoArgsConstructor 16 | @ToString 17 | @Entity 18 | public class ApparelImages { 19 | @Id 20 | @GeneratedValue(strategy= GenerationType.IDENTITY) 21 | private int id; 22 | 23 | private String title; 24 | 25 | private String imageLocalPath; 26 | 27 | private String imageURL; 28 | 29 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 30 | @JoinColumn(name = "apparel_id", referencedColumnName = "id") 31 | @JsonIgnore 32 | private ApparelCategory apparelCategory; 33 | 34 | @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 35 | @JoinColumn(name = "gender_id") 36 | @JsonIgnore 37 | private GenderCategory genderCategory; 38 | 39 | public ApparelImages(String title, String imageLocalPath, String imageURL) { 40 | this.title = title; 41 | this.imageLocalPath = imageLocalPath; 42 | this.imageURL = imageURL; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /client/src/components/routes/product/filterSideNavbar/checkboxSearchBar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import log from 'loglevel'; 3 | import {NavBarHeader} from "../../../ui/headers"; 4 | import {Grid} from "@material-ui/core"; 5 | import CollapsableSearch from "../../../ui/collapsableSearch"; 6 | 7 | export default function CheckboxSearchBar(props) { 8 | 9 | if (!props.checkboxList) { 10 | log.debug(`[CheckboxSearchBar] apparelList is null`) 11 | return null 12 | } 13 | 14 | const handleSearchBarChange = value => { 15 | log.info(`[CheckboxSearchBar] handleSearchClick value = ${value}`) 16 | let filterApparelList = props.checkboxList.filter(info => info.value.toUpperCase().startsWith(value.toUpperCase())) 17 | props.searchListHandler(filterApparelList) 18 | } 19 | 20 | const handleSearchBarCancel = () => { 21 | props.searchListHandler(null) 22 | } 23 | 24 | log.info(`[CheckboxSearchBar] Rendering CheckboxSearchBar Component`) 25 | 26 | return ( 27 | 28 | 29 | 30 | 31 | 36 | 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /client/src/constants/constants.js: -------------------------------------------------------------------------------- 1 | 2 | export const MAX_PRODUCTS_PER_PAGE = 16; 3 | 4 | export const TAB_CONFIG = [ 5 | {index: 0, label: 'MEN', color: '#ee5f73', mapKey: "men"}, 6 | {index: 1, label: 'WOMEN', color: '#fb56c1', mapKey: "women"}, 7 | {index: 2, label: 'KIDS', color: '#f26a10', mapKey: "boys"}, 8 | {index: 3, label: 'ESSENTIALS', color: '#0db7af', mapKey: "essentials"}, 9 | {index: 4, label: 'HOME & LIVING', color: '#f2c210', mapKey: "homeAndLiving"}, 10 | ]; 11 | 12 | export const INITIAL_PAGINATION_STATE = { 13 | pageNumber: 1, 14 | maxProducts: MAX_PRODUCTS_PER_PAGE, 15 | isLoadedFromURL: true 16 | } 17 | 18 | export const INITIAL_SORT_STATE = { 19 | id: 1, 20 | value: null, 21 | isLoadedFromURL: true 22 | } 23 | 24 | export const INITIAL_SELECTED_FILTER_ATTRIBUTE_STATE = { 25 | genders: [], 26 | apparels: [], 27 | brands: [], 28 | prices: [], 29 | oldQuery: null, 30 | newQuery: null 31 | } 32 | 33 | export const INITIAL_SHIPPING_OPTION_STATE = { 34 | price: "Free", 35 | submitted: false 36 | } 37 | 38 | export const INITIAL_SHIPPING_ADDRESS_STATE = { 39 | values: null, 40 | submitted: false 41 | } 42 | 43 | export const FILTER_ATTRIBUTES = ["genders", "apparels", "brands", "prices"] 44 | export const SORT_ATTRIBUTE = "sortby" 45 | export const PAGE_ATTRIBUTE = "page" 46 | 47 | export const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 48 | 'August', 'September', 'October', 'November', 'December']; 49 | 50 | export const HOME_PAGE_API_OBJECT_LEN = 3; 51 | export const TABS_API_OBJECT_LEN = 6; 52 | -------------------------------------------------------------------------------- /server/search-suggestion-service/src/main/java/com/ujjaval/ecommerce/searchsuggestionservice/controller/SearchSuggestionController.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.searchsuggestionservice.controller; 2 | 3 | import com.ujjaval.ecommerce.searchsuggestionservice.dto.SearchSuggestionKeywordInfo; 4 | import com.ujjaval.ecommerce.searchsuggestionservice.service.SearchSuggestionService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.core.env.Environment; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RequestParam; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | import java.util.*; 13 | 14 | @RestController 15 | public class SearchSuggestionController { 16 | 17 | @Autowired 18 | SearchSuggestionService searchSuggestionService; 19 | 20 | @Autowired 21 | Environment environment; 22 | 23 | public void loadSearchSuggestions() { 24 | searchSuggestionService.loadSearchSuggestionToMap(); 25 | } 26 | 27 | @GetMapping("/search-suggestion") 28 | public ResponseEntity searchKeyword(@RequestParam String q) { 29 | return ResponseEntity.ok(searchSuggestionService.searchKeywordFromMap(q)); 30 | } 31 | 32 | @GetMapping("/default-search-suggestion") 33 | public ResponseEntity defaultSearchSuggestions() { 34 | List resultList 35 | = searchSuggestionService.getDefaultSearchSuggestions(); 36 | return ResponseEntity.ok(resultList); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /client/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import {combineReducers} from "redux"; 2 | import {reducer as formReducer} from "redux-form"; 3 | 4 | import { 5 | homePageDataReducer, addToCartReducer, 6 | selectProductDetailReducer, shoppingBagProductReducer, 7 | filterProductsReducer, filterAttributesReducer, 8 | filterQueryReducer, tabsDataReducer, 9 | cartTotalReducer, savedSortedListReducer, 10 | shippingAddressReducer, paymentInfoReducer, 11 | shippingOptionReducer, deliveryChargesReducer, 12 | paymentResponseReducer, signInReducer, signUpReducer, 13 | googleAuthReducer, searchKeywordReducer 14 | } from "./screens/commonScreenReducer"; 15 | 16 | import {tabHoverEventReducer} from "./events/eventReducer"; 17 | 18 | import { 19 | selectedFilterAttributesReducer, 20 | selectSortReducer, selectPageReducer, clearFiltersReducer 21 | } from "./screens/filter/selectedFilterAttributesReducer" 22 | 23 | export default combineReducers({ 24 | form: formReducer, 25 | signInReducer, 26 | signUpReducer, 27 | homePageDataReducer, 28 | addToCartReducer, 29 | tabHoverEventReducer, 30 | filterProductsReducer, 31 | filterAttributesReducer, 32 | selectSortReducer, 33 | selectPageReducer, 34 | selectProductDetailReducer, 35 | shoppingBagProductReducer, 36 | filterQueryReducer, 37 | selectedFilterAttributesReducer, 38 | tabsDataReducer, 39 | cartTotalReducer, 40 | savedSortedListReducer, 41 | shippingAddressReducer, 42 | paymentInfoReducer, 43 | shippingOptionReducer, 44 | deliveryChargesReducer, 45 | paymentResponseReducer, 46 | googleAuthReducer, 47 | searchKeywordReducer, 48 | clearFiltersReducer 49 | }); -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/dao/sql/info/ProductInfoRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.dao.sql.info; 2 | 3 | import com.ujjaval.ecommerce.commondataservice.dto.SearchSuggestionForThreeAttrDTO; 4 | import com.ujjaval.ecommerce.commondataservice.dto.SearchSuggestionForTwoAttrDTO; 5 | import com.ujjaval.ecommerce.commondataservice.entity.sql.info.ProductInfo; 6 | import com.ujjaval.ecommerce.commondataservice.model.FilterAttributesResponse; 7 | import com.ujjaval.ecommerce.commondataservice.model.HomeTabsDataResponse; 8 | import org.javatuples.Pair; 9 | import org.springframework.data.jpa.repository.JpaRepository; 10 | import org.springframework.data.jpa.repository.Query; 11 | 12 | import java.util.HashMap; 13 | import java.util.List; 14 | 15 | public interface ProductInfoRepository extends JpaRepository { 16 | 17 | Pair> getProductsByCategories(HashMap conditionMap); 18 | 19 | List getProductsById(String[] productIds); 20 | 21 | FilterAttributesResponse getFilterAttributesByProducts(HashMap conditionMap); 22 | 23 | HomeTabsDataResponse getBrandsAndApparelsByGender(); 24 | 25 | List getGenderApparelBrandByIdAndName(); 26 | 27 | List getGenderAndApparelByIdAndName(); 28 | 29 | List getGenderAndBrandByIdAndName(); 30 | 31 | List getApparelAndBrandByIdAndName(); 32 | 33 | @Query(value = "SELECT DISTINCT p.name FROM ProductInfo p") 34 | List getProductByName(); 35 | } 36 | -------------------------------------------------------------------------------- /client/src/components/routes/product/filterSideNavbar/clearAllButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import log from 'loglevel'; 3 | import {useDispatch, useSelector} from "react-redux"; 4 | import {CLEAR_ALL_FILTERS, RESET_SELECTED_CATEGORY} from "../../../../actions/types"; 5 | import history from "../../../../history"; 6 | 7 | function ClearAllButton() { 8 | const dispatch = useDispatch() 9 | const selectedFilterAttribute = useSelector(state => state.selectedFilterAttributesReducer) 10 | 11 | // check if any filter is selected or not 12 | if ((selectedFilterAttribute.genders.length + selectedFilterAttribute.apparels.length 13 | + selectedFilterAttribute.brands.length + selectedFilterAttribute.prices.length) === 0) { 14 | log.info(`[ClearAllButton] selected attribute are null`) 15 | return null 16 | } 17 | 18 | /** 19 | * remove all selected filters 20 | */ 21 | const handleClearAllClick = () => { 22 | log.info(`[ClearAllButton] handleClearAllClick(value)`) 23 | dispatch({ 24 | type: RESET_SELECTED_CATEGORY 25 | }) 26 | dispatch({ 27 | type: CLEAR_ALL_FILTERS, 28 | payload: true 29 | }) 30 | history.push(history.location.pathname + "?q=page=0,16") 31 | } 32 | 33 | log.info(`[ClearAllButton] Rendering ClearAllButton Component`) 34 | 35 | return ( 36 | <> 37 |
CLEAR ALL 41 |
42 | 43 | ); 44 | } 45 | 46 | export default ClearAllButton; -------------------------------------------------------------------------------- /client/src/components/ui/modal.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {makeStyles} from '@material-ui/core/styles'; 3 | import Modal from '@material-ui/core/Modal'; 4 | import {Fade} from '@material-ui/core'; 5 | import Backdrop from '@material-ui/core/Backdrop'; 6 | 7 | const useStyles = makeStyles((theme) => ({ 8 | modal: { 9 | display: 'flex', 10 | alignItems: 'center', 11 | justifyContent: 'center', 12 | }, 13 | paper: { 14 | backgroundColor: theme.palette.background.paper, 15 | boxShadow: theme.shadows[6], 16 | height: "fit-content", 17 | borderRadius: 4 18 | }, 19 | })); 20 | 21 | export default function ModalSection(props) { 22 | const classes = useStyles(); 23 | const [open, setOpen] = React.useState(true); 24 | 25 | const handleClose = () => { 26 | props.closeHandler(); 27 | setOpen(false); 28 | }; 29 | 30 | return ( 31 |
32 | 45 | 46 |
47 | {props.renderWarningComponent} 48 |
49 |
50 |
51 |
52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /server/payment-service/src/main/java/com/ujjaval/ecommerce/paymentservice/config/CORSFilter.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.paymentservice.config; 2 | 3 | import java.io.IOException; 4 | import javax.servlet.Filter; 5 | import javax.servlet.FilterChain; 6 | import javax.servlet.FilterConfig; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.ServletRequest; 9 | import javax.servlet.ServletResponse; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.stereotype.Component; 15 | 16 | @Component 17 | public class CORSFilter implements Filter { 18 | 19 | private final Logger log = LoggerFactory.getLogger(CORSFilter.class); 20 | 21 | public CORSFilter() { 22 | log.info("CORSFilter init"); 23 | } 24 | 25 | @Override 26 | public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 27 | 28 | HttpServletRequest request = (HttpServletRequest) req; 29 | HttpServletResponse response = (HttpServletResponse) res; 30 | 31 | response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); 32 | response.setHeader("Access-Control-Allow-Credentials", "true"); 33 | response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); 34 | response.setHeader("Access-Control-Max-Age", "3600"); 35 | response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With"); 36 | 37 | chain.doFilter(req, res); 38 | } 39 | 40 | @Override 41 | public void init(FilterConfig filterConfig) { 42 | } 43 | 44 | @Override 45 | public void destroy() { 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /client/src/components/routes/product/filterDropdown.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect, useState} from 'react'; 2 | import log from 'loglevel'; 3 | import {useSelector} from "react-redux"; 4 | import DropdownSection from "../../ui/dropDown"; 5 | import {SORT_ATTRIBUTE} from "../../../constants/constants"; 6 | import history from "../../../history"; 7 | 8 | export default function FilterDropdown() { 9 | const sortList = useSelector(state => state.filterAttributesReducer.data ? 10 | state.filterAttributesReducer.data[SORT_ATTRIBUTE] : null) 11 | const selectedSort = useSelector(state => state.selectSortReducer) 12 | const [sortValue, setSortValue] = useState({id:1, value: ""}) 13 | 14 | useEffect(() => { 15 | if (selectedSort != null) { 16 | setSortValue(selectedSort) 17 | } 18 | }, [selectedSort]) 19 | 20 | if (!sortList) { 21 | return null 22 | } 23 | 24 | const onChangeHandler = (id, value) => { 25 | log.info(`[FilterDropdown] onChangeHandler id = ${id}, value = ${value}`) 26 | setSortValue({id, value}) 27 | let route = history.location.pathname 28 | let queryStr = history.location.search 29 | if (history.location.search.search("sortby") === -1) { 30 | history.push(`${route}${queryStr}::sortby=${id}`) 31 | } else { 32 | history.push(`${route}${queryStr.replace(new RegExp(`sortby=[0-9]`), `sortby=${id}`)}`) 33 | } 34 | } 35 | 36 | log.info(`[FilterDropdown] Rendering FilterDropdown Component`) 37 | 38 | return ( 39 | 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/config/DevRedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.context.annotation.Profile; 7 | import org.springframework.core.env.Environment; 8 | import org.springframework.data.redis.connection.RedisPassword; 9 | import org.springframework.data.redis.connection.RedisStandaloneConfiguration; 10 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 11 | import org.springframework.data.redis.core.RedisTemplate; 12 | 13 | import java.util.Objects; 14 | 15 | @Configuration 16 | @Profile("dev") 17 | public class DevRedisConfig { 18 | 19 | @Autowired 20 | Environment environment; 21 | 22 | @Bean 23 | JedisConnectionFactory jedisConnectionFactory() { 24 | System.out.println("Loading Dev profile redis config...."); 25 | RedisStandaloneConfiguration redisStandaloneConfiguration = 26 | new RedisStandaloneConfiguration(Objects.requireNonNull(environment.getProperty("REDIS_HOST")), 27 | Integer.parseInt(Objects.requireNonNull(environment.getProperty("REDIS_PORT")))); 28 | 29 | redisStandaloneConfiguration. 30 | setPassword(RedisPassword.of(Objects.requireNonNull(environment.getProperty("REDIS_PASSWORD")))); 31 | return new JedisConnectionFactory(redisStandaloneConfiguration); 32 | } 33 | 34 | @Bean 35 | public RedisTemplate redisTemplate() { 36 | RedisTemplate template = new RedisTemplate<>(); 37 | template.setConnectionFactory(jedisConnectionFactory()); 38 | return template; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /client/src/components/routes/home/verticalSlider.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Swiper from 'react-id-swiper'; 3 | import log from 'loglevel'; 4 | import {useSelector} from "react-redux"; 5 | import {BadRequest} from "../../ui/error/badRequest"; 6 | 7 | const VerticalSlider = () => { 8 | const homeAPIData = useSelector(state => state.homePageDataReducer) 9 | 10 | const params = { 11 | spaceBetween: 30, 12 | centeredSlides: true, 13 | autoplay: { 14 | delay: 4000, 15 | disableOnInteraction: false 16 | }, 17 | pagination: { 18 | el: '.swiper-pagination', 19 | clickable: true 20 | }, 21 | navigation: { 22 | nextEl: '.swiper-button-next', 23 | prevEl: '.swiper-button-prev' 24 | } 25 | } 26 | 27 | const renderImageList = (imageList) => { 28 | 29 | if(!imageList) { 30 | log.info(`[VerticalSlider]: imageList is null`) 31 | return 32 | } 33 | 34 | // filter out images which are not for carousels. 35 | imageList = imageList.filter(image => image.imageLocalPath.search("icon") === -1) 36 | 37 | log.trace("[VerticalSlider]: Rendering renderImageList imageList = " + JSON.stringify(imageList)) 38 | return imageList.map(({id, imageLocalPath, imageURL}) => { 39 | log.trace(`[VerticalSlider]: Rendering renderImageList imageList filePath = ${imageLocalPath}`) 40 | return ( 41 | {imageLocalPath}/ 42 | ) 43 | }); 44 | }; 45 | 46 | log.info("[VerticalSlider]: Rendering VerticalSlider Component") 47 | return ( 48 | 49 | {renderImageList(homeAPIData.data.carousels)} 50 | 51 | ) 52 | }; 53 | export default VerticalSlider; -------------------------------------------------------------------------------- /client/src/components/routes/checkout/summaryCard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Grid, Card, CardContent} from "@material-ui/core"; 3 | import DeleteIcon from '@material-ui/icons/Delete'; 4 | import Button from '@material-ui/core/Button'; 5 | import IconButton from '@material-ui/core/IconButton'; 6 | 7 | export const SummaryCard = (props) => { 8 | 9 | const renderCardContent = () => { 10 | let id = 0 11 | return props.contentList.map((formValue) => { 12 | ++id 13 | return ( 14 | 15 | {formValue} 16 | 17 | ) 18 | }) 19 | } 20 | 21 | return ( 22 | 23 | 24 | 25 | {renderCardContent()} 26 | 27 | 28 | 29 | 30 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ) 48 | } -------------------------------------------------------------------------------- /client/src/hooks/useAddProductsToShoppingBag.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import log from "loglevel"; 3 | import {LOAD_SHOPPING_BAG_PRODUCTS} from "../actions/types"; 4 | import {useDispatch, useSelector} from "react-redux"; 5 | import _ from "lodash"; 6 | import {PRODUCT_BY_ID_DATA_API} from "../constants/api_routes"; 7 | 8 | /** 9 | * Hook that alerts clicks outside of the passed ref 10 | */ 11 | export function useAddProductsToShoppingBag(getDataViaAPIFunc) { 12 | const addToCart = useSelector(state => state.addToCartReducer) 13 | const dispatch = useDispatch() 14 | 15 | const extractIdsFromObject = object => { 16 | log.info("[useAddProductsToShoppingBag] extractIdsFromObject object = " + JSON.stringify(object)) 17 | let idList = [] 18 | for (const [id] of Object.entries(object)) { 19 | idList.push(parseInt(id)) 20 | } 21 | return idList 22 | } 23 | 24 | useEffect(() => { 25 | log.info("[useAddProductsToShoppingBag] Component will mount... addToCart = " + JSON.stringify(addToCart)) 26 | 27 | let idList = [] 28 | 29 | if (!_.isEmpty(addToCart.productQty)) { 30 | log.info(`[ShoppingBag] load ShoppingBag products` + 31 | ` from addToCartQuantity = ${JSON.stringify(addToCart)}`) 32 | 33 | idList = extractIdsFromObject(addToCart["productQty"]) 34 | 35 | if (idList.length > 0) { 36 | getDataViaAPIFunc(LOAD_SHOPPING_BAG_PRODUCTS, PRODUCT_BY_ID_DATA_API + idList.toString(), null, false) 37 | return 38 | } 39 | 40 | } 41 | 42 | dispatch({ 43 | type: LOAD_SHOPPING_BAG_PRODUCTS, 44 | payload: {isLoading: false, data: {}} 45 | }) 46 | 47 | log.info(`[ShoppingBag] load ShoppingBag products idList = ${JSON.stringify(idList)}`) 48 | 49 | // eslint-disable-next-line 50 | }, [addToCart]) 51 | } -------------------------------------------------------------------------------- /client/src/components/routes/signup/signUp.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect, useState} from "react"; 2 | import SignUpForm from "./signUpForm" 3 | import {Grid} from "@material-ui/core"; 4 | import log from "loglevel"; 5 | import {useDispatch, useSelector} from "react-redux"; 6 | import {Dimmer, Loader} from "semantic-ui-react"; 7 | import {DocumentTitle} from "../../ui/documentTitle"; 8 | import {RESET_SIGN_UP} from "../../../actions/types"; 9 | 10 | const SignUp = () => { 11 | const [isLoading, setIsLoading] = useState(false); 12 | const {timestamp} = useSelector(state => state.signUpReducer) 13 | const dispatch = useDispatch() 14 | 15 | const setIsLoadingState = () => { 16 | setIsLoading(true); 17 | } 18 | 19 | useEffect(() => { 20 | log.info(`[SignUp]: Component did mount...`) 21 | setIsLoading(false) 22 | 23 | // eslint-disable-next-line 24 | }, [timestamp]) 25 | 26 | useEffect(() => { 27 | 28 | return () => { 29 | log.info(`[SignIn] Component will unmount...`) 30 | dispatch({ 31 | type: RESET_SIGN_UP 32 | }) 33 | } 34 | 35 | // eslint-disable-next-line 36 | }, []) 37 | 38 | log.info(`[SignUp]: Rendering SignUp Component`) 39 | 40 | return ( 41 | 42 | 43 | 44 | 45 |

Sign Up

46 |
47 | 48 |
49 | 50 | {isLoading ? 51 | Loading 52 | : null} 53 |
54 | ) 55 | } 56 | 57 | export default SignUp; -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/dao/UserInfoRepository.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.dao; 2 | 3 | import com.ujjaval.ecommerce.authenticationservice.entity.UserInfo; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Modifying; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.query.Param; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | import java.util.Optional; 11 | 12 | public interface UserInfoRepository extends JpaRepository { 13 | @Query(value = "SELECT user_id, username, first_name, last_name, email, password " + 14 | "FROM user_info where username = :USERNAME ", 15 | nativeQuery = true) 16 | Optional findByUsername(@Param("USERNAME") String USERNAME); 17 | 18 | @Query(value = "SELECT user_id, username, first_name, last_name, email, password " + 19 | "FROM user_info where email = :EMAIL ", 20 | nativeQuery = true) 21 | Optional findByEmail(@Param("EMAIL") String EMAIL); 22 | 23 | @Query(value = "DELETE FROM user_info where username = :USERNAME and password = :PASSWORD", 24 | nativeQuery = true) 25 | void deleteByUsernamePassword(@Param("USERNAME") String USERNAME, @Param("PASSWORD") String PASSWORD); 26 | 27 | @Modifying 28 | @Transactional 29 | @Query(value = "INSERT INTO user_info (username, first_name, last_name, email, password) " + 30 | " VALUES (:USERNAME, :FIRSTNAME, :LASTNAME, :EMAIL, :PASSWORD)", nativeQuery = true) 31 | void createUserProfile(@Param("USERNAME") String USERNAME, @Param("FIRSTNAME") String FIRSTNAME, 32 | @Param("LASTNAME") String LASTNAME, @Param("EMAIL") String EMAIL, 33 | @Param("PASSWORD") String PASSWORD); 34 | 35 | } -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 18 | 19 | 20 | 29 | Welcome to Shoppers 30 | 31 | 32 | 33 |
34 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/service/AuthDataServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.service; 2 | 3 | import com.ujjaval.ecommerce.authenticationservice.dao.UserInfoRepository; 4 | import com.ujjaval.ecommerce.authenticationservice.entity.UserInfo; 5 | import com.ujjaval.ecommerce.authenticationservice.util.Md5Util; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import java.security.NoSuchAlgorithmException; 10 | import java.util.Optional; 11 | 12 | @Service 13 | public class AuthDataServiceImpl implements AuthDataService { 14 | 15 | @Autowired 16 | private UserInfoRepository UserInfoRepository; 17 | 18 | public UserInfo findByUsername(String username) { 19 | Optional result = UserInfoRepository.findByUsername(username); 20 | 21 | UserInfo userInfo = null; 22 | 23 | if(result.isPresent()) { 24 | userInfo = result.get(); 25 | } 26 | 27 | return userInfo; 28 | } 29 | 30 | public UserInfo findByEmail(String email) { 31 | Optional result = UserInfoRepository.findByEmail(email); 32 | 33 | UserInfo userInfo = null; 34 | 35 | if(result.isPresent()) { 36 | userInfo = result.get(); 37 | } 38 | 39 | return userInfo; 40 | } 41 | 42 | public void createUserProfile(UserInfo userInfo) throws NoSuchAlgorithmException { 43 | UserInfoRepository.createUserProfile(userInfo.getUsername(), 44 | userInfo.getFirstName(), userInfo.getLastName(), 45 | userInfo.getEmail(), Md5Util.getInstance().getMd5Hash(userInfo.getPassword())); 46 | } 47 | 48 | public void deleteByUsernamePassword(String username, String password) throws NoSuchAlgorithmException { 49 | UserInfoRepository.deleteByUsernamePassword(username, Md5Util.getInstance().getMd5Hash(password)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /client/src/components/routes/navbar/sideBar.js: -------------------------------------------------------------------------------- 1 | import React, {useRef} from "react"; 2 | import {makeStyles} from "@material-ui/core/styles"; 3 | import AccordionSection from "./accordionSection"; 4 | import Drawer from "@material-ui/core/Drawer"; 5 | import log from 'loglevel'; 6 | import {useClickAway} from "../../../hooks/useClickAway"; 7 | 8 | export const useSideBarStyles = makeStyles((theme) => ({ 9 | root: { 10 | display: 'flex', 11 | }, 12 | drawer: { 13 | [theme.breakpoints.up('sm')]: { 14 | width: 280, 15 | flexShrink: 0, 16 | }, 17 | }, 18 | menuButton: { 19 | marginRight: theme.spacing(2), 20 | [theme.breakpoints.up('sm')]: { 21 | display: 'none', 22 | }, 23 | }, 24 | // necessary for content to be below app bar 25 | toolbar: theme.mixins.toolbar, 26 | drawerPaper: { 27 | position: "fixed", 28 | overflow: 'auto', 29 | backgroundColor: "#fff", 30 | [theme.breakpoints.up('xs')]: { 31 | width: 280, 32 | }, 33 | [theme.breakpoints.up('sm')]: { 34 | width: 400, 35 | }, 36 | }, 37 | })); 38 | 39 | const SideBar = (props) => { 40 | const classes = useSideBarStyles(); 41 | const wrapperRef = useRef(null); 42 | 43 | useClickAway(wrapperRef, props.closeHandler); 44 | 45 | log.info(`[SideBar] Rendering SideBar`) 46 | return ( 47 |
48 | 60 |
61 | ); 62 | } 63 | 64 | export default SideBar; -------------------------------------------------------------------------------- /server/payment-service/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | ${LOGS}/payment-service-logger.log 23 | 25 | %d %p %C{1.} [%t] %m%n 26 | 27 | 28 | 30 | 31 | ${LOGS}/archived/payment-service-logger-%d{yyyy-MM-dd}.%i.log 32 | 33 | 35 | 10MB 36 | 37 | 3 38 | 100MB 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /client/src/components/ui/modalConfirmation.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import log from 'loglevel'; 3 | import {Grid, Divider} from "@material-ui/core"; 4 | import Modal from "./modal"; 5 | 6 | export const ModalConfirmation = (props) => { 7 | 8 | log.info("[ModalConfirmation] Rendering ModalConfirmation Component...") 9 | const renderAddressRemovalConfirmation = () => { 10 | return ( 11 | 12 | 13 | 15 | {props.title} 16 | 17 | 18 | {props.question} 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | REMOVE 29 | 30 | 31 | 33 | CANCEL 34 | 35 | 36 | 37 | ) 38 | } 39 | 40 | return ( 41 | 44 | ) 45 | } 46 | -------------------------------------------------------------------------------- /client/src/components/routes/checkout/continueButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import log from 'loglevel'; 3 | import {Button, Grid, Hidden} from "@material-ui/core"; 4 | 5 | const continueButtonStyle = { 6 | backgroundColor: "#e01a2b", 7 | height: 50, 8 | fontSize: "1rem", 9 | fontWeight: "bolder", 10 | color: "White" 11 | } 12 | 13 | function ContinueButton(props) { 14 | 15 | const renderContinueDesktopBtn = () => { 16 | return ( 17 | 18 | 23 | 24 | ) 25 | } 26 | 27 | const renderContinueMobileBtn = () => { 28 | return ( 29 | 30 | 35 | 36 | ) 37 | } 38 | 39 | log.info("[Continue Button] Rendering Continue Button Component.") 40 | 41 | return ( 42 | <> 43 | 44 | {renderContinueDesktopBtn()} 45 | 46 | 47 | 48 | {renderContinueMobileBtn()} 49 | 50 | 51 | ) 52 | } 53 | 54 | function continueButtonPropsAreEqual(prevProps, nextProps) { 55 | return prevProps.action === nextProps.action && !prevProps.buttonHandler; 56 | } 57 | 58 | const continueButtonMemoWrapper = React.memo(ContinueButton, continueButtonPropsAreEqual); 59 | 60 | export default continueButtonMemoWrapper; -------------------------------------------------------------------------------- /server/common-data-service/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | ${LOGS}/common-data-service-logger.log 23 | 25 | %d %p %C{1.} [%t] %m%n 26 | 27 | 28 | 30 | 31 | ${LOGS}/archived/common-data-service-logger-%d{yyyy-MM-dd}.%i.log 32 | 33 | 35 | 10MB 36 | 37 | 3 38 | 100MB 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | ${LOGS}/authentication-service-logger.log 23 | 25 | %d %p %C{1.} [%t] %m%n 26 | 27 | 28 | 30 | 31 | ${LOGS}/archived/authentication-service-logger-%d{yyyy-MM-dd}.%i.log 32 | 33 | 35 | 10MB 36 | 37 | 3 38 | 100MB 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /server/search-suggestion-service/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | ${LOGS}/search-suggestion-service-logger.log 23 | 25 | %d %p %C{1.} [%t] %m%n 26 | 27 | 28 | 30 | 31 | ${LOGS}/archived/search-suggestion-service-logger-%d{yyyy-MM-dd}.%i.log 32 | 33 | 35 | 10MB 36 | 37 | 3 38 | 100MB 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ecommerce-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@material-ui/core": "~4.12.4", 7 | "@material-ui/icons": "latest", 8 | "@material-ui/lab": "latest", 9 | "@stripe/react-stripe-js": "~1.1.2", 10 | "@stripe/stripe-js": "~1.8.0", 11 | "axios": "~0.19.2", 12 | "env-cmd": "~10.1.0", 13 | "express": "~4.17.1", 14 | "fontsource-roboto": "~2.1.3", 15 | "js-base64": "~2.5.2", 16 | "js-cookie": "~2.2.1", 17 | "lodash": "~4.17.15", 18 | "loglevel": "~1.6.8", 19 | "node-sass": "~4.14.1", 20 | "path": "~0.12.7", 21 | "prop-types": "~15.7.2", 22 | "react": "~16.13.0", 23 | "react-dom": "~16.13.0", 24 | "react-helmet": "~6.1.0", 25 | "react-id-swiper": "~4.0.0", 26 | "react-redux": "~7.2.0", 27 | "react-router-dom": "~5.2.0", 28 | "react-scripts": "~3.4.4", 29 | "react-stripe-checkout": "~2.6.3", 30 | "redux": "~4.0.5", 31 | "redux-form": "~8.3.6", 32 | "redux-thunk": "~2.3.0", 33 | "semantic-ui-css": "~2.4.1", 34 | "semantic-ui-react": "~0.88.2", 35 | "stripe": "~8.78.0", 36 | "styled-components": "~5.1.1", 37 | "swiper": "~5.4.2" 38 | }, 39 | "scripts": { 40 | "start": "node server.js", 41 | "build": "react-scripts build", 42 | "start_docker_dev": "react-scripts start", 43 | "start_dev": "./node_modules/.bin/env-cmd -f .env react-scripts start", 44 | "build_dev": "./node_modules/.bin/env-cmd -f .env react-scripts build", 45 | "test": "react-scripts test", 46 | "eject": "react-scripts eject" 47 | }, 48 | "eslintConfig": { 49 | "extends": "react-app" 50 | }, 51 | "browserslist": { 52 | "production": [ 53 | ">0.2%", 54 | "not dead", 55 | "not op_mini all" 56 | ], 57 | "development": [ 58 | "last 1 chrome version", 59 | "last 1 firefox version", 60 | "last 1 safari version" 61 | ] 62 | }, 63 | "devDependencies": { 64 | "@testing-library/jest-dom": "^5.11.2", 65 | "@testing-library/react": "^10.4.7" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /client/src/components/routes/navbar/mobileMenu.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import log from "loglevel"; 3 | import {Grid, IconButton, Menu} from "@material-ui/core"; 4 | import MenuItem from "@material-ui/core/MenuItem"; 5 | import BagButton from "./bagButton"; 6 | 7 | export default function MobileMenu(props) { 8 | 9 | log.info(`[MobileMenu]: Rendering MobileMenu Component`) 10 | return ( 11 | 19 | 20 | 21 | 22 | 26 | {props.authIcon} 27 | 28 | 29 | 30 |

{props.authLabel}

31 |
32 |
33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |

Bag

43 |
44 |
45 |
46 |
47 | ); 48 | }; 49 | -------------------------------------------------------------------------------- /client/src/components/routes/priceDetails.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import log from 'loglevel'; 3 | import {Divider, Grid} from "@material-ui/core"; 4 | import {useSelector} from "react-redux"; 5 | 6 | const paymentStyles = { 7 | header: { 8 | fontColor: "#535766", 9 | fontWeight: "bolder", 10 | fontSize: "1.2rem", 11 | padding: "20px 0", 12 | }, 13 | fontColor: "#282c3f", 14 | fontWeight: 400, 15 | fontSize: "1.1rem", 16 | } 17 | 18 | function PriceDetails() { 19 | let cartTotal = useSelector(state => state.cartTotalReducer); 20 | const deliveryCharges = useSelector(state => state.deliveryChargesReducer) 21 | 22 | const renderGridData = (label, value, styles) => { 23 | return ( 24 | 25 | 26 | 27 | {label} 28 | 29 | 30 | 32 | {value} 33 | 34 | 35 | ) 36 | } 37 | 38 | log.info("[PriceDetails] Rendering PriceDetails Component.") 39 | 40 | return ( 41 | 42 | 43 | 45 | Price Details 46 | 47 | 48 | {renderGridData("Bag Total", `$${cartTotal}`, {...paymentStyles, paddingTop: 10})} 49 | {renderGridData("Shipping", `$${deliveryCharges}`, {...paymentStyles, paddingTop: 10})} 50 | 51 | 52 | 53 | 54 | 55 | {renderGridData("Order Total", `$${cartTotal + deliveryCharges}`, 56 | {...paymentStyles.header})} 57 | 58 | 59 | ) 60 | } 61 | 62 | export default PriceDetails; -------------------------------------------------------------------------------- /client/src/components/ui/radioButtonGroup.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Radio from '@material-ui/core/Radio'; 3 | import RadioGroup from '@material-ui/core/RadioGroup'; 4 | import FormControlLabel from '@material-ui/core/FormControlLabel'; 5 | import FormControl from '@material-ui/core/FormControl'; 6 | import log from "loglevel"; 7 | import {makeStyles} from "@material-ui/core/styles"; 8 | 9 | const useStyles = makeStyles(() => ({ 10 | label: { 11 | fontWeight: "bold", 12 | fontSize: "0.9rem" 13 | } 14 | })); 15 | 16 | export default function RadioButtonsGroup(props) { 17 | const classes = useStyles() 18 | 19 | const handleChange = (event) => { 20 | log.info(`[RadioButtonsGroup]: handleChange event.target.value = ${event.target.value}`) 21 | props.onChangeHandler(event.target.value) 22 | }; 23 | 24 | const renderRadioButtonList = rbList => { 25 | 26 | if (!rbList) { 27 | log.info(`[RadioButtonsGroup]: rbList is null`) 28 | return null 29 | } 30 | 31 | log.debug(`[RadioButtonsGroup]: rbList = ${JSON.stringify(rbList)}`) 32 | 33 | return rbList.map(({id, value}) => { 34 | return } 37 | label={value} 38 | classes={{label: classes.label}}/> 39 | }) 40 | } 41 | 42 | log.debug(`[RadioButtonsGroup]: props.attrList = ${props.attrList}`) 43 | log.debug(`[RadioButtonsGroup]: props.selectedValue = ${props.selectedValue}`) 44 | log.info(`[RadioButtonsGroup]: Rendering RadioButtonsGroup Component`) 45 | 46 | return ( 47 | 48 | 51 | {renderRadioButtonList(props.attrList)} 52 | 53 | 54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /client/src/components/app.js: -------------------------------------------------------------------------------- 1 | import React, {useState} from "react"; 2 | import history from "../history"; 3 | import {Router, Route, Switch} from 'react-router-dom'; 4 | import log from "loglevel" 5 | import NavBar from "./routes/navbar/navBar"; 6 | import {TabPanelList} from "./routes/navbar/tabPanelList"; 7 | import Home from "./routes/home/home"; 8 | import SignIn from "./routes/signin/signIn"; 9 | import SignUp from "./routes/signup/signUp"; 10 | import Product from "./routes/product/product"; 11 | import ProductDetail from "./routes/detail/productDetails"; 12 | import Checkout from "./routes/checkout/checkout"; 13 | import ShoppingBag from "./routes/shoppingBag"; 14 | import {SuccessPayment} from "./routes/successPayment"; 15 | import {CancelPayment} from "./routes/cancelPayment"; 16 | import {BadRequest} from "./ui/error/badRequest"; 17 | 18 | const App = () => { 19 | log.info(`[App]: Rendering App Component`) 20 | const [serverError, setServerError] = useState(false); 21 | 22 | const setServerErrorHandler = () => { 23 | setServerError(true) 24 | } 25 | 26 | return ( 27 | 28 | 29 | 30 | {serverError ? null: 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | } 43 | 44 | ) 45 | } 46 | 47 | export default App; -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/util/JwtUtil.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.util; 2 | 3 | import io.jsonwebtoken.Claims; 4 | import io.jsonwebtoken.Jwts; 5 | import io.jsonwebtoken.SignatureAlgorithm; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | import org.springframework.stereotype.Service; 8 | 9 | import java.util.Date; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.function.Function; 13 | 14 | @Service 15 | public class JwtUtil { 16 | 17 | private String SECRET_KEY = "sdf34hj@#234hls23$@423%nl"; 18 | 19 | public String extractUsername(String token) { 20 | return extractClaim(token, Claims::getSubject); 21 | } 22 | 23 | public Date extractExpiration(String token) { 24 | return extractClaim(token, Claims::getExpiration); 25 | } 26 | 27 | public T extractClaim(String token, Function claimsResolver) { 28 | final Claims claims = extractAllClaims(token); 29 | return claimsResolver.apply(claims); 30 | } 31 | private Claims extractAllClaims(String token) { 32 | return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody(); 33 | } 34 | 35 | private Boolean isTokenExpired(String token) { 36 | return extractExpiration(token).before(new Date()); 37 | } 38 | 39 | public String generateToken(UserDetails userDetails) { 40 | Map claims = new HashMap<>(); 41 | return createToken(claims, userDetails.getUsername()); 42 | } 43 | 44 | private String createToken(Map claims, String subject) { 45 | 46 | return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis())) 47 | .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) 48 | .signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact(); 49 | } 50 | 51 | public Boolean validateToken(String token, UserDetails userDetails) { 52 | final String username = extractUsername(token); 53 | return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /client/src/logger/Logger.js: -------------------------------------------------------------------------------- 1 | class Logger { 2 | static Levels = { 3 | ERROR:1, 4 | WARN:2, 5 | INFO:3, 6 | DEBUG:4, 7 | DISABLE:99, 8 | MAX_LEVEL:100 9 | }; 10 | 11 | static globalLoggerLevel = Logger.Levels.MAX_LEVEL; 12 | 13 | constructor(level = Logger.globalLoggerLevel) { 14 | this.currentLevel = level 15 | // console.log("constructor Level = " + level) 16 | } 17 | 18 | disable() { 19 | this.currentLevel = Logger.Levels.DISABLE 20 | } 21 | 22 | enable(level = Logger.Levels.ERROR) { 23 | this.currentLevel = level 24 | } 25 | 26 | send(level, message) { 27 | // eslint-disable-next-line default-case 28 | switch (level) { 29 | case Logger.Levels.DEBUG: 30 | console.log(`%c[${this.getCurrentTime()}] [DEBUG]: ${message}`, "color:orange; font-size: 15px; font-weight: bold") 31 | break 32 | case Logger.Levels.INFO: 33 | console.log(`%c[${this.getCurrentTime()}] [INFO]: ${message}`, "color:green; font-size: 15px; font-weight: bold") 34 | break 35 | case Logger.Levels.WARN: 36 | console.log(`%c[${this.getCurrentTime()}] [WARN]: ${message}`, "color:yellow; font-size: 15px; font-weight: bold") 37 | break 38 | case Logger.Levels.ERROR: 39 | console.log(`%c[${this.getCurrentTime()}] [ERROR]: ${message}`, "color:red; font-size: 15px; font-weight: bold") 40 | break 41 | } 42 | } 43 | 44 | log(level, message) { 45 | console.log("Level = " + level) 46 | if(level === Logger.Levels.DISABLE) { 47 | return; 48 | } 49 | 50 | if(Logger.globalLoggerLevel <= level || this.currentLevel <= level) { 51 | this.send(level, message) 52 | } 53 | } 54 | 55 | getCurrentTime() { 56 | let d = new Date(); 57 | return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}.${d.getMilliseconds()}` 58 | } 59 | 60 | error(message) { 61 | this.log(Logger.Levels.ERROR, message); 62 | } 63 | 64 | warn(message) { 65 | this.log(Logger.Levels.WARN, message); 66 | } 67 | 68 | info(message) { 69 | this.log(Logger.Levels.INFO, message); 70 | } 71 | 72 | debug(message) { 73 | this.log(Logger.Levels.DEBUG, message); 74 | } 75 | } 76 | 77 | export default Logger; -------------------------------------------------------------------------------- /client/src/components/ui/alertModal.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect, useState} from 'react'; 2 | import log from 'loglevel'; 3 | import {Button, Divider, Grid} from "@material-ui/core"; 4 | import Modal from "../ui/modal" 5 | 6 | function AlertModal(props) { 7 | 8 | const [alertConfirmation, setAlertConfirmation] = useState(false) 9 | 10 | useEffect(() => { 11 | log.info(`[AlertModal] Component Did mount`) 12 | if(props.enable) { 13 | log.info(`[AlertModal] enabling the alert confirmation`) 14 | setAlertConfirmation(true) 15 | } 16 | 17 | // eslint-disable-next-line 18 | }, [props.timestamp]) 19 | 20 | const renderAlertConfirmation = () => { 21 | return ( 22 | 23 | 24 | 26 | {props.title} 27 | 28 | 29 | {props.question} 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 42 | 43 | 44 | 45 | ) 46 | } 47 | 48 | const closeModalHandler = () => { 49 | setAlertConfirmation(false) 50 | } 51 | 52 | const renderModal = () => { 53 | return 56 | } 57 | 58 | log.info(`[AlertModal] Rendering AlertModal Component. alertConfirmation = ${alertConfirmation}`) 59 | 60 | return ( 61 | <> 62 | {alertConfirmation ? renderModal(): null} 63 | 64 | ) 65 | } 66 | 67 | export default AlertModal; -------------------------------------------------------------------------------- /server/payment-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.3.2.RELEASE 9 | 10 | 11 | com.ujjaval.ecommerce 12 | payment-service 13 | 0.0.1-SNAPSHOT 14 | payment-service 15 | payment-service Microservices 16 | 17 | 18 | 11 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-actuator 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-devtools 35 | runtime 36 | true 37 | 38 | 39 | 40 | com.stripe 41 | stripe-java 42 | 19.34.0 43 | 44 | 45 | 46 | org.projectlombok 47 | lombok 48 | true 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-test 53 | test 54 | 55 | 56 | org.junit.vintage 57 | junit-vintage-engine 58 | 59 | 60 | 61 | 62 | 63 | 64 | payment-service 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-maven-plugin 69 | 70 | 71 | repackage 72 | 73 | repackage 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/config/SecurityConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.config; 2 | 3 | import com.ujjaval.ecommerce.authenticationservice.filter.JwtRequestFilter; 4 | import com.ujjaval.ecommerce.authenticationservice.service.CustomUserDetailsService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.security.authentication.AuthenticationManager; 8 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 12 | import org.springframework.security.config.http.SessionCreationPolicy; 13 | import org.springframework.security.crypto.password.NoOpPasswordEncoder; 14 | import org.springframework.security.crypto.password.PasswordEncoder; 15 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 16 | 17 | @EnableWebSecurity 18 | public class SecurityConfigurer extends WebSecurityConfigurerAdapter { 19 | 20 | @Autowired 21 | private CustomUserDetailsService customUserDetailsService; 22 | 23 | @Autowired 24 | private JwtRequestFilter jwtRequestFilter; 25 | 26 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 27 | auth.userDetailsService(customUserDetailsService); 28 | } 29 | 30 | @Bean 31 | public PasswordEncoder passwordEncoder() { 32 | return NoOpPasswordEncoder.getInstance(); 33 | } 34 | 35 | @Override 36 | @Bean 37 | public AuthenticationManager authenticationManagerBean() throws Exception { 38 | return super.authenticationManagerBean(); 39 | } 40 | 41 | @Override 42 | protected void configure(HttpSecurity httpSecurity) throws Exception { 43 | httpSecurity.csrf().disable() 44 | .authorizeRequests().antMatchers("/authenticate", "/signup", "/test").permitAll(). 45 | anyRequest().authenticated().and(). 46 | exceptionHandling().and().sessionManagement() 47 | .sessionCreationPolicy(SessionCreationPolicy.STATELESS); 48 | 49 | httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /server/common-data-service/src/main/java/com/ujjaval/ecommerce/commondataservice/config/ProdRedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.commondataservice.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.cache.CacheManager; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.Profile; 9 | import org.springframework.core.env.Environment; 10 | import org.springframework.data.redis.cache.RedisCacheManager; 11 | import org.springframework.data.redis.connection.RedisConnectionFactory; 12 | import org.springframework.data.redis.connection.RedisPassword; 13 | import org.springframework.data.redis.connection.RedisStandaloneConfiguration; 14 | import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; 15 | import org.springframework.data.redis.core.RedisTemplate; 16 | import redis.clients.jedis.Jedis; 17 | import redis.clients.jedis.JedisPool; 18 | import redis.clients.jedis.JedisPoolConfig; 19 | import redis.clients.jedis.Protocol; 20 | 21 | import java.net.URI; 22 | import java.net.URISyntaxException; 23 | import java.net.UnknownHostException; 24 | import java.util.Objects; 25 | 26 | @Configuration 27 | @Profile("prod") 28 | public class ProdRedisConfig { 29 | 30 | @Bean 31 | public JedisConnectionFactory jedisConnectionFactory() { 32 | 33 | try { 34 | System.out.println("Loading Prod profile redis config...."); 35 | String redistogoUrl = System.getenv("REDIS_URL"); 36 | URI redistogoUri = new URI(redistogoUrl); 37 | 38 | JedisConnectionFactory jedisConnFactory = new JedisConnectionFactory(); 39 | 40 | jedisConnFactory.setUsePool(true); 41 | jedisConnFactory.setHostName(redistogoUri.getHost()); 42 | jedisConnFactory.setPort(redistogoUri.getPort()); 43 | jedisConnFactory.setTimeout(Protocol.DEFAULT_TIMEOUT); 44 | jedisConnFactory.setPassword(redistogoUri.getUserInfo().split(":", 2)[1]); 45 | 46 | return jedisConnFactory; 47 | 48 | } catch (URISyntaxException e) { 49 | e.printStackTrace(); 50 | return null; 51 | } 52 | } 53 | 54 | @Bean 55 | public RedisTemplate redisTemplate() { 56 | RedisTemplate template = new RedisTemplate<>(); 57 | template.setConnectionFactory(jedisConnectionFactory()); 58 | return template; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /client/src/components/routes/product/filterPagination.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect, useState} from 'react'; 2 | import Grid from "@material-ui/core/Grid"; 3 | import log from 'loglevel'; 4 | import {useSelector} from "react-redux"; 5 | import Pagination from "@material-ui/lab/Pagination"; 6 | import {MAX_PRODUCTS_PER_PAGE} from "../../../constants/constants"; 7 | import history from "../../../history"; 8 | 9 | export default function FilterPagination() { 10 | const selectedPage = useSelector(state => state.selectPageReducer) 11 | const filterProductsReducer = useSelector(state => state.filterProductsReducer) 12 | const [page, setPage] = useState(1) 13 | let totalProducts = 0 14 | 15 | useEffect(() => { 16 | if(selectedPage != null) { 17 | setPage(selectedPage.pageNumber) 18 | } 19 | }, [selectedPage]) 20 | 21 | const handleChangePage = (event, page) => { 22 | log.info(`[FilterPagination] dispatching SELECT_PRODUCT_PAGE for page = ${page}`) 23 | 24 | setPage(page) 25 | let route = history.location.pathname 26 | let queryStr = history.location.search 27 | if (history.location.search.search("page") === -1) { 28 | history.push(`${route}${queryStr}::page=${page-1},${MAX_PRODUCTS_PER_PAGE}`) 29 | } else { 30 | history.push(`${route}${queryStr.replace(new RegExp(`page=[0-9]+,${MAX_PRODUCTS_PER_PAGE}`), 31 | `page=${page-1},${MAX_PRODUCTS_PER_PAGE}`)}`) 32 | } 33 | } 34 | 35 | // if we got data from the server side 36 | if (!filterProductsReducer || filterProductsReducer.hasOwnProperty("data") === false || 37 | filterProductsReducer.data.hasOwnProperty("totalCount") === false) { 38 | log.info(`[FilterPagination] totalProducts = ${totalProducts}`) 39 | return null 40 | } else { 41 | // set the total products used to calculate how many pages require 42 | totalProducts = filterProductsReducer.data.totalCount 43 | } 44 | 45 | log.info(`[FilterPagination] Rendering FilterPagination Component selectedPage = ${JSON.stringify(selectedPage)}`) 46 | 47 | return ( 48 | 52 | 56 | 57 | ); 58 | } 59 | -------------------------------------------------------------------------------- /client/src/components/routes/product/filterSideNavbar/priceCheckBox.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect, useState} from 'react'; 2 | import CheckboxList from "../../../ui/checkboxList"; 3 | import log from 'loglevel'; 4 | import {useSelector} from "react-redux"; 5 | import {NavBarHeader} from "../../../ui/headers"; 6 | import {Box} from "@material-ui/core"; 7 | import history from "../../../../history"; 8 | import {toggleId} from "../../../../helper/toggleId"; 9 | import {updateQueryString} from "../../../../helper/updateQueryString"; 10 | 11 | export default function PriceCheckBox() { 12 | const TITLE = "Price" 13 | const priceRangeList = useSelector(state => state.filterAttributesReducer.data ? 14 | state.filterAttributesReducer.data.prices : null) 15 | const selectedPriceRanges = useSelector(state => state.selectedFilterAttributesReducer.prices) 16 | const [selectedList, setSelectedList] = useState([]) 17 | const resetFilter = useSelector(state => state.clearFiltersReducer) 18 | 19 | useEffect(() => { 20 | if (selectedPriceRanges.length > 0) { 21 | setSelectedList(selectedPriceRanges) 22 | } else { 23 | setSelectedList([]) 24 | } 25 | }, [selectedPriceRanges]) 26 | 27 | useEffect(() => { 28 | if(resetFilter) { 29 | if(selectedList.length > 0) { 30 | setSelectedList([]) 31 | } 32 | } 33 | 34 | // eslint-disable-next-line 35 | }, [history.location.search]) 36 | 37 | if (!priceRangeList) { 38 | log.debug(`[PriceCheckBox] priceRangeList is null`) 39 | return null 40 | } 41 | 42 | /** 43 | * select and dispatch the selected option 44 | * @param id 45 | * @param value 46 | */ 47 | const handleCheckBoxChange = (id, value) => { 48 | log.info(`[PriceCheckBox] handleCheckBoxChange(id) = ${id}`) 49 | const {list, ids} = toggleId(id, value, selectedList) 50 | setSelectedList(list) 51 | history.push(updateQueryString(history, "prices", id, ids)) 52 | } 53 | 54 | log.debug(`[PriceCheckBox] selectedPriceRanges...`) 55 | 56 | log.info(`[PriceCheckBox] Rendering PriceCheckBox Component`) 57 | 58 | return ( 59 | 60 | 61 | 62 | 63 | 68 | 69 | ); 70 | } 71 | -------------------------------------------------------------------------------- /server/payment-service/src/main/java/com/ujjaval/ecommerce/paymentservice/controller/PaymentController.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.paymentservice.controller; 2 | 3 | import com.stripe.Stripe; 4 | import com.stripe.exception.StripeException; 5 | import com.stripe.model.Charge; 6 | import com.stripe.param.ChargeCreateParams; 7 | import com.ujjaval.ecommerce.paymentservice.dto.CardToken; 8 | import com.ujjaval.ecommerce.paymentservice.dto.PaymentStatus; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.core.env.Environment; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | import java.net.UnknownHostException; 15 | import java.sql.Timestamp; 16 | 17 | @CrossOrigin(origins = "*", allowedHeaders = "*") 18 | @RestController 19 | public class PaymentController { 20 | 21 | @Autowired 22 | private Environment env; 23 | 24 | @GetMapping("/test") 25 | public ResponseEntity test() { 26 | return ResponseEntity.ok("success"); 27 | } 28 | 29 | @PostMapping("/payment") 30 | public ResponseEntity chargeCustomer(@RequestBody CardToken cardToken) { 31 | 32 | Stripe.apiKey = env.getProperty("STRIPE_SECRET_KEY"); 33 | Stripe.setMaxNetworkRetries(2); 34 | 35 | Charge charge; 36 | PaymentStatus paymentStatus; 37 | 38 | try { 39 | ChargeCreateParams params = 40 | ChargeCreateParams.builder() 41 | .setAmount(cardToken.getAmount()) 42 | .setCurrency(cardToken.getCurrency()) 43 | .setDescription("Shopper Buy") 44 | .setSource(cardToken.getId()) 45 | .build(); 46 | 47 | charge = Charge.create(params); 48 | System.out.println("Charge = " + charge); 49 | Timestamp timestamp = new Timestamp(System.currentTimeMillis()); 50 | 51 | paymentStatus = new PaymentStatus(timestamp.getTime(), false, 52 | charge.getId(), 53 | charge.getBalanceTransaction(), 54 | charge.getReceiptUrl() 55 | ); 56 | 57 | } catch (Exception e) { 58 | paymentStatus = new PaymentStatus(); 59 | paymentStatus.setPayment_failed(true); 60 | System.out.println("Something went wrong with Stripe API"); 61 | return ResponseEntity.badRequest().body(paymentStatus); 62 | } 63 | 64 | System.out.println("Payment is successful...."); 65 | return ResponseEntity.ok(paymentStatus); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /server/authentication-service/src/main/java/com/ujjaval/ecommerce/authenticationservice/filter/JwtRequestFilter.java: -------------------------------------------------------------------------------- 1 | package com.ujjaval.ecommerce.authenticationservice.filter; 2 | 3 | import com.ujjaval.ecommerce.authenticationservice.service.CustomUserDetailsService; 4 | import com.ujjaval.ecommerce.authenticationservice.util.JwtUtil; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.web.filter.OncePerRequestFilter; 12 | 13 | import javax.servlet.FilterChain; 14 | import javax.servlet.ServletException; 15 | import javax.servlet.http.HttpServletRequest; 16 | import javax.servlet.http.HttpServletResponse; 17 | import java.io.IOException; 18 | 19 | @Component 20 | public class JwtRequestFilter extends OncePerRequestFilter { 21 | 22 | @Autowired 23 | private CustomUserDetailsService customUserDetailsService; 24 | 25 | @Autowired 26 | private JwtUtil jwtUtil; 27 | 28 | @Override 29 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) 30 | throws ServletException, IOException { 31 | 32 | final String authorizationHeader = request.getHeader("Authorization"); 33 | 34 | String username = null; 35 | String jwt = null; 36 | 37 | if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { 38 | jwt = authorizationHeader.substring(7); 39 | username = jwtUtil.extractUsername(jwt); 40 | } 41 | 42 | if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { 43 | 44 | UserDetails userDetails = this.customUserDetailsService.loadUserByUsername(username); 45 | 46 | if (jwtUtil.validateToken(jwt, userDetails)) { 47 | 48 | UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken( 49 | userDetails, null, userDetails.getAuthorities()); 50 | usernamePasswordAuthenticationToken 51 | .setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 52 | SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); 53 | } 54 | } 55 | chain.doFilter(request, response); 56 | } 57 | 58 | } --------------------------------------------------------------------------------