Repository: EmbarkXOfficial/spring-boot-course
Branch: main
Commit: ecae1cad6af4
Files: 266
Total size: 469.5 KB
Directory structure:
gitextract_0gy1k5a8/
├── FirstSpring/
│ ├── .gitignore
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── embarkx/
│ │ │ └── FirstSpring/
│ │ │ ├── FirstSpringApplication.java
│ │ │ ├── HelloController.java
│ │ │ └── HelloResponse.java
│ │ └── resources/
│ │ └── application.properties
│ └── test/
│ └── java/
│ └── com/
│ └── embarkx/
│ └── FirstSpring/
│ └── FirstSpringApplicationTests.java
├── Java Spring Boot- Professional eCommerce Project Masterclass.postman_collection.json
├── README.md
├── SpringExample/
│ ├── .gitignore
│ ├── .idea/
│ │ ├── .gitignore
│ │ ├── encodings.xml
│ │ ├── misc.xml
│ │ ├── uiDesigner.xml
│ │ └── vcs.xml
│ ├── pom.xml
│ └── src/
│ └── main/
│ ├── java/
│ │ ├── car/
│ │ │ └── example/
│ │ │ ├── bean/
│ │ │ │ ├── App.java
│ │ │ │ └── MyBean.java
│ │ │ ├── constructor/
│ │ │ │ └── injection/
│ │ │ │ ├── App.java
│ │ │ │ ├── Car.java
│ │ │ │ └── Specification.java
│ │ │ └── setter/
│ │ │ └── injection/
│ │ │ ├── App.java
│ │ │ ├── Car.java
│ │ │ └── Specification.java
│ │ └── com/
│ │ ├── example/
│ │ │ ├── autowire/
│ │ │ │ ├── constructor/
│ │ │ │ │ ├── App.java
│ │ │ │ │ ├── Car.java
│ │ │ │ │ └── Specification.java
│ │ │ │ ├── name/
│ │ │ │ │ ├── App.java
│ │ │ │ │ ├── Car.java
│ │ │ │ │ └── Specification.java
│ │ │ │ └── type/
│ │ │ │ ├── App.java
│ │ │ │ ├── Car.java
│ │ │ │ └── Specification.java
│ │ │ ├── autowired/
│ │ │ │ └── annotation/
│ │ │ │ ├── App.java
│ │ │ │ ├── AppConfig.java
│ │ │ │ ├── Employee.java
│ │ │ │ └── Manager.java
│ │ │ └── componentscan/
│ │ │ ├── App.java
│ │ │ ├── Employee.java
│ │ │ └── annotation/
│ │ │ ├── App.java
│ │ │ ├── AppConfig.java
│ │ │ └── Employee.java
│ │ ├── ioc/
│ │ │ └── coupling/
│ │ │ ├── IOCExample.java
│ │ │ ├── NewDatabaseProvider.java
│ │ │ ├── UserDataProvider.java
│ │ │ ├── UserDatabaseProvider.java
│ │ │ ├── UserManager.java
│ │ │ └── WebServiceDataProvider.java
│ │ ├── loose/
│ │ │ └── coupling/
│ │ │ ├── LooseCouplingExample.java
│ │ │ ├── NewDatabaseProvider.java
│ │ │ ├── UserDataProvider.java
│ │ │ ├── UserDatabaseProvider.java
│ │ │ ├── UserManager.java
│ │ │ └── WebServiceDataProvider.java
│ │ └── tight/
│ │ └── coupling/
│ │ ├── TightCouplingExample.java
│ │ ├── UserDatabase.java
│ │ └── UserManager.java
│ └── resources/
│ ├── applicationBeanContext.xml
│ ├── applicationConstructorInjection.xml
│ ├── applicationIoCLooseCouplingExample.xml
│ ├── applicationSetterInjection.xml
│ ├── autowireByConstructor.xml
│ ├── autowireByName.xml
│ ├── autowireByType.xml
│ └── componentScanDemo.xml
├── ecom-frontend/
│ ├── .gitignore
│ ├── README.md
│ ├── eslint.config.js
│ ├── index.html
│ ├── package.json
│ ├── postcss.config.js
│ ├── src/
│ │ ├── App.css
│ │ ├── App.jsx
│ │ ├── api/
│ │ │ └── api.js
│ │ ├── components/
│ │ │ ├── About.jsx
│ │ │ ├── BackDrop.jsx
│ │ │ ├── Contact.jsx
│ │ │ ├── PrivateRoute.jsx
│ │ │ ├── UserMenu.jsx
│ │ │ ├── admin/
│ │ │ │ ├── AdminLayout.jsx
│ │ │ │ ├── categories/
│ │ │ │ │ ├── AddCategoryForm.jsx
│ │ │ │ │ └── Category.jsx
│ │ │ │ ├── dashboard/
│ │ │ │ │ ├── Dashboard.jsx
│ │ │ │ │ └── DashboardOverview.jsx
│ │ │ │ ├── orders/
│ │ │ │ │ ├── OrderTable.jsx
│ │ │ │ │ ├── Orders.jsx
│ │ │ │ │ └── UpdateOrderForm.jsx
│ │ │ │ ├── products/
│ │ │ │ │ ├── AddProductForm.jsx
│ │ │ │ │ ├── AdminProducts.jsx
│ │ │ │ │ └── ImageUploadForm.jsx
│ │ │ │ └── sellers/
│ │ │ │ ├── AddSellerForm.jsx
│ │ │ │ ├── SellerTable.jsx
│ │ │ │ ├── Sellers.jsx
│ │ │ │ └── useSellerFilter.jsx
│ │ │ ├── auth/
│ │ │ │ ├── LogIn.jsx
│ │ │ │ └── Register.jsx
│ │ │ ├── cart/
│ │ │ │ ├── Cart.jsx
│ │ │ │ ├── CartEmpty.jsx
│ │ │ │ ├── ItemContent.jsx
│ │ │ │ └── SetQuantity.jsx
│ │ │ ├── checkout/
│ │ │ │ ├── AddAddressForm.jsx
│ │ │ │ ├── AddressInfo.jsx
│ │ │ │ ├── AddressInfoModal.jsx
│ │ │ │ ├── AddressList.jsx
│ │ │ │ ├── Checkout.jsx
│ │ │ │ ├── DeleteModal.jsx
│ │ │ │ ├── OrderSummary.jsx
│ │ │ │ ├── PaymentConfirmation.jsx
│ │ │ │ ├── PaymentForm.jsx
│ │ │ │ ├── PaymentMethod.jsx
│ │ │ │ ├── PaypalPayment.jsx
│ │ │ │ └── StripePayment.jsx
│ │ │ ├── helper/
│ │ │ │ └── tableColumn.jsx
│ │ │ ├── home/
│ │ │ │ ├── HeroBanner.jsx
│ │ │ │ └── Home.jsx
│ │ │ ├── products/
│ │ │ │ ├── Filter.jsx
│ │ │ │ └── Products.jsx
│ │ │ └── shared/
│ │ │ ├── DeleteModal.jsx
│ │ │ ├── ErrorPage.jsx
│ │ │ ├── InputField.jsx
│ │ │ ├── Loader.jsx
│ │ │ ├── Modal.jsx
│ │ │ ├── Navbar.jsx
│ │ │ ├── Paginations.jsx
│ │ │ ├── ProductCard.jsx
│ │ │ ├── ProductViewModal.jsx
│ │ │ ├── SelectTextField.jsx
│ │ │ ├── Sidebar.jsx
│ │ │ ├── Skeleton.jsx
│ │ │ ├── Spinners.jsx
│ │ │ └── Status.jsx
│ │ ├── hooks/
│ │ │ ├── useCategoryFilter.js
│ │ │ ├── useOrderFilter.js
│ │ │ └── useProductFilter.js
│ │ ├── index.css
│ │ ├── main.jsx
│ │ ├── store/
│ │ │ ├── actions/
│ │ │ │ └── index.js
│ │ │ └── reducers/
│ │ │ ├── ProductReducer.js
│ │ │ ├── adminReducer.js
│ │ │ ├── authReducer.js
│ │ │ ├── cartReducer.js
│ │ │ ├── errorReducer.js
│ │ │ ├── orderReducer.js
│ │ │ ├── paymentMethodReducer.js
│ │ │ ├── sellerReducer.js
│ │ │ └── store.js
│ │ └── utils/
│ │ ├── constant.js
│ │ ├── formatPrice.js
│ │ ├── index.js
│ │ └── truncateText.js
│ └── vite.config.js
├── media/
│ ├── .gitignore
│ ├── .mvn/
│ │ └── wrapper/
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── social/
│ │ │ └── media/
│ │ │ ├── DataInitializer.java
│ │ │ ├── MediaApplication.java
│ │ │ ├── controllers/
│ │ │ │ └── SocialController.java
│ │ │ ├── models/
│ │ │ │ ├── Post.java
│ │ │ │ ├── SocialGroup.java
│ │ │ │ ├── SocialProfile.java
│ │ │ │ └── SocialUser.java
│ │ │ ├── repositories/
│ │ │ │ ├── PostRepository.java
│ │ │ │ ├── SocialGroupRepository.java
│ │ │ │ ├── SocialProfileRepository.java
│ │ │ │ └── SocialUserRepository.java
│ │ │ └── services/
│ │ │ └── SocialService.java
│ │ └── resources/
│ │ └── application.properties
│ └── test/
│ └── java/
│ └── com/
│ └── social/
│ └── media/
│ └── MediaApplicationTests.java
└── sb-ecom/
├── .gitignore
├── .mvn/
│ └── wrapper/
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── ecommerce/
│ │ └── project/
│ │ ├── SbEcomApplication.java
│ │ ├── config/
│ │ │ ├── AppConfig.java
│ │ │ ├── AppConstants.java
│ │ │ ├── SwaggerConfig.java
│ │ │ └── WebMvcConfig.java
│ │ ├── controller/
│ │ │ ├── AddressController.java
│ │ │ ├── AnalyticsController.java
│ │ │ ├── AuthController.java
│ │ │ ├── CartController.java
│ │ │ ├── CategoryController.java
│ │ │ ├── OrderController.java
│ │ │ └── ProductController.java
│ │ ├── exceptions/
│ │ │ ├── APIException.java
│ │ │ ├── MyGlobalExceptionHandler.java
│ │ │ └── ResourceNotFoundException.java
│ │ ├── model/
│ │ │ ├── Address.java
│ │ │ ├── AppRole.java
│ │ │ ├── Cart.java
│ │ │ ├── CartItem.java
│ │ │ ├── Category.java
│ │ │ ├── Order.java
│ │ │ ├── OrderItem.java
│ │ │ ├── Payment.java
│ │ │ ├── Product.java
│ │ │ ├── Role.java
│ │ │ └── User.java
│ │ ├── payload/
│ │ │ ├── APIResponse.java
│ │ │ ├── AddressDTO.java
│ │ │ ├── AnalyticsResponse.java
│ │ │ ├── AuthenticationResult.java
│ │ │ ├── CartDTO.java
│ │ │ ├── CartItemDTO.java
│ │ │ ├── CategoryDTO.java
│ │ │ ├── CategoryResponse.java
│ │ │ ├── OrderDTO.java
│ │ │ ├── OrderItemDTO.java
│ │ │ ├── OrderRequestDTO.java
│ │ │ ├── OrderResponse.java
│ │ │ ├── OrderStatusUpdateDto.java
│ │ │ ├── PaymentDTO.java
│ │ │ ├── ProductDTO.java
│ │ │ ├── ProductResponse.java
│ │ │ ├── StripePaymentDto.java
│ │ │ ├── UserDTO.java
│ │ │ └── UserResponse.java
│ │ ├── repositories/
│ │ │ ├── AddressRepository.java
│ │ │ ├── CartItemRepository.java
│ │ │ ├── CartRepository.java
│ │ │ ├── CategoryRepository.java
│ │ │ ├── OrderItemRepository.java
│ │ │ ├── OrderRepository.java
│ │ │ ├── PaymentRepository.java
│ │ │ ├── ProductRepository.java
│ │ │ ├── RoleRepository.java
│ │ │ └── UserRepository.java
│ │ ├── security/
│ │ │ ├── WebConfig.java
│ │ │ ├── WebSecurityConfig.java
│ │ │ ├── jwt/
│ │ │ │ ├── AuthEntryPointJwt.java
│ │ │ │ ├── AuthTokenFilter.java
│ │ │ │ └── JwtUtils.java
│ │ │ ├── request/
│ │ │ │ ├── LoginRequest.java
│ │ │ │ └── SignupRequest.java
│ │ │ ├── response/
│ │ │ │ ├── MessageResponse.java
│ │ │ │ └── UserInfoResponse.java
│ │ │ └── services/
│ │ │ ├── UserDetailsImpl.java
│ │ │ └── UserDetailsServiceImpl.java
│ │ ├── service/
│ │ │ ├── AddressService.java
│ │ │ ├── AddressServiceImpl.java
│ │ │ ├── AnalyticsService.java
│ │ │ ├── AnalyticsServiceImpl.java
│ │ │ ├── AuthService.java
│ │ │ ├── AuthServiceImpl.java
│ │ │ ├── CartService.java
│ │ │ ├── CartServiceImpl.java
│ │ │ ├── CategoryService.java
│ │ │ ├── CategoryServiceImpl.java
│ │ │ ├── FileService.java
│ │ │ ├── FileServiceImpl.java
│ │ │ ├── OrderService.java
│ │ │ ├── OrderServiceImpl.java
│ │ │ ├── ProductService.java
│ │ │ ├── ProductServiceImpl.java
│ │ │ ├── StripeService.java
│ │ │ └── StripeServiceImpl.java
│ │ └── util/
│ │ └── AuthUtil.java
│ └── resources/
│ └── application.properties
└── test/
└── java/
└── com/
└── ecommerce/
└── project/
└── SbEcomApplicationTests.java
================================================
FILE CONTENTS
================================================
================================================
FILE: FirstSpring/.gitignore
================================================
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
================================================
FILE: FirstSpring/mvnw
================================================
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' < "$1"
fi
}
log() {
if [ "$MVNW_VERBOSE" = true ]; then
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1
fi
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
# shellcheck disable=SC2086 # safe args
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
================================================
FILE: FirstSpring/mvnw.cmd
================================================
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.2.0
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%
================================================
FILE: FirstSpring/pom.xml
================================================
4.0.0
org.springframework.boot
spring-boot-starter-parent
4.0.1
com.embarkx
FirstSpring
0.0.1-SNAPSHOT
FirstSpring
First project for Spring Boot
24
org.springframework.boot
spring-boot-starter-webmvc
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
================================================
FILE: FirstSpring/src/main/java/com/embarkx/FirstSpring/FirstSpringApplication.java
================================================
package com.embarkx.FirstSpring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FirstSpringApplication {
public static void main(String[] args) {
SpringApplication.run(FirstSpringApplication.class, args);
}
}
================================================
FILE: FirstSpring/src/main/java/com/embarkx/FirstSpring/HelloController.java
================================================
package com.embarkx.FirstSpring;
import org.springframework.web.bind.annotation.*;
@RestController
public class HelloController {
@GetMapping("/hello/{name}")
public HelloResponse helloParam(@PathVariable String name) {
return new HelloResponse("Hello, " + name);
}
@GetMapping("/hello")
public HelloResponse hello() {
return new HelloResponse("Hello, World!");
}
@PostMapping("/hello")
public HelloResponse helloPost(@RequestBody String name) {
return new HelloResponse("Hello, " + name + "!");
}
}
================================================
FILE: FirstSpring/src/main/java/com/embarkx/FirstSpring/HelloResponse.java
================================================
package com.embarkx.FirstSpring;
public class HelloResponse {
private String message;
public HelloResponse(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
================================================
FILE: FirstSpring/src/main/resources/application.properties
================================================
server.port=8080
================================================
FILE: FirstSpring/src/test/java/com/embarkx/FirstSpring/FirstSpringApplicationTests.java
================================================
package com.embarkx.FirstSpring;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class FirstSpringApplicationTests {
@Test
void contextLoads() {
}
}
================================================
FILE: Java Spring Boot- Professional eCommerce Project Masterclass.postman_collection.json
================================================
{
"info": {
"_postman_id": "e901da3d-88dd-479e-a9f9-2a1a38b6282b",
"name": "Java Spring Boot: Professional eCommerce Project Masterclass",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "28392683"
},
"item": [
{
"name": "SocialMedia APIs",
"item": [
{
"name": "GetUsers",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/social/users",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"social",
"users"
]
}
},
"response": []
},
{
"name": "GetUsers",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/social/users/1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"social",
"users",
"1"
]
}
},
"response": []
},
{
"name": "DeleteUsers",
"request": {
"method": "DELETE",
"header": [],
"url": {
"raw": "http://localhost:8080/social/users/4",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"social",
"users",
"4"
]
}
},
"response": []
},
{
"name": "SaveUsers",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"id\": 10,\r\n \"socialProfile\": {\r\n \"id\": 10,\r\n \"description\":\"Test 4\"\r\n }\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/social/users",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"social",
"users"
]
}
},
"response": []
}
]
},
{
"name": "Hello World App",
"item": [
{
"name": "http://localhost:8080/hello",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "Spring Boot"
},
"url": {
"raw": "http://localhost:8080/hello",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"hello"
]
}
},
"response": []
},
{
"name": "http://localhost:8080/hello",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/hello",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"hello"
]
}
},
"response": []
}
]
},
{
"name": "Spring Boot Ecommerce",
"item": [
{
"name": "Product",
"item": [
{
"name": "Add Product",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"productName\": \"Adjustable dumbbell set for home workouts | Premium Quality\",\r\n \"description\": \"Adjustable dumbbell set for home workouts, can be used indoors, outdoors, at your personal gym. This is available at lowest possible rates.\",\r\n \"quantity\": 90,\r\n \"price\": 90,\r\n \"discount\": 10\r\n}\r\n",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/api/admin/categories/6/product",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"admin",
"categories",
"6",
"product"
]
}
},
"response": []
},
{
"name": "Update Product",
"request": {
"method": "PUT",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"productName\": \"Adjustable dumbbell set for home workouts | Premium Quality\",\r\n \"description\": \"Adjustable dumbbell set for home workouts, can be used indoors, outdoors, at your personal gym. This is available at lowest possible rates.\",\r\n \"quantity\": 0,\r\n \"price\": 90,\r\n \"discount\": 10\r\n}\r\n",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/api/admin/products/157",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"admin",
"products",
"157"
]
}
},
"response": []
},
{
"name": "Update Product Image",
"request": {
"method": "PUT",
"header": [],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "image",
"type": "file",
"src": "/C:/Users/FAISAL/Downloads/placeholder.png"
}
]
},
"url": {
"raw": "http://localhost:8080/api/products/202/image",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"products",
"202",
"image"
]
}
},
"response": []
},
{
"name": "Delete Product",
"request": {
"method": "DELETE",
"header": [],
"url": {
"raw": "http://localhost:8080/api/admin/products/1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"admin",
"products",
"1"
]
}
},
"response": []
},
{
"name": "Get All Products",
"request": {
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMSIsImlhdCI6MTcxNTE4MzY0OSwiZXhwIjoxNzE1MTg2NjQ5fQ.XS0-JKPhMJMrULRonqYLQzhJFTFOXGxkeuFj4q4mxeE",
"disabled": true
}
],
"url": {
"raw": "http://localhost:8080/api/public/products?sortBy=price&sortOrder=desc&pageSize=20",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"public",
"products"
],
"query": [
{
"key": "pageNumber",
"value": "1",
"disabled": true
},
{
"key": "sortBy",
"value": "price"
},
{
"key": "sortOrder",
"value": "desc"
},
{
"key": "keyword",
"value": "blender",
"disabled": true
},
{
"key": "category",
"value": "Electronics",
"disabled": true
},
{
"key": "pageSize",
"value": "20"
}
]
}
},
"response": []
},
{
"name": "Get Products By Keyword",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/api/public/products/keyword/rob?pageNumber=0&pageSize=10&sortBy=productName&sortOrder=desc",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"public",
"products",
"keyword",
"rob"
],
"query": [
{
"key": "pageNumber",
"value": "0"
},
{
"key": "pageSize",
"value": "10"
},
{
"key": "sortBy",
"value": "productName"
},
{
"key": "sortOrder",
"value": "desc"
}
]
}
},
"response": []
},
{
"name": "Get Products By Category",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/api/public/categories/1/products?pageNumber=0&pageSize=10&sortBy=productId&sortOrder=desc",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"public",
"categories",
"1",
"products"
],
"query": [
{
"key": "pageNumber",
"value": "0"
},
{
"key": "pageSize",
"value": "10"
},
{
"key": "sortBy",
"value": "productId"
},
{
"key": "sortOrder",
"value": "desc"
}
]
}
},
"response": []
}
]
},
{
"name": "Category",
"item": [
{
"name": "Get All Categories",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/api/public/categories",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"public",
"categories"
],
"query": [
{
"key": "pageNumber",
"value": "0",
"disabled": true
},
{
"key": "pageSize",
"value": "10",
"disabled": true
},
{
"key": "sortBy",
"value": "categoryName",
"disabled": true
},
{
"key": "sortOrder",
"value": "desc",
"disabled": true
}
]
}
},
"response": []
},
{
"name": "DELETE Category",
"request": {
"method": "DELETE",
"header": [],
"url": {
"raw": "http://localhost:8080/api/admin/categories/4",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"admin",
"categories",
"4"
]
}
},
"response": []
},
{
"name": "Create new Category",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"categoryName\":\"Sports & Fitness\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/api/public/categories",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"public",
"categories"
]
}
},
"response": []
},
{
"name": "Update Category",
"request": {
"method": "PUT",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"categoryName\":\"Travel Updated\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/api/public/categories/1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"public",
"categories",
"1"
]
}
},
"response": []
}
]
},
{
"name": "Authentication",
"item": [
{
"name": "Sign in",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"username\":\"user1\",\r\n \"password\":\"password1\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/api/auth/signin",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"auth",
"signin"
]
}
},
"response": []
},
{
"name": "GetUserName",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/api/auth/username",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"auth",
"username"
]
}
},
"response": []
},
{
"name": "GetUser",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/api/auth/user",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"auth",
"user"
]
}
},
"response": []
},
{
"name": "Sign Out",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "http://localhost:8080/api/auth/signout",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"auth",
"signout"
]
}
},
"response": []
},
{
"name": "Sign up",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"username\":\"user3\",\r\n \"email\":\"user3email@gmail.com\",\r\n \"password\":\"password3\",\r\n \"role\":[\"admin\"]\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/api/auth/signup",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"auth",
"signup"
]
}
},
"response": []
}
]
},
{
"name": "Cart",
"item": [
{
"name": "Add product to cart",
"request": {
"auth": {
"type": "noauth"
},
"method": "POST",
"header": [
{
"key": "",
"value": "",
"disabled": true
}
],
"url": {
"raw": "http://localhost:8080/api/carts/products/1/quantity/1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"carts",
"products",
"1",
"quantity",
"1"
]
}
},
"response": []
},
{
"name": "Get all carts",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [
{
"key": "",
"value": "",
"disabled": true
}
],
"url": {
"raw": "http://localhost:8080/api/carts",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"carts"
]
}
},
"response": []
},
{
"name": "Get User Cart",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [
{
"key": "",
"value": "",
"disabled": true
}
],
"url": {
"raw": "http://localhost:8080/api/carts/users/cart",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"carts",
"users",
"cart"
]
}
},
"response": []
},
{
"name": "Update quantity of product in Cart",
"request": {
"auth": {
"type": "noauth"
},
"method": "PUT",
"header": [
{
"key": "",
"value": "",
"disabled": true
}
],
"url": {
"raw": "http://localhost:8080/api/cart/products/1/quantity/delete",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"cart",
"products",
"1",
"quantity",
"delete"
]
}
},
"response": []
},
{
"name": "Delete product from cart",
"request": {
"auth": {
"type": "noauth"
},
"method": "DELETE",
"header": [
{
"key": "",
"value": "",
"disabled": true
}
],
"url": {
"raw": "http://localhost:8080/api/carts/1/product/1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"carts",
"1",
"product",
"1"
]
}
},
"response": []
}
]
},
{
"name": "Addresses",
"item": [
{
"name": "Create Address",
"request": {
"auth": {
"type": "noauth"
},
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"country\": \"USA\",\r\n \"city\": \"San Francisco\",\r\n \"street\": \"Market Street\",\r\n \"pincode\": \"94103\",\r\n \"buildingName\": \"Bay Apartments\",\r\n \"state\": \"California\"\r\n}\r\n",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/api/addresses",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"addresses"
]
}
},
"response": []
},
{
"name": "Update Address",
"request": {
"auth": {
"type": "noauth"
},
"method": "PUT",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"country\": \"USA\",\r\n \"city\": \"San Francisco\",\r\n \"street\": \"Market Street\",\r\n \"pincode\": \"94103\",\r\n \"buildingName\": \"Bay Apartments Updated\",\r\n \"state\": \"California\"\r\n}\r\n",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/api/addresses/1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"addresses",
"1"
]
}
},
"response": []
},
{
"name": "Get Addresses",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/api/addresses",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"addresses"
]
}
},
"response": []
},
{
"name": "Get Address By Id",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/api/addresses/1",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"addresses",
"1"
]
}
},
"response": []
},
{
"name": "Delete Address",
"request": {
"auth": {
"type": "noauth"
},
"method": "DELETE",
"header": [],
"url": {
"raw": "http://localhost:8080/api/addresses/2",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"addresses",
"2"
]
}
},
"response": []
},
{
"name": "Get User Addresses",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [],
"url": {
"raw": "http://localhost:8080/api/users/addresses",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"users",
"addresses"
]
}
},
"response": []
}
]
},
{
"name": "Orders",
"item": [
{
"name": "Place Order",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"addressId\": 1,\r\n \"pgName\": \"Stripe\",\r\n \"pgPaymentId\": \"pi_1FHEhK2eZvKYlo2CcK4UJNdW\",\r\n \"pgStatus\": \"succeeded\",\r\n \"pgResponseMessage\": \"Payment successful\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/api/order/users/payments/CARD",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"order",
"users",
"payments",
"CARD"
]
}
},
"response": []
},
{
"name": "StripeClientSecret",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"amount\": 2000,\r\n \"currency\": \"usd\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "http://localhost:8080/api/order/stripe-client-secret",
"protocol": "http",
"host": [
"localhost"
],
"port": "8080",
"path": [
"api",
"order",
"stripe-client-secret"
]
}
},
"response": []
}
]
}
]
}
]
}
================================================
FILE: README.md
================================================
This is the Official repository of **Java Spring Boot: Professional eCommerce Project Masterclass** on Udemy
# The Ultimate Java and Spring Boot Mastery Roadmap
Welcome to your one-stop-shop for mastering Java and Spring Boot! This repository offers a comprehensive learning experience with high-quality resources and community support. Dive into over 150+ hours of premium content, with everything you need to excel at Java and Spring Boot development.
## 🎓 Learning Roadmap
Most of the courses below are available in **Udemy For Business**, so if you have subscription - you can get FREE access.
Here’s a structured path to enhance your skills with detailed courses available:
1. **[Spring Boot By Building Complex Projects Step by Step](https://link.embarkx.com/spring-boot) (90+ Hours of Content)**
2. **[Master Spring Boot Microservices by Building eCommerce Project](https://link.embarkx.com/microservices) (55+ Hours of Content)**
3. **[Full Stack AI DevOps for Software Developers (AWS, Azure, GCP)](https://link.embarkx.com/devops) (20+ Hours of Content)**
4. **[Learn Java with 60+ Hours of Content](http://link.embarkx.com/java) (60+ Hours of Content)**
5. **[Master Spring Security with React JS + OAuth2](https://link.embarkx.com/spring-security) (34+ Hours of Content)**
6. **[Master IntelliJ IDEA](http://link.embarkx.com/intellij) (3+ Hours of Content)**
## 🌟 With All Our Courses You Gain Access To
- 📝 **Notes:** Detailed and downloadable notes to accompany each lesson.
- 💻 **Source Code:** Full access to the source code used in the tutorials.
- 🤔 **Doubt Solving:** Responsive instructor and community support.
- 🎥 **High-Quality HD Videos:** Easy to understand, high-definition video tutorials.
- 🔄 **Free Lifetime Updates:** Continuous updates to course content at no extra cost.
## 📚 Why Choose This Mastery Series?
With this series, you're not just learning; you're preparing to dominate the field of Java and Spring Boot development. Our structured learning path ensures that you build your skills progressively, with each course designed to build on the knowledge gained from the previous one.
### Join Us Now!
Start your journey today to become a master at Java and Spring Boot. Our community and expert instructors are here to support your learning every step of the way. **Enroll and start building your future, today!**
# Usage Policy for Course Materials
## Instructor Information
**Instructor:** Faisal Memon
**Company:** [EmbarkX.com](http://www.embarkx.com)
## Policy Overview
This document outlines the guidelines and restrictions concerning the use of course materials provided by EmbarkX, including but not limited to PDF presentations, code samples, and video tutorials.
### 1. Personal Use Only
The materials provided in this course are intended for **your personal use only**. They are to be used solely for the purpose of learning and completing this course.
### 2. No Unauthorized Sharing or Distribution
You are **not permitted** to share, distribute, or publicly post any course materials on any websites, social media platforms, or other public forums without prior written consent from the instructor.
### 3. Intellectual Property
All course materials are protected by copyright laws and are the intellectual property of Faisal Memon and EmbarkX. Unauthorized use, reproduction, or distribution of these materials is **strictly prohibited**.
### 4. Reporting Violations
If you become aware of any unauthorized sharing or distribution of course materials, please report it immediately to [embarkxofficial@gmail.com](mailto:embarkxofficial@gmail.com).
### 5. Legal Action
We reserve the right to take legal action against individuals or entities found to be violating this usage policy.
## Thank You
Thank you for respecting these guidelines and helping us maintain the integrity of our course materials.
## Contact Information
- **Email:** [embarkxofficial@gmail.com](mailto:embarkxofficial@gmail.com)
- **Website:** [www.embarkx.com](http://www.embarkx.com)
================================================
FILE: SpringExample/.gitignore
================================================
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
================================================
FILE: SpringExample/.idea/.gitignore
================================================
# Default ignored files
/shelf/
/workspace.xml
================================================
FILE: SpringExample/.idea/encodings.xml
================================================
================================================
FILE: SpringExample/.idea/misc.xml
================================================
================================================
FILE: SpringExample/.idea/uiDesigner.xml
================================================
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
================================================
FILE: SpringExample/.idea/vcs.xml
================================================
================================================
FILE: SpringExample/pom.xml
================================================
4.0.0
org.example
SpringExample
1.0-SNAPSHOT
21
21
UTF-8
org.springframework
spring-core
6.1.6
org.springframework
spring-context
6.1.6
================================================
FILE: SpringExample/src/main/java/car/example/bean/App.java
================================================
package car.example.bean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context
= new ClassPathXmlApplicationContext("applicationBeanContext.xml");
MyBean myBean = (MyBean) context.getBean("myBean");
System.out.println(myBean);
}
}
================================================
FILE: SpringExample/src/main/java/car/example/bean/MyBean.java
================================================
package car.example.bean;
public class MyBean {
private String message;
public void setMessage(String message) {
this.message = message;
}
public void showMessage(){
System.out.println("Message: " + message);
}
@Override
public String toString() {
return "MyBean{" +
"message='" + message + '\'' +
'}';
}
}
================================================
FILE: SpringExample/src/main/java/car/example/constructor/injection/App.java
================================================
package car.example.constructor.injection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context
= new ClassPathXmlApplicationContext("applicationConstructorInjection.xml");
Car myCar = (Car) context.getBean("myCar");
myCar.displayDetails();
}
}
================================================
FILE: SpringExample/src/main/java/car/example/constructor/injection/Car.java
================================================
package car.example.constructor.injection;
public class Car {
private Specification specification;
public Car(Specification specification) {
this.specification = specification;
}
public void displayDetails(){
System.out.println("Car Details: " + specification.toString());
}
}
================================================
FILE: SpringExample/src/main/java/car/example/constructor/injection/Specification.java
================================================
package car.example.constructor.injection;
public class Specification {
private String make;
private String model;
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String toString() {
return "Specification{" +
"make='" + make + '\'' +
", model='" + model + '\'' +
'}';
}
}
================================================
FILE: SpringExample/src/main/java/car/example/setter/injection/App.java
================================================
package car.example.setter.injection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context
= new ClassPathXmlApplicationContext("applicationSetterInjection.xml");
Car myCar = (Car) context.getBean("myCar");
myCar.displayDetails();
}
}
================================================
FILE: SpringExample/src/main/java/car/example/setter/injection/Car.java
================================================
package car.example.setter.injection;
public class Car {
private Specification specification;
public void setSpecification(Specification specification) {
this.specification = specification;
}
public void displayDetails(){
System.out.println("Car Details: " + specification.toString());
}
}
================================================
FILE: SpringExample/src/main/java/car/example/setter/injection/Specification.java
================================================
package car.example.setter.injection;
public class Specification {
private String make;
private String model;
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String toString() {
return "Specification{" +
"make='" + make + '\'' +
", model='" + model + '\'' +
'}';
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowire/constructor/App.java
================================================
package com.example.autowire.constructor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context
= new ClassPathXmlApplicationContext("autowireByConstructor.xml");
Car myCar = (Car) context.getBean("myCar");
myCar.displayDetails();
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowire/constructor/Car.java
================================================
package com.example.autowire.constructor;
public class Car {
private Specification specification;
public Car(Specification specification) {
this.specification = specification;
}
// public void setSpecification(Specification specification) {
// this.specification = specification;
// }
public void displayDetails(){
System.out.println("Car Details: " + specification.toString());
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowire/constructor/Specification.java
================================================
package com.example.autowire.constructor;
public class Specification {
private String make;
private String model;
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String toString() {
return "Specification{" +
"make='" + make + '\'' +
", model='" + model + '\'' +
'}';
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowire/name/App.java
================================================
package com.example.autowire.name;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context
= new ClassPathXmlApplicationContext("autowireByName.xml");
Car myCar = (Car) context.getBean("myCar");
myCar.displayDetails();
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowire/name/Car.java
================================================
package com.example.autowire.name;
public class Car {
private Specification specification;
public void setSpecification(Specification specification) {
this.specification = specification;
}
public void displayDetails(){
System.out.println("Car Details: " + specification.toString());
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowire/name/Specification.java
================================================
package com.example.autowire.name;
public class Specification {
private String make;
private String model;
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String toString() {
return "Specification{" +
"make='" + make + '\'' +
", model='" + model + '\'' +
'}';
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowire/type/App.java
================================================
package com.example.autowire.type;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context
= new ClassPathXmlApplicationContext("autowireByType.xml");
Car myCar = (Car) context.getBean("myCar");
myCar.displayDetails();
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowire/type/Car.java
================================================
package com.example.autowire.type;
public class Car {
private Specification specification;
public void setSpecification(Specification specification) {
this.specification = specification;
}
public void displayDetails(){
System.out.println("Car Details: " + specification.toString());
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowire/type/Specification.java
================================================
package com.example.autowire.type;
public class Specification {
private String make;
private String model;
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String toString() {
return "Specification{" +
"make='" + make + '\'' +
", model='" + model + '\'' +
'}';
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowired/annotation/App.java
================================================
package com.example.autowired.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
Employee employee = context.getBean("employee", Employee.class);
System.out.println(employee.toString());
Manager manager = context.getBean("manager", Manager.class);
System.out.println(manager.toString());
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowired/annotation/AppConfig.java
================================================
package com.example.autowired.annotation;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.example.autowired.annotation")
public class AppConfig {
}
================================================
FILE: SpringExample/src/main/java/com/example/autowired/annotation/Employee.java
================================================
package com.example.autowired.annotation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("employee")
public class Employee {
private int employeeId;
@Value("Hello")
private String firstName;
@Value("${java.home}")
private String lastName;
@Value("#{4*4}")
private double salary;
public int getEmployeeId() {
return employeeId;
}
public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"employeeId=" + employeeId +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", salary=" + salary +
'}';
}
}
================================================
FILE: SpringExample/src/main/java/com/example/autowired/annotation/Manager.java
================================================
package com.example.autowired.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class Manager {
@Autowired
@Qualifier("employee")
private Employee employee;
/*@Autowired
public Manager(Employee employee) {
this.employee = employee;
}*/
@Override
public String toString() {
return "Manager{" +
"employee=" + employee +
'}';
}
}
================================================
FILE: SpringExample/src/main/java/com/example/componentscan/App.java
================================================
package com.example.componentscan;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context
= new ClassPathXmlApplicationContext("componentScanDemo.xml");
Employee employee = context.getBean("employee", Employee.class);
System.out.println(employee.toString());
}
}
================================================
FILE: SpringExample/src/main/java/com/example/componentscan/Employee.java
================================================
package com.example.componentscan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("employee")
public class Employee {
private int employeeId;
@Value("Hello")
private String firstName;
@Value("${java.home}")
private String lastName;
@Value("#{4*4}")
private double salary;
public int getEmployeeId() {
return employeeId;
}
public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"employeeId=" + employeeId +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", salary=" + salary +
'}';
}
}
================================================
FILE: SpringExample/src/main/java/com/example/componentscan/annotation/App.java
================================================
package com.example.componentscan.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context
= new AnnotationConfigApplicationContext(AppConfig.class);
Employee employee = context.getBean("employee", Employee.class);
System.out.println(employee.toString());
}
}
================================================
FILE: SpringExample/src/main/java/com/example/componentscan/annotation/AppConfig.java
================================================
package com.example.componentscan.annotation;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.example.componentscan.annotation")
public class AppConfig {
}
================================================
FILE: SpringExample/src/main/java/com/example/componentscan/annotation/Employee.java
================================================
package com.example.componentscan.annotation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("employee")
public class Employee {
private int employeeId;
@Value("Hello")
private String firstName;
@Value("${java.home}")
private String lastName;
@Value("#{4*4}")
private double salary;
public int getEmployeeId() {
return employeeId;
}
public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"employeeId=" + employeeId +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", salary=" + salary +
'}';
}
}
================================================
FILE: SpringExample/src/main/java/com/ioc/coupling/IOCExample.java
================================================
package com.ioc.coupling;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class IOCExample {
public static void main(String[] args) {
ApplicationContext context
= new ClassPathXmlApplicationContext("applicationIoCLooseCouplingExample.xml");
UserManager userManagerWithDB =
(UserManager) context.getBean("userManagerWithUserDataProvider");
System.out.println(userManagerWithDB.getUserInfo());
UserManager userManagerWithWS =
(UserManager) context.getBean("userManagerWithWebServiceProvider");
System.out.println(userManagerWithWS.getUserInfo());
UserManager userManagerWithNewDB =
(UserManager) context.getBean("userManagerWithNewDatabaseProvider");
System.out.println(userManagerWithNewDB.getUserInfo());
}
}
================================================
FILE: SpringExample/src/main/java/com/ioc/coupling/NewDatabaseProvider.java
================================================
package com.ioc.coupling;
public class NewDatabaseProvider implements UserDataProvider {
@Override
public String getUserDetails() {
return "New Database in action";
}
}
================================================
FILE: SpringExample/src/main/java/com/ioc/coupling/UserDataProvider.java
================================================
package com.ioc.coupling;
public interface UserDataProvider {
String getUserDetails();
}
================================================
FILE: SpringExample/src/main/java/com/ioc/coupling/UserDatabaseProvider.java
================================================
package com.ioc.coupling;
// A - MySQL, PostgreSQL
// B - Web Service, MongoDB
public class UserDatabaseProvider implements UserDataProvider {
@Override
public String getUserDetails(){
// Directly access database here
return "User Details From Database";
}
}
================================================
FILE: SpringExample/src/main/java/com/ioc/coupling/UserManager.java
================================================
package com.ioc.coupling;
public class UserManager {
private UserDataProvider userDataProvider;
public UserManager(UserDataProvider userDataProvider) {
this.userDataProvider = userDataProvider;
}
public String getUserInfo(){
return userDataProvider.getUserDetails();
}
}
================================================
FILE: SpringExample/src/main/java/com/ioc/coupling/WebServiceDataProvider.java
================================================
package com.ioc.coupling;
public class WebServiceDataProvider implements UserDataProvider {
@Override
public String getUserDetails() {
return "Fetching Data From WebService";
}
}
================================================
FILE: SpringExample/src/main/java/com/loose/coupling/LooseCouplingExample.java
================================================
package com.loose.coupling;
public class LooseCouplingExample {
public static void main(String[] args) {
UserDataProvider databaseProvider = new UserDatabaseProvider();
UserManager userManagerWithDB = new UserManager(databaseProvider);
System.out.println(userManagerWithDB.getUserInfo());
UserDataProvider webServiceProvider = new WebServiceDataProvider();
UserManager userManagerWithWS = new UserManager(webServiceProvider);
System.out.println(userManagerWithWS.getUserInfo());
UserDataProvider newDatabaseProvider = new NewDatabaseProvider();
UserManager userManagerWithNewDB = new UserManager(newDatabaseProvider);
System.out.println(userManagerWithNewDB.getUserInfo());
}
}
================================================
FILE: SpringExample/src/main/java/com/loose/coupling/NewDatabaseProvider.java
================================================
package com.loose.coupling;
public class NewDatabaseProvider implements UserDataProvider{
@Override
public String getUserDetails() {
return "New Database in action";
}
}
================================================
FILE: SpringExample/src/main/java/com/loose/coupling/UserDataProvider.java
================================================
package com.loose.coupling;
public interface UserDataProvider {
String getUserDetails();
}
================================================
FILE: SpringExample/src/main/java/com/loose/coupling/UserDatabaseProvider.java
================================================
package com.loose.coupling;
// A - MySQL, PostgreSQL
// B - Web Service, MongoDB
public class UserDatabaseProvider implements UserDataProvider {
@Override
public String getUserDetails(){
// Directly access database here
return "User Details From Database";
}
}
================================================
FILE: SpringExample/src/main/java/com/loose/coupling/UserManager.java
================================================
package com.loose.coupling;
public class UserManager {
private UserDataProvider userDataProvider;
public UserManager(UserDataProvider userDataProvider) {
this.userDataProvider = userDataProvider;
}
public String getUserInfo(){
return userDataProvider.getUserDetails();
}
}
================================================
FILE: SpringExample/src/main/java/com/loose/coupling/WebServiceDataProvider.java
================================================
package com.loose.coupling;
public class WebServiceDataProvider implements UserDataProvider{
@Override
public String getUserDetails() {
return "Fetching Data From WebService";
}
}
================================================
FILE: SpringExample/src/main/java/com/tight/coupling/TightCouplingExample.java
================================================
package com.tight.coupling;
public class TightCouplingExample {
public static void main(String[] args) {
UserManager userManager = new UserManager();
System.out.println(userManager.getUserInfo());
}
}
================================================
FILE: SpringExample/src/main/java/com/tight/coupling/UserDatabase.java
================================================
package com.tight.coupling;
// A - MySQL, PostgreSQL
// B - Web Service, MongoDB
public class UserDatabase {
public String getUserDetails(){
// Directly access database here
return "User Details From Database";
}
}
================================================
FILE: SpringExample/src/main/java/com/tight/coupling/UserManager.java
================================================
package com.tight.coupling;
public class UserManager {
private UserDatabase userDatabase = new UserDatabase();
public String getUserInfo(){
return userDatabase.getUserDetails();
}
}
================================================
FILE: SpringExample/src/main/resources/applicationBeanContext.xml
================================================
================================================
FILE: SpringExample/src/main/resources/applicationConstructorInjection.xml
================================================
================================================
FILE: SpringExample/src/main/resources/applicationIoCLooseCouplingExample.xml
================================================
================================================
FILE: SpringExample/src/main/resources/applicationSetterInjection.xml
================================================
================================================
FILE: SpringExample/src/main/resources/autowireByConstructor.xml
================================================
================================================
FILE: SpringExample/src/main/resources/autowireByName.xml
================================================
================================================
FILE: SpringExample/src/main/resources/autowireByType.xml
================================================
================================================
FILE: SpringExample/src/main/resources/componentScanDemo.xml
================================================
================================================
FILE: ecom-frontend/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.env
================================================
FILE: ecom-frontend/README.md
================================================
# React + Vite
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
================================================
FILE: ecom-frontend/eslint.config.js
================================================
import js from '@eslint/js'
import globals from 'globals'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
settings: { react: { version: '18.3' } },
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...js.configs.recommended.rules,
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
]
================================================
FILE: ecom-frontend/index.html
================================================
Vite + React
================================================
FILE: ecom-frontend/package.json
================================================
{
"name": "ecom-frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@headlessui/react": "^2.2.9",
"@mui/material": "^7.3.7",
"@mui/x-data-grid": "^8.25.0",
"@reduxjs/toolkit": "^2.11.2",
"@stripe/react-stripe-js": "^5.4.1",
"@stripe/stripe-js": "^8.6.3",
"axios": "^1.13.2",
"classnames": "^2.5.1",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"react-hook-form": "^7.71.1",
"react-hot-toast": "^2.6.0",
"react-icons": "^5.5.0",
"react-loader-spinner": "^8.0.2",
"react-redux": "^9.2.0",
"react-router-dom": "^7.12.0",
"swiper": "^12.0.3"
},
"devDependencies": {
"@eslint/js": "^9.39.2",
"@tailwindcss/postcss": "^4.1.18",
"@types/react": "^19.2.9",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.2",
"eslint": "^9.39.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.26",
"globals": "^17.0.0",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.18",
"vite": "^7.3.1"
}
}
================================================
FILE: ecom-frontend/postcss.config.js
================================================
export default {
plugins: {
'@tailwindcss/postcss': {},
},
}
================================================
FILE: ecom-frontend/src/App.css
================================================
================================================
FILE: ecom-frontend/src/App.jsx
================================================
import React, { useState } from 'react'
import './App.css'
import Products from './components/products/Products'
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import Home from './components/home/Home'
import Navbar from './components/shared/Navbar'
import About from './components/About'
import Contact from './components/Contact'
import { Toaster } from 'react-hot-toast'
import Cart from './components/cart/Cart'
import LogIn from './components/auth/LogIn'
import PrivateRoute from './components/PrivateRoute'
import Register from './components/auth/Register'
import Checkout from './components/checkout/Checkout'
import PaymentConfirmation from './components/checkout/PaymentConfirmation'
import AdminLayout from './components/admin/AdminLayout'
import Dashboard from './components/admin/dashboard/Dashboard'
import AdminProducts from './components/admin/products/AdminProducts'
import Sellers from './components/admin/sellers/Sellers'
import Category from './components/admin/categories/Category'
import Orders from './components/admin/orders/Orders'
function App() {
return (
}/>
}/>
}/>
}/>
}/>
}>
}/>
}/>
}>
}/>
}/>
}>
}>
} />
} />
} />
} />
} />
)
}
export default App
================================================
FILE: ecom-frontend/src/api/api.js
================================================
import axios from "axios";
const api = axios.create({
baseURL: `${import.meta.env.VITE_BACK_END_URL}/api`,
withCredentials: true,
});
export default api;
================================================
FILE: ecom-frontend/src/components/About.jsx
================================================
import ProductCard from "./shared/ProductCard";
const products = [
{
image: "https://embarkx.com/sample/placeholder.png",
productName: "iPhone 13 Pro Max",
description:
"The iPhone 13 Pro Max offers exceptional performance with its A15 Bionic chip, stunning Super Retina XDR display, and advanced camera features for breathtaking photos.",
specialPrice: 720,
price: 780,
},
{
image: "https://embarkx.com/sample/placeholder.png",
productName: "Samsung Galaxy S21",
description:
"Experience the brilliance of the Samsung Galaxy S21 with its vibrant AMOLED display, powerful camera, and sleek design that fits perfectly in your hand.",
specialPrice: 699,
price: 799,
},
{
image: "https://embarkx.com/sample/placeholder.png",
productName: "Google Pixel 6",
description:
"The Google Pixel 6 boasts cutting-edge AI features, exceptional photo quality, and a stunning display, making it a perfect choice for Android enthusiasts.",
price: 599,
specialPrice: 400,
}
];
const About = () => {
return (
About Us
Welcome to our e-commerce store! We are dedicated to providing the
best products and services to our customers. Our mission is to offer
a seamless shopping experience while ensuring the highest quality of
our offerings.
Our Products
{products.map((product, index) => (
))
}
);
}
export default About;
================================================
FILE: ecom-frontend/src/components/BackDrop.jsx
================================================
import React from 'react'
const BackDrop = ({ data }) => {
return (
)
}
export default BackDrop
================================================
FILE: ecom-frontend/src/components/Contact.jsx
================================================
import { FaEnvelope, FaMapMarkedAlt, FaPhone } from "react-icons/fa";
const Contact = () => {
return(
Contact us
We would love to hear from you! Please fill out the form below or contact us directly
Contact Information
+4 8961 944 149
embarkxofficial@gmail.com
123 Main, Town, USA
);
}
export default Contact;
================================================
FILE: ecom-frontend/src/components/PrivateRoute.jsx
================================================
import React from 'react'
import { useSelector } from 'react-redux'
import { Navigate, Outlet, useLocation } from 'react-router-dom';
const PrivateRoute = ({ publicPage = false, adminOnly = false }) => {
const { user } = useSelector((state) => state.auth);
const isAdmin = user && user?.roles?.includes("ROLE_ADMIN");
const isSeller = user && user?.roles.includes("ROLE_SELLER");
const location = useLocation();
if (publicPage) {
return user ? :
}
if (adminOnly) {
if (isSeller && !isAdmin) {
const sellerAllowedPaths = ["/admin/orders", "/admin/products"];
const sellerAllowed = sellerAllowedPaths.some(path =>
location.pathname.startsWith(path)
);
if (!sellerAllowed) {
return
}
}
}
if (!isAdmin && !isSeller) {
return
}
return user ? : ;
}
export default PrivateRoute
================================================
FILE: ecom-frontend/src/components/UserMenu.jsx
================================================
import { Avatar, Button, Menu, MenuItem } from '@mui/material';
import React from 'react'
import { BiUser } from 'react-icons/bi';
import { FaShoppingCart, FaUserShield } from 'react-icons/fa';
import { IoExitOutline } from 'react-icons/io5';
import { useDispatch, useSelector } from 'react-redux';
import { Link, useNavigate } from 'react-router-dom';
import BackDrop from './BackDrop';
import { logOutUser } from '../store/actions';
const UserMenu = () => {
const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const { user } = useSelector((state) => state.auth);
const dispatch = useDispatch();
const navigate = useNavigate();
const isAdmin = user && user?.roles.includes("ROLE_ADMIN");
const isSeller = user && user?.roles.includes("ROLE_SELLER");
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const logOutHandler = () => {
dispatch(logOutUser(navigate));
};
return (
);
}
export default UserMenu
================================================
FILE: ecom-frontend/src/components/admin/AdminLayout.jsx
================================================
import React, { useState } from 'react'
import Sidebar from '../shared/Sidebar'
import { Outlet } from 'react-router-dom'
import { Description, Dialog, DialogBackdrop, DialogPanel, DialogTitle, TransitionChild } from '@headlessui/react';
import { RxCross1 } from 'react-icons/rx';
import { FaBars } from 'react-icons/fa';
const AdminLayout = () => {
let [sidebarOpen, setSidebarOpen] = useState(false);
return (
setSidebarOpen(false)}
className="relative z-50 xl:hidden">
setSidebarOpen(false)}
className='-m-2.5 p-2.5'>
Close Sidebar
setSidebarOpen(true)}
className='-m-2.5 text-gray-700 xl:hidden p-4'>
Open Sidebar
)
}
export default AdminLayout
================================================
FILE: ecom-frontend/src/components/admin/categories/AddCategoryForm.jsx
================================================
import React, { useEffect } from "react";
import { useForm } from "react-hook-form";
import { useDispatch } from "react-redux";
import toast from "react-hot-toast";
import {
createCategoryDashboardAction,
updateCategoryDashboardAction,
} from "../../../store/actions";
import InputField from "../../shared/InputField";
const AddCategoryForm = ({ setOpen, open, category, update = false }) => {
const dispatch = useDispatch();
const {
register,
handleSubmit,
reset,
setValue,
formState: { errors },
} = useForm({
mode: "onTouched",
});
const addNewCategoryHandler = (data) => {
if (!update) {
//dispatch createCategoryDashboardAction
dispatch(createCategoryDashboardAction(data, setOpen, reset, toast));
} else {
//dispatch updateCategoryDashboardAction
dispatch(
updateCategoryDashboardAction(data, setOpen, category.id, reset, toast)
);
}
};
useEffect(() => {
if (update && category) {
setValue("categoryName", category?.categoryName);
}
}, [update, category]);
return (
setOpen(false)}
type="button"
className={`border border-borderColor rounded-[5px] font-metropolis text-textColor py-[10px] px-4 text-sm font-medium`}
>
Cancel
{open ? "Loading.." : update ? "Update" : "Save"}
);
};
export default AddCategoryForm;
================================================
FILE: ecom-frontend/src/components/admin/categories/Category.jsx
================================================
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useLocation, useNavigate, useSearchParams } from "react-router-dom";
import { DataGrid } from "@mui/x-data-grid";
import { FaFolderOpen, FaThList } from "react-icons/fa";
import toast from "react-hot-toast";
import Modal from "../../shared/Modal";
import AddCategoryForm from "./AddCategoryForm";
import Loader from "../../shared/Loader";
import { DeleteModal } from "../../../components/shared/DeleteModal";
import useCategoryFilter from "../../../hooks/useCategoryFilter";
import ErrorPage from "../../shared/ErrorPage";
import { deleteCategoryDashboardAction } from "../../../store/actions";
import { categoryTableColumns } from "../../helper/tableColumn";
const Category = () => {
const [searchParams] = useSearchParams();
const pathname = useLocation().pathname;
const params = new URLSearchParams(searchParams);
const navigate = useNavigate();
const dispatch = useDispatch();
const [openModal, setOpenModal] = useState(false);
const [openUpdateModal, setOpenUpdateModal] = useState(false);
const [openDeleteModal, setOpenDeleteModal] = useState(false);
const [selectedCategory, setSelectedCategory] = useState(null);
const { categoryLoader, errorMessage } = useSelector((state) => state.errors);
const { categories, pagination } = useSelector((state) => state.products);
const [currentPage, setCurrentPage] = useState(
pagination?.pageNumber + 1 || 1
);
// Calling the `useCategoryFilter` custom hook to handle category fetching and pagination based on the current URL parameters.
useCategoryFilter();
const tableRecords = categories?.map((item) => ({
id: item.categoryId,
categoryName: item.categoryName,
version: item.version,
}));
const handleEdit = (category) => {
setOpenUpdateModal(true);
setSelectedCategory(category);
};
const handleDelete = (category) => {
setSelectedCategory(category);
setOpenDeleteModal(true);
};
const onDeleteHandler = () => {
dispatch(
deleteCategoryDashboardAction(setOpenDeleteModal, selectedCategory?.id, toast)
);
};
const handlePaginationChange = (paginationModel) => {
const page = paginationModel.page + 1; // Adjust to 1-based index
setCurrentPage(page);
params.set("page", page.toString());
navigate(`${pathname}?${params}`);
};
const emptyCategories = !categories || categories?.length === 0;
if (errorMessage) return ;
return (
setOpenModal(true)}
className="bg-custom-blue hover:bg-blue-800 text-white font-semibold py-2 px-4 flex items-center gap-2 rounded-md shadow-md transition-colors hover:text-slate-300 duration-300"
>
Add Category
{!emptyCategories && (
All Categories
)}
{categoryLoader ? (
) : (
<>
{emptyCategories ? (
No Categories Created Yet
) : (
)}
>
)}
);
};
export default Category;
================================================
FILE: ecom-frontend/src/components/admin/dashboard/Dashboard.jsx
================================================
import React, { useEffect } from 'react'
import DashboardOverview from './DashboardOverview'
import { FaBoxOpen, FaDollarSign, FaShoppingCart } from 'react-icons/fa';
import { MdAttachMoney } from 'react-icons/md';
import { useDispatch, useSelector } from 'react-redux';
import { analyticsAction } from '../../../store/actions';
import Loader from '../../shared/Loader';
import ErrorPage from '../../shared/ErrorPage';
const Dashboard = () => {
const dispatch = useDispatch();
const {isLoading, errorMessage} = useSelector((state) => state.errors);
const {
analytics: { productCount, totalRevenue, totalOrders },
} = useSelector((state) => state.admin);
useEffect(() => {
dispatch(analyticsAction());
}, [dispatch]);
if (isLoading) {
return
}
if (errorMessage) {
return ;
}
return (
)
}
export default Dashboard
================================================
FILE: ecom-frontend/src/components/admin/dashboard/DashboardOverview.jsx
================================================
import { Icon } from '@mui/material';
import React from 'react'
import { formatRevenue } from '../../../utils/formatPrice';
const DashboardOverview = ({ title, amount, Icon, revenue = false }) => {
const convertedAmount = revenue ? Number(amount).toFixed(2) : amount;
return (
<>
{title}
{revenue ? "$" : null}
{revenue ? formatRevenue(convertedAmount) : convertedAmount}
>
)
}
export default DashboardOverview
================================================
FILE: ecom-frontend/src/components/admin/orders/OrderTable.jsx
================================================
import { DataGrid } from '@mui/x-data-grid'
import { adminOrderTableColumn } from '../../helper/tableColumn';
import { useState } from 'react';
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';
import Modal from '../../shared/Modal';
import UpdateOrderForm from './UpdateOrderForm';
const OrderTable = ({ adminOrder, pagination}) => {
const [updateOpenModal, setUpdateOpenModal] = useState(false);
const [selectedItem, setSelectedItem] = useState("");
const [loader, setLoader] = useState(false);
const navigate = useNavigate();
const [currentPage, setCurrentPage] = useState(
pagination?.pageNumber + 1 || 1
);
const [searchParams] = useSearchParams();
const params = new URLSearchParams(searchParams);
const pathname = useLocation().pathname;
const tableRecords = adminOrder?.map((item) => {
return {
id: item.orderId,
email: item.email,
totalAmount: item.totalAmount,
status: item.orderStatus,
date: item.orderDate,
}
});
const handlePaginationChange = (paginationModel) => {
const page = paginationModel.page + 1;
setCurrentPage(page);
params.set("page", page.toString());
navigate(`${pathname}?${params}`)
}
const handleEdit = (order) => {
setSelectedItem(order);
setUpdateOpenModal(true);
}
return (
)
}
export default OrderTable
================================================
FILE: ecom-frontend/src/components/admin/orders/Orders.jsx
================================================
import React from 'react'
import { FaShoppingCart } from 'react-icons/fa';
import OrderTable from './OrderTable';
import { useSelector } from 'react-redux';
import useOrderFilter from '../../../hooks/useOrderFilter';
const Orders = () => {
// const adminOrder = [ { "orderId": 17, "email": "user1@example.com", "orderItems": [ { "orderItemId": 7, "product": { "productId": 153, "productName": "Running Shoes", "image": "0abca637-0c4e-4054-ae03-bdfc51cb3396.png", "description": "Comfortable and lightweight running shoes for daily fitness", "quantity": 49, "price": 80, "discount": 10, "specialPrice": 72 }, "quantity": 1, "discount": 10, "orderedProductPrice": 72 } ], "orderDate": "2025-02-15", "payment": { "paymentId": 17, "paymentMethod": "online", "pgPaymentId": "pi_3QsfCYLK9jOar8Y81NsK7PXG", "pgStatus": "succeeded", "pgResponseMessage": "Payment successful", "pgName": "Stripe" }, "totalAmount": 72, "orderStatus": "Order Accepted !", "addressId": 1 }, { "orderId": 18, "email": "user1@example.com", "orderItems": [ { "orderItemId": 8, "product": { "productId": 102, "productName": "Blender", "image": "39356dd0-6682-4821-adc8-b198ee85b358.png", "description": "High-performance Blender having powerful features for modern family", "quantity": 28, "price": 500, "discount": 19, "specialPrice": 405 }, "quantity": 1, "discount": 19, "orderedProductPrice": 405 } ], "orderDate": "2025-07-18", "payment": { "paymentId": 18, "paymentMethod": "online", "pgPaymentId": "pi_3Rm6zYLK9jOar8Y81iyMdnMg", "pgStatus": "succeeded", "pgResponseMessage": "Payment successful", "pgName": "Stripe" }, "totalAmount": 405, "orderStatus": "Order Accepted !", "addressId": 5 } ];
// const pagination = { pageNumber: 0, pageSize: 50, totalElements: 11, totalPages: 1, lastPage: true };
const {adminOrder, pagination} = useSelector((state) => state.order);
useOrderFilter();
const emptyOrder = !adminOrder || adminOrder?.length ===0;
return (
{emptyOrder ? (
No Orders Placed Yet
) : (
)}
)
}
export default Orders
================================================
FILE: ecom-frontend/src/components/admin/orders/UpdateOrderForm.jsx
================================================
import { Button, FormControl, FormHelperText, InputLabel, MenuItem, Select } from '@mui/material'
import React, { useState } from 'react'
import { FaSpinner } from 'react-icons/fa';
import Spinners from '../../shared/Spinners';
import { useDispatch, useSelector } from 'react-redux';
import { updateOrderStatusFromDashboard } from '../../../store/actions';
import toast from 'react-hot-toast';
const ORDER_STATUSES = [
"Pending",
"Processing",
"Shipped",
"Delivered",
"Cancelled",
"Accepted",
];
const UpdateOrderForm = ({ setOpen, selectedId, selectedItem, loader, setLoader}) => {
const [orderStatus, setOrderStatus] = useState(selectedItem?.status || 'Accepted');
const [error, setError] = useState("");
const dispatch = useDispatch();
const { user } = useSelector((state) => state.auth);
const isAdmin = user && user?.roles?.includes("ROLE_ADMIN");
const updateOrderStatus = (e) => {
e.preventDefault();
if (!orderStatus) {
setError("Order status is required");
return;
}
dispatch(updateOrderStatusFromDashboard(
selectedId,
orderStatus,
toast,
setLoader,
isAdmin
));
};
return (
Order Status
{
setOrderStatus(e.target.value);
setError("");
}}>
{
ORDER_STATUSES.map((status) => (
{status}
))
}
{error && {error} }
setOpen(false)}
variant='outlined'
className='text-white py-[10px] px-4 text-sm font-medium'>
Cancel
{loader ? (
Loading...
) : (
"Update"
)}
)
}
export default UpdateOrderForm
================================================
FILE: ecom-frontend/src/components/admin/products/AddProductForm.jsx
================================================
import React, { useEffect, useState } from 'react'
import { useForm } from 'react-hook-form'
import InputField from '../../shared/InputField';
import { Button } from '@mui/material';
import { useDispatch, useSelector } from 'react-redux';
import { addNewProductFromDashboard, fetchCategories, updateProductFromDashboard } from '../../../store/actions';
import toast from 'react-hot-toast';
import Spinners from '../../shared/Spinners';
import SelectTextField from '../../shared/SelectTextField';
import Skeleton from '../../shared/Skeleton';
import ErrorPage from '../../shared/ErrorPage';
const AddProductForm = ({ setOpen, product, update=false}) => {
const [loader, setLoader] = useState(false);
const [selectedCategory, setSelectedCategory] = useState();
const { categories } = useSelector((state) => state.products);
const { categoryLoader, errorMessage } = useSelector((state) => state.errors);
const { user } = useSelector((state) => state.auth);
const isAdmin = user && user?.roles?.includes("ROLE_ADMIN");
const dispatch = useDispatch();
const {
register,
handleSubmit,
reset,
setValue,
formState: { errors }
} = useForm({
mode: "onTouched"
});
const saveProductHandler = (data) => {
if(!update) {
// create new product logic
const sendData = {
...data,
categoryId: selectedCategory.categoryId,
};
dispatch(addNewProductFromDashboard(
sendData, toast, reset, setLoader, setOpen, isAdmin
));
} else {
const sendData = {
...data,
id: product.id,
};
dispatch(updateProductFromDashboard(sendData, toast, reset, setLoader, setOpen, isAdmin));
}
};
useEffect(() => {
if (update && product) {
setValue("productName", product?.productName);
setValue("price", product?.price);
setValue("quantity", product?.quantity);
setValue("discount", product?.discount);
setValue("specialPrice", product?.specialPrice);
setValue("description", product?.description);
}
}, [update, product]);
useEffect(() => {
if (!update) {
dispatch(fetchCategories());
}
}, [dispatch, update]);
useEffect(() => {
if (!categoryLoader && categories) {
setSelectedCategory(categories[0]);
}
}, [categories, categoryLoader]);
if (categoryLoader) return
if (errorMessage) return
return (
{!update && (
)}
Description
{errors["description"]?.message && (
{errors["description"]?.message}
)}
setOpen(false)}
variant='outlined'
className='text-white py-[10px] px-4 text-sm font-medium'>
Cancel
{loader ? (
Loading...
) : (
"Save"
)}
)
}
export default AddProductForm
================================================
FILE: ecom-frontend/src/components/admin/products/AdminProducts.jsx
================================================
import React, { useState } from 'react'
import { MdAddShoppingCart } from 'react-icons/md';
import { useDispatch, useSelector } from 'react-redux';
import Loader from '../../shared/Loader';
import { FaBoxOpen } from 'react-icons/fa';
import { DataGrid } from '@mui/x-data-grid';
import { adminProductTableColumn } from '../../helper/tableColumn';
import { useDashboardProductFilter } from '../../../hooks/useProductFilter';
import Modal from '../../shared/Modal';
import AddProductForm from './AddProductForm';
import DeleteModal from '../../shared/DeleteModal';
import { deleteProduct } from '../../../store/actions';
import toast from 'react-hot-toast';
import ImageUploadForm from './ImageUploadForm';
import ProductViewModal from '../../shared/ProductViewModal';
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';
const AdminProducts = () => {
// const products = [{ "productId": 52, "productName": "iPad Pro", "image": "http://localhost:8080/images/7a7b38c4-2342-4d10-89e9-2c5b3c4fdb44.png", "description": "High-performance Tablet with a 4K display and powerful camera", "quantity": 30, "price": 1800.0, "discount": 43.0, "specialPrice": 1026.0 }, { "productId": 2, "productName": "iPhone 16 Pro Max", "image": "http://localhost:8080/images/22185fd1-024a-4708-9a10-832b8a50bfde.png", "description": "High-performance phone with a 4K display and powerful camera", "quantity": 19, "price": 1400.0, "discount": 23.0, "specialPrice": 1078.0 }];
// const pagination = { pageNumber: 0, pageSize: 50, totalElements: 11, totalPages: 1, lastPage: true };
const {products, pagination} = useSelector((state) => state.products);
const { isLoading, errorMessage } = useSelector((state) => state.errors);
const [currentPage, setCurrentPage] = useState(
pagination?.pageNumber + 1 || 1
);
const dispatch = useDispatch();
const [selectedProduct, setSelectedProduct] = useState('');
const [openUpdateModal, setOpenUpdateModal] = useState(false);
const [openAddModal, setOpenAddModal] = useState(false);
const [openDeleteModal, setOpenDeleteModal] = useState(false);
const [openProductViewModal, setOpenProductViewModal] = useState(false);
const [openImageUploadModal, setOpenImageUploadModal] = useState(false);
const [loader, setLoader] = useState(false);
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const params = new URLSearchParams(searchParams);
const pathname = useLocation().pathname;
const { user } = useSelector((state) => state.auth);
const isAdmin = user && user?.roles?.includes("ROLE_ADMIN");
useDashboardProductFilter();
const tableRecords = products?.map((item) => {
return {
id: item.productId,
productName: item.productName,
description: item.description,
discount: item.discount,
image: item.image,
price: item.price,
quantity: item.quantity,
specialPrice: item.specialPrice,
}
});
const handleEdit = (product) => {
setSelectedProduct(product);
setOpenUpdateModal(true);
};
const handleDelete = (product) => {
setSelectedProduct(product);
setOpenDeleteModal(true);
};
const handleImageUpload = (product) => {
setSelectedProduct(product);
setOpenImageUploadModal(true);
};
const handleProductView = (product) => {
setSelectedProduct(product);
setOpenProductViewModal(true);
};
const handlePaginationChange = (paginationModel) => {
const page = paginationModel.page + 1;
setCurrentPage(page);
params.set("page", page.toString());
navigate(`${pathname}?${params}`)
};
const onDeleteHandler = () => {
dispatch(deleteProduct(setLoader, selectedProduct?.id, toast, setOpenDeleteModal, isAdmin));
};
const emptyProduct = !products || products?.length ===0;
return (
setOpenAddModal(true)}
className='bg-custom-blue hover:bg-blue-800 text-white font-semibold py-2 px-4 flex items-center gap-2 rounded-md shadow-md transition-colors hover:text-slate-300 duration-300'>
Add Product
{!emptyProduct && (
All Products
)}
{isLoading ? (
) : (
<>
{emptyProduct ? (
No products created yet
) : (
)}
>
)}
)
}
export default AdminProducts
================================================
FILE: ecom-frontend/src/components/admin/products/ImageUploadForm.jsx
================================================
import React, { useRef, useState } from 'react'
import { FaCloudUploadAlt } from 'react-icons/fa'
import Spinners from '../../shared/Spinners';
import { Button } from '@mui/material';
import toast from 'react-hot-toast';
import { useDispatch, useSelector } from 'react-redux';
import { updateProductImageFromDashboard } from '../../../store/actions';
const ImageUploadForm = ({ setOpen, product }) => {
const [loader, setLoader] = useState(false);
const fileInputRef = useRef();
const [previewImage, setPreviewImage] = useState(null);
const [selectedFile, setSelectedFile] = useState(null);
const dispatch = useDispatch();
const { user } = useSelector((state) => state.auth);
const isAdmin = user && user?.roles?.includes("ROLE_ADMIN");
const onHandleImageChange = (e) => {
const file = e.target.files[0];
if (file && ["image/jpeg", "image/jpg", "image/png"].includes(file.type)) {
const reader = new FileReader();
reader.onloadend = () => {
setPreviewImage(reader.result);
};
reader.readAsDataURL(file);
setSelectedFile(file);
} else {
toast.error("Please select a valid image file (.jpeg, .jpg, .png)");
setPreviewImage(null);
setSelectedFile(null);
}
};
const addNewImageHandler = async (event) => {
event.preventDefault();
if (!selectedFile) {
toast.error("Please select an image before saving.");
return;
}
const formData = new FormData();
formData.append("image", selectedFile);
dispatch(updateProductImageFromDashboard(formData, product.id, toast, setLoader, setOpen, isAdmin));
};
const handleClearImage = () => {
setPreviewImage(null);
setSelectedFile(null);
fileInputRef.current.value = null;
};
return (
setOpen(false)}
variant='outlined'
className='text-white py-[10px] px-4 text-sm font-medium'>
Cancel
{loader ? (
Loading...
) : (
"Update"
)}
)
}
export default ImageUploadForm
================================================
FILE: ecom-frontend/src/components/admin/sellers/AddSellerForm.jsx
================================================
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { useForm } from "react-hook-form";
import toast from "react-hot-toast";
import { addNewDashboardSeller } from "../../../store/actions";
import InputField from "../../shared/InputField";
import Spinners from "../../shared/Spinners";
const AddSellerForm = ({ setOpen }) => {
const dispatch = useDispatch();
const [loader, setLoader] = useState(false);
const {
register,
handleSubmit,
reset,
formState: { errors },
} = useForm({
mode: "onTouched",
});
const addSellerHandler = (data) => {
const sendData = {
...data,
role: ["seller"],
};
dispatch(addNewDashboardSeller(sendData, toast, reset, setOpen, setLoader));
};
return (
setOpen(false)}
type="button"
className={`border border-blue-500 rounded-[5px] font-metropolis text-textColor py-[10px] px-4 text-sm font-medium`}
>
Cancel
{loader ? (
Loading..
) : (
"Add New Seller"
)}
);
};
export default AddSellerForm;
================================================
FILE: ecom-frontend/src/components/admin/sellers/SellerTable.jsx
================================================
import React, { useState } from "react";
import { useLocation, useNavigate, useSearchParams } from "react-router-dom";
import { DataGrid } from "@mui/x-data-grid";
import { sellerTableColumns } from "../../helper/tableColumn";
const SellerTable = ({ sellers, pagination }) => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const pathname = useLocation().pathname;
const params = new URLSearchParams(searchParams);
const [currentPage, setCurrentPage] = useState(pagination?.pageNumber || 1);
const tableRecords = sellers?.map((item) => {
return {
id: item.userId,
username: item.username,
email: item.email,
};
});
const handlePaginationChange = (paginationModel) => {
const page = paginationModel.page + 1;
setCurrentPage(page);
params.set("page", page.toString());
navigate(`${pathname}?${params}`);
};
return (
);
};
export default SellerTable;
================================================
FILE: ecom-frontend/src/components/admin/sellers/Sellers.jsx
================================================
import React, { useState } from "react";
import { useSelector } from "react-redux";
import { MdPersonAdd } from "react-icons/md";
import SellerTable from "./SellerTable";
import ErrorPage from "../../shared/ErrorPage";
import Loader from "../../shared/Loader";
import Modal from "../../shared/Modal";
import AddSellerForm from "./AddSellerForm";
import useSellerFilter from "./useSellerFilter";
const Sellers = () => {
const [openModal, setOpenModal] = useState(false);
const { sellers, pagination } = useSelector((state) => state.seller);
const { isLoading, errorMessage } = useSelector((state) => state.errors);
// Calling the `useSellerFilter` custom hook to fetch sellers and pagination based on the current URL parameters.
useSellerFilter();
const emptySellers = !sellers || sellers?.length === 0;
if (errorMessage) {
return ;
}
return (
setOpenModal(true)}
className="bg-custom-blue hover:bg-blue-800 text-white font-semibold py-2 px-4 flex items-center gap-2 rounded-md shadow-md transition-colors hover:text-slate-300 duration-300"
>
Add Seller
{!emptySellers && (
All Sellers
)}
{isLoading ? (
) : (
<>
{emptySellers ? (
<>
No Seller Created Yet
>
) : (
)}
>
)}
);
};
export default Sellers;
================================================
FILE: ecom-frontend/src/components/admin/sellers/useSellerFilter.jsx
================================================
import { useEffect } from "react";
import { useSearchParams } from "react-router-dom";
import { useDispatch } from "react-redux";
import { getAllSellersDashboard } from "../../../store/actions";
const useSellerFilter = () => {
const [searchParams] = useSearchParams(); // Access search params from the URL
const dispatch = useDispatch(); // Get the dispatch function to call actions
useEffect(() => {
const params = new URLSearchParams(); // Create new URLSearchParams object
// Get current page from URL search params, defaulting to 1 if not present
const currentPage = searchParams.get("page")
? Number(searchParams.get("page"))
: 1;
params.set("pageNumber", currentPage - 1); // Pagination starts from 0 for API
// Convert params to a query string
const queryString = params.toString();
// Dispatch action to fetch all seller using the constructed query string
dispatch(getAllSellersDashboard(queryString));
}, [dispatch, searchParams]);
};
export default useSellerFilter;
================================================
FILE: ecom-frontend/src/components/auth/LogIn.jsx
================================================
import { useState } from "react";
import { useForm } from "react-hook-form";
import { AiOutlineLogin } from "react-icons/ai";
import { Link, useNavigate } from "react-router-dom";
import InputField from "../shared/InputField";
import { useDispatch } from "react-redux";
import { authenticateSignInUser } from "../../store/actions";
import toast from "react-hot-toast";
import Spinners from "../shared/Spinners";
const LogIn = () => {
const navigate = useNavigate();
const dispatch = useDispatch();
const [loader, setLoader] = useState(false);
const {
register,
handleSubmit,
reset,
formState: {errors},
} = useForm({
mode: "onTouched",
});
const loginHandler = async (data) => {
console.log("Login Click");
dispatch(authenticateSignInUser(data, toast, reset, navigate, setLoader));
};
return (
{loader ? (
<>
Loading...
>
) : (
<>Login>
)}
Don't have an account?
SignUp
);
}
export default LogIn;
================================================
FILE: ecom-frontend/src/components/auth/Register.jsx
================================================
import React, { useState } from 'react'
import { useForm } from 'react-hook-form';
import { FaUserPlus } from 'react-icons/fa';
import { Link, useNavigate } from 'react-router-dom';
import InputField from '../shared/InputField';
import { useDispatch } from 'react-redux';
import { registerNewUser } from '../../store/actions';
import toast from 'react-hot-toast';
import Spinners from '../shared/Spinners';
const Register = () => {
const navigate = useNavigate();
const dispatch = useDispatch();
const [loader, setLoader] = useState(false);
const {
register,
handleSubmit,
reset,
formState: {errors},
} = useForm({
mode: "onTouched",
});
const registerHandler = async (data) => {
console.log("Register Click");
dispatch(registerNewUser(data, toast, reset, navigate, setLoader));
};
return (
Register Here
{loader ? (
<>
Loading...
>
) : (
<>Register>
)}
Already have an account?
Login
);
}
export default Register
================================================
FILE: ecom-frontend/src/components/cart/Cart.jsx
================================================
import { MdArrowBack, MdShoppingCart } from "react-icons/md";
import { useDispatch, useSelector } from "react-redux";
import { Link } from "react-router-dom";
import ItemContent from "./ItemContent";
import CartEmpty from "./CartEmpty";
import { formatPrice } from "../../utils/formatPrice";
const Cart = () => {
const dispatch = useDispatch();
const { cart } = useSelector((state) => state.carts);
const newCart = { ...cart };
newCart.totalPrice = cart?.reduce(
(acc, cur) => acc + Number(cur?.specialPrice) * Number(cur?.quantity), 0
);
if (!cart || cart.length === 0) return ;
return (
Your Cart
All your selected items
Product
Price
Quantity
Total
{cart && cart.length > 0 &&
cart.map((item, i) => )}
Subtotal
{formatPrice(newCart?.totalPrice)}
Taxes and shipping calculated at checkout
{}}
className="font-semibold w-[300px] py-2 px-4 rounded-xs bg-custom-blue text-white flex items-center justify-center gap-2 hover:text-gray-300 transition duration-500">
Checkout
Continue Shopping
);
};
export default Cart;
================================================
FILE: ecom-frontend/src/components/cart/CartEmpty.jsx
================================================
import { MdArrowBack, MdShoppingCart } from "react-icons/md";
import { Link } from "react-router-dom";
const CartEmpty = () => {
return (
Your cart is empty
Add some products to get started
Start Shopping
)
}
export default CartEmpty;
================================================
FILE: ecom-frontend/src/components/cart/ItemContent.jsx
================================================
import { useState } from "react";
import { HiOutlineTrash } from "react-icons/hi";
import SetQuantity from "./SetQuantity";
import { useDispatch } from "react-redux";
import { decreaseCartQuantity, increaseCartQuantity, removeFromCart } from "../../store/actions";
import toast from "react-hot-toast";
import { formatPrice } from "../../utils/formatPrice";
import truncateText from "../../utils/truncateText";
const ItemContent = ({
productId,
productName,
image,
description,
quantity,
price,
discount,
specialPrice,
cartId,
}) => {
const [currentQuantity, setCurrentQuantity] = useState(quantity);
const dispatch = useDispatch();
const handleQtyIncrease = (cartItems) => {
dispatch(increaseCartQuantity(
cartItems,
toast,
currentQuantity,
setCurrentQuantity
));
};
const handleQtyDecrease = (cartItems) => {
if (currentQuantity > 1) {
const newQuantity = currentQuantity - 1;
setCurrentQuantity(newQuantity);
dispatch(decreaseCartQuantity(cartItems, newQuantity));
}
};
const removeItemFromCart = (cartItems) => {
dispatch(removeFromCart(cartItems, toast));
};
return (
{truncateText(productName)}
removeItemFromCart({
image,
productName,
description,
specialPrice,
price,
productId,
quantity,
})}
className="flex items-center font-semibold space-x-2 px-4 py-1 text-xs border border-rose-600 text-rose-600 rounded-md hover:bg-red-50 transition-colors duration-200">
Remove
{formatPrice(Number(specialPrice))}
handleQtyIncrease({
image,
productName,
description,
specialPrice,
price,
productId,
quantity,
})}
handleQtyDecrease={() => {handleQtyDecrease({
image,
productName,
description,
specialPrice,
price,
productId,
quantity,
})}}/>
{formatPrice(Number(currentQuantity) * Number(specialPrice))}
)
};
export default ItemContent;
================================================
FILE: ecom-frontend/src/components/cart/SetQuantity.jsx
================================================
const btnStyles = "border-[1.2px] border-slate-800 px-3 py-1 rounded-sm";
const SetQuantity = ({
quantity,
cardCounter,
handeQtyIncrease,
handleQtyDecrease,
}) => {
return (
{cardCounter ? null :
QUANTITY
}
);
};
export default SetQuantity;
================================================
FILE: ecom-frontend/src/components/checkout/AddAddressForm.jsx
================================================
import React, { useEffect } from 'react'
import InputField from '../shared/InputField'
import { useForm } from 'react-hook-form';
import { FaAddressCard } from 'react-icons/fa';
import { useDispatch, useSelector } from 'react-redux';
import Spinners from '../shared/Spinners';
import toast from 'react-hot-toast';
import { addUpdateUserAddress } from '../../store/actions';
const AddAddressForm = ({ address, setOpenAddressModal }) => {
const dispatch = useDispatch();
const { btnLoader } = useSelector((state) => state.errors);
const {
register,
handleSubmit,
reset,
setValue,
formState: {errors},
} = useForm({
mode: "onTouched",
});
const onSaveAddressHandler = async (data) => {
dispatch(addUpdateUserAddress(
data,
toast,
address?.addressId,
setOpenAddressModal
));
};
useEffect(() => {
if (address?.addressId) {
setValue("buildingName", address?.buildingName);
setValue("city", address?.city);
setValue("street", address?.street);
setValue("state", address?.state);
setValue("pincode", address?.pincode);
setValue("country", address?.country);
}
}, [address]);
return (
{!address?.addressId ?
"Add Address" :
"Update Address"
}
{btnLoader ? (
<>
Loading...
>
) : (
<>Save>
)}
)
}
export default AddAddressForm
================================================
FILE: ecom-frontend/src/components/checkout/AddressInfo.jsx
================================================
import React, { useState } from 'react'
import Skeleton from '../shared/Skeleton';
import { FaAddressBook } from 'react-icons/fa';
import AddressInfoModal from './AddressInfoModal';
import AddAddressForm from './AddAddressForm';
import { useDispatch, useSelector } from 'react-redux';
import AddressList from './AddressList';
import { DeleteModal } from './DeleteModal';
import toast from 'react-hot-toast';
import { deleteUserAddress } from '../../store/actions';
const AddressInfo = ({ address }) => {
const [openAddressModal, setOpenAddressModal] = useState(false);
const [openDeleteModal, setOpenDeleteModal] = useState(false);
const [selectedAddress, setSelectedAddress] = useState("");
const addNewAddressHandler = () => {
setSelectedAddress("");
setOpenAddressModal(true);
};
const dispatch = useDispatch();
const deleteAddressHandler = () => {
dispatch(deleteUserAddress(
toast,
selectedAddress?.addressId,
setOpenDeleteModal
))
};
const noAddressExist = !address || address.length === 0;
const { isLoading, btnLoader } = useSelector((state) => state.errors);
return (
{noAddressExist ? (
No Address Added Yet
Please add your address to complete purchase
Add Address
) : (
Select Address
{isLoading ? (
) : (
<>
{address.length > 0 && (
Add More
)}
>
)}
)}
)
}
export default AddressInfo
================================================
FILE: ecom-frontend/src/components/checkout/AddressInfoModal.jsx
================================================
import { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react';
import React from 'react'
import { FaTimes } from 'react-icons/fa';
const AddressInfoModal = ({ open, setOpen, children }) => {
return (
setOpen(false)} className="relative z-50">
{/* The backdrop, rendered as a fixed sibling to the panel container */}
{/* Full-screen container to center the panel */}
{/* The actual dialog panel */}
{children}
setOpen(false)} type='button'>
);
}
export default AddressInfoModal
================================================
FILE: ecom-frontend/src/components/checkout/AddressList.jsx
================================================
import React from 'react'
import { FaBuilding, FaCheckCircle, FaEdit, FaStreetView, FaTrash } from 'react-icons/fa';
import { MdLocationCity, MdPinDrop, MdPublic } from "react-icons/md";
import { useDispatch, useSelector } from 'react-redux'
import { selectUserCheckoutAddress } from '../../store/actions';
const AddressList = ({ addresses, setSelectedAddress, setOpenAddressModal, setOpenDeleteModal }) => {
const dispatch = useDispatch();
const { selectedUserCheckoutAddress } = useSelector((state) => state.auth);
const onEditButtonHandler = (addresses) => {
setSelectedAddress(addresses);
setOpenAddressModal(true);
};
const onDeleteButtonHandler = (addresses) => {
setSelectedAddress(addresses);
setOpenDeleteModal(true);
};
const handleAddressSelection = (addresses) => {
dispatch(selectUserCheckoutAddress(addresses));
};
return (
{addresses.map((address) => (
handleAddressSelection(address)}
className={`p-4 border rounded-md cursor-pointer relative ${
selectedUserCheckoutAddress?.addressId === address.addressId
? "bg-green-100"
: "bg-white"
}`}>
{address.buildingName}
{selectedUserCheckoutAddress?.addressId === address.addressId && (
)}
{address.city}, {address.state}
onEditButtonHandler(address)}>
onDeleteButtonHandler(address)}>
))}
)
}
export default AddressList
================================================
FILE: ecom-frontend/src/components/checkout/Checkout.jsx
================================================
import { Button, Step, StepLabel, Stepper } from '@mui/material';
import React, { useEffect, useState } from 'react'
import AddressInfo from './AddressInfo';
import { useDispatch, useSelector } from 'react-redux';
import { getUserAddresses } from '../../store/actions';
import toast from 'react-hot-toast';
import Skeleton from '../shared/Skeleton';
import ErrorPage from '../shared/ErrorPage';
import PaymentMethod from './PaymentMethod';
import OrderSummary from './OrderSummary';
import StripePayment from './StripePayment';
import PaypalPayment from './PaypalPayment';
const Checkout = () => {
const [activeStep, setActiveStep] = useState(0);
const dispatch = useDispatch();
const { isLoading, errorMessage } = useSelector((state) => state.errors);
const { cart, totalPrice } = useSelector((state) => state.carts);
const { address, selectedUserCheckoutAddress } = useSelector(
(state) => state.auth
)
const { paymentMethod } = useSelector((state) => state.payment);
const handleBack = () => {
setActiveStep((prevStep) => prevStep - 1);
};
const handleNext = () => {
if(activeStep === 0 && !selectedUserCheckoutAddress) {
toast.error("Please select checkout address before proceeding.");
return;
}
if(activeStep === 1 && (!selectedUserCheckoutAddress || !paymentMethod)) {
toast.error("Please select payment address before proceeding.");
return;
}
setActiveStep((prevStep) => prevStep + 1);
};
const steps = [
"Address",
"Payment Method",
"Order Summary",
"Payment",
];
useEffect(() => {
dispatch(getUserAddresses());
}, [dispatch]);
return (
{steps.map((label, index) => (
{label}
))}
{isLoading ? (
) : (
{activeStep === 0 &&
}
{activeStep === 1 &&
}
{activeStep === 2 &&
}
{activeStep === 3 &&
<>
{paymentMethod === "Stripe" ? (
) : (
)}
>}
)}
Back
{activeStep !== steps.length - 1 && (
Proceed
)}
{errorMessage &&
}
);
}
export default Checkout;
================================================
FILE: ecom-frontend/src/components/checkout/DeleteModal.jsx
================================================
import React from "react";
import { FaExclamationTriangle } from "react-icons/fa";
import { FaTimes } from "react-icons/fa";
import {
Dialog,
DialogBackdrop,
DialogPanel,
DialogTitle,
} from "@headlessui/react";
export const DeleteModal = ({
open,
setOpen,
title,
onDeleteHandler,
loader,
}) => {
return (
setOpen(false)}
className="rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-hidden focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
Close
{title}
Are you sure you want to delete?
{loader ? "Loading..." : "Delete"}
setOpen(false)}
className="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-xs ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto"
>
Cancel
);
};
================================================
FILE: ecom-frontend/src/components/checkout/OrderSummary.jsx
================================================
import React from 'react'
import { formatPriceCalculation } from '../../utils/formatPrice'
const OrderSummary = ({ totalPrice, cart, address, paymentMethod}) => {
return (
Billing Address
Building Name:
{address?.buildingName}
City:
{address?.city}
Street:
{address?.street}
State:
{address?.state}
Pincode:
{address?.pincode}
Country:
{address?.country}
Payment Method
Method:
{paymentMethod}
Order Items
{cart?.map((item) => (
{item?.productName}
{item?.quantity} x ${item?.specialPrice} = ${
formatPriceCalculation(item?.quantity, item?.specialPrice)
}
))}
Order Summary
Products
${formatPriceCalculation(totalPrice, 1)}
Tax (0%)
$0.00
SubTotal
${formatPriceCalculation(totalPrice, 1)}
)
}
export default OrderSummary
================================================
FILE: ecom-frontend/src/components/checkout/PaymentConfirmation.jsx
================================================
import React, { useEffect, useState } from 'react'
import { FaCheckCircle } from 'react-icons/fa';
import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom'
import { stripePaymentConfirmation } from '../../store/actions';
import toast from 'react-hot-toast';
const PaymentConfirmation = () => {
const location = useLocation();
const searchParams = new URLSearchParams(location.search);
const dispatch = useDispatch();
const [errorMessage, setErrorMessage ] = useState("");
const { cart } = useSelector((state) => state.carts);
const [ loading, setLoading] = useState(false);
const paymentIntent = searchParams.get("payment_intent");
const clientSecret = searchParams.get("payment_intent_client_secret");
const redirectStatus = searchParams.get("redirect_status");
const selectedUserCheckoutAddress = localStorage.getItem("CHECKOUT_ADDRESS")
? JSON.parse(localStorage.getItem("CHECKOUT_ADDRESS"))
: [];
useEffect(() => {
if (paymentIntent &&
clientSecret &&
redirectStatus &&
cart &&
cart?.length > 0
) {
console.log(selectedUserCheckoutAddress);
const sendData = {
addressId: selectedUserCheckoutAddress.addressId,
pgName: "Stripe",
pgPaymentId: paymentIntent,
pgStatus: "succeeded",
pgResponseMessage: "Payment successful"
};
console.log(sendData);
dispatch(stripePaymentConfirmation(sendData, setErrorMessage, setLoading, toast));
}
}, [paymentIntent, clientSecret, redirectStatus, cart]);
return (
{loading ? (
) : (
Payment Successful!
Thank you for your purchase! Your payment was successful, and we’re
processing your order.
)}
)
}
export default PaymentConfirmation
================================================
FILE: ecom-frontend/src/components/checkout/PaymentForm.jsx
================================================
import { Skeleton } from '@mui/material';
import { PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js'
import React from 'react'
import { useState } from 'react';
const PaymentForm = ({ clientSecret, totalPrice }) => {
const stripe = useStripe();
const elements = useElements();
const [errorMessage, setErrorMessage] = useState("");
const handleSubmit = async (e) => {
e.preventDefault();
if (!stripe || !elements) {
return;
}
const { error: submitError } = await elements.submit();
const { error } = await stripe.confirmPayment({
elements,
clientSecret,
confirmParams: {
return_url: `${import.meta.env.VITE_FRONTEND_URL}/order-confirm`,
},
});
if (error) {
setErrorMessage(error.message);
return false;
}
};
const paymentElementOptions = {
layout: "tabs",
}
const isLoading = !clientSecret || !stripe || !elements;
return (
Payment Information
{isLoading ? (
) : (
<>
{clientSecret && }
{errorMessage && (
{errorMessage}
)}
{!isLoading ? `Pay $${Number(totalPrice).toFixed(2)}`
: "Processing"}
>
)}
)
}
export default PaymentForm
================================================
FILE: ecom-frontend/src/components/checkout/PaymentMethod.jsx
================================================
import { FormControl, FormControlLabel, Radio, RadioGroup } from '@mui/material'
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { addPaymentMethod, createUserCart } from '../../store/actions';
const PaymentMethod = () => {
const dispatch = useDispatch();
const { paymentMethod } = useSelector((state) => state.payment);
const { cart, cartId } = useSelector((state) => state.carts);
const { isLoading, errorMessage } = useSelector((state) => state.errors);
useEffect(() => {
if (cart.length > 0 && !cartId && !errorMessage) {
const sendCartItems = cart.map((item) => {
return {
productId: item.productId,
quantity: item.quantity,
};
});
dispatch(createUserCart(sendCartItems));
}
}, [dispatch, cartId]);
const paymentMethodHandler = (method) => {
dispatch(addPaymentMethod(method));
}
return (
Select Payment Method
paymentMethodHandler(e.target.value)}
>
}
label="Stripe"
className='text-gray-700'/>
}
label="Paypal"
className='text-gray-700'/>
)
}
export default PaymentMethod
================================================
FILE: ecom-frontend/src/components/checkout/PaypalPayment.jsx
================================================
import { Alert, AlertTitle } from '@mui/material'
import React from 'react'
const PaypalPayment = () => {
return (
Paypal Unavailable
Paypal payment is unavailable. Please use another payment method.
)
}
export default PaypalPayment
================================================
FILE: ecom-frontend/src/components/checkout/StripePayment.jsx
================================================
import { Alert, AlertTitle, Skeleton } from '@mui/material'
import { Elements } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';
import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import PaymentForm from './PaymentForm';
import { createStripePaymentSecret } from '../../store/actions';
const stripePromise = loadStripe(import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY);
const StripePayment = () => {
const dispatch = useDispatch();
const { clientSecret } = useSelector((state) => state.auth);
const { totalPrice } = useSelector((state) => state.carts);
const { isLoading, errorMessage } = useSelector((state) => state.errors);
const { user, selectedUserCheckoutAddress } = useSelector((state) => state.auth);
useEffect(() => {
if (!clientSecret) {
const sendData = {
amount: Number(totalPrice) * 100,
currency: "usd",
email: user.email,
name: `${user.username}`,
address: selectedUserCheckoutAddress,
description: `Order for ${user.email}`,
metadata: {
test: "1"
}
};
dispatch(createStripePaymentSecret(sendData));
}
}, [clientSecret]);
if (isLoading) {
return (
)
}
return (
<>
{clientSecret && (
)}
>
)
}
export default StripePayment
================================================
FILE: ecom-frontend/src/components/helper/tableColumn.jsx
================================================
import { FaEdit, FaEye, FaImage, FaTrashAlt } from "react-icons/fa";
import { MdOutlineEmail } from "react-icons/md";
export const adminProductTableColumn = (
handleEdit,
handleDelete,
handleImageUpload,
handleProductView
) => [
{
disableColumnMenu: true,
sortable: false,
field: "id",
headerName: "ID",
minWidth: 200,
headerAlign: "center",
align: "center",
editable: false,
headerClassName: "text-black font-semibold border",
cellClassName: "text-slate-700 font-normal border",
renderHeader: (params) => ProductID ,
},
{
disableColumnMenu: true,
field: "productName",
headerName: "Product Name",
align: "center",
width: 260,
editable: false,
sortable: false,
headerAlign: "center",
headerClassName: "text-black font-semibold text-center border ",
cellClassName: "text-slate-700 font-normal border text-center",
renderHeader: (params) => Product Name ,
},
{
disableColumnMenu: true,
field: "price",
headerName: "Price",
minWidth: 200,
headerAlign: "center",
align: "center",
editable: false,
headerClassName: "text-black font-semibold border",
cellClassName: "text-slate-700 font-normal border",
renderHeader: (params) => Price ,
},
{
disableColumnMenu: true,
field: "quantity",
headerName: "Quantity",
minWidth: 200,
headerAlign: "center",
align: "center",
editable: false,
headerClassName: "text-black font-semibold border",
cellClassName: "text-slate-700 font-normal border",
renderHeader: (params) => Quantity ,
},
{
disableColumnMenu: true,
field: "specialPrice",
headerName: "Price",
minWidth: 200,
headerAlign: "center",
align: "center",
editable: false,
headerClassName: "text-black font-semibold border",
cellClassName: "text-slate-700 font-normal border",
renderHeader: (params) => (
Special Price
),
},
{
sortable: false,
field: "description",
headerName: "Image",
headerAlign: "center",
align: "center",
width: 200,
editable: false,
disableColumnMenu: true,
headerClassName: "text-black font-semibold border ",
cellClassName: "text-slate-700 font-normal border",
renderHeader: (params) => Description ,
},
{
sortable: false,
field: "image",
headerName: "Image",
headerAlign: "center",
align: "center",
width: 200,
editable: false,
disableColumnMenu: true,
headerClassName: "text-black font-semibold border ",
cellClassName: "text-slate-700 font-normal border",
renderHeader: (params) => Image ,
},
{
field: "action",
headerName: "Action",
headerAlign: "center",
editable: false,
headerClassName: "text-black font-semibold text-center",
cellClassName: "text-slate-700 font-normal",
sortable: false,
width: 400,
renderHeader: (params) => Action ,
renderCell: (params) => {
return (
handleImageUpload(params.row)}
className="flex items-center bg-green-500 hover:bg-green-600 text-white px-4 h-9 rounded-md"
>
Image
handleEdit(params.row)}
className="flex items-center bg-blue-500 text-white px-4 h-9 rounded-md "
>
Edit
handleDelete(params.row)}
className="flex items-center bg-red-500 text-white px-4 h-9 rounded-md"
>
Delete
handleProductView(params.row)}
className="flex items-center bg-slate-800 text-white px-4 h-9 rounded-md"
>
View
);
},
},
];
export const adminOrderTableColumn = (handleEdit) => [
{
sortable: false,
disableColumnMenu: true,
field: "id",
headerName: "orderId",
minWidth: 180,
headerAlign: "center",
editable: false,
headerClassName: "text-black font-semibold border",
cellClassName: "text-slate-700 font-normal border",
renderHeader: (params) => Order ID
},
{
// Column for customer email.
disableColumnMenu: true,
field: "email",
headerName: "Email",
align: "center",
width: 250,
editable: false,
sortable: false,
headerAlign: "center",
headerClassName: "text-black font-semibold text-center border ",
cellClassName: "text-slate-700 font-normal border text-center",
renderHeader: (params) => Email ,
},
{
// Column for showing total amount of the order.
disableColumnMenu: true,
field: "totalAmount",
headerName: "Total Amount",
align: "center",
width: 200,
editable: false,
sortable: true,
headerAlign: "center",
headerClassName: "text-black font-semibold text-center border ",
cellClassName: "text-slate-700 font-normal border text-center",
renderHeader: (params) => Total Amount ,
},
{
// Column to display order status (e.g., Pending, Shipped).
disableColumnMenu: true,
field: "status",
headerName: "Status",
align: "center",
width: 200,
editable: false,
sortable: false,
headerAlign: "center",
headerClassName: "text-black font-semibold text-center border ",
cellClassName: "text-slate-700 font-normal border text-center",
renderHeader: (params) => Status ,
},
{
// Column for order creation date.
disableColumnMenu: true,
field: "date",
headerName: "Order Date",
align: "center",
width: 200,
editable: false,
sortable: false,
headerAlign: "center",
headerClassName: "text-black font-semibold text-center border ",
cellClassName: "text-slate-700 font-normal border text-center",
renderHeader: (params) => Order Date ,
},
{
// Custom action column with an "Edit" button.
field: "action",
headerName: "Action",
headerAlign: "center",
editable: false,
headerClassName: "text-black font-semibold text-center",
cellClassName: "text-slate-700 font-normal",
sortable: false,
width: 250,
renderHeader: (params) => Action ,
renderCell: (params) => {
return (
handleEdit(params.row)}
className='flex items-center bg-blue-500 text-white px-4 h-9 rounded-md'>
Edit
);
},
},
];
//table column for categories in admin panel
export const categoryTableColumns = (handleEdit, handleDelete) => [
{
sortable: false,
disableColumnMenu: true,
field: "id",
headerName: "CategoryId",
minWidth: 300,
headerAlign: "center",
align: "center",
editable: false,
headerClassName: "text-black font-semibold border",
cellClassName: "text-slate-700 font-normal border",
renderHeader: (params) => CategoryId ,
},
{
disableColumnMenu: true,
field: "categoryName",
headerName: "Category Name",
align: "center",
width: 400,
editable: false,
sortable: false,
headerAlign: "center",
headerClassName: "text-black font-semibold text-center border ",
cellClassName: "text-slate-700 font-normal border text-center",
renderHeader: (params) => Category Name ,
},
{
field: "action",
headerName: "Action",
headerAlign: "center",
editable: false,
headerClassName: "text-black font-semibold text-center",
cellClassName: "text-slate-700 font-normal",
sortable: false,
width: 400,
renderHeader: (params) => Action ,
renderCell: (params) => {
return (
handleEdit(params.row)}
className="flex items-center bg-blue-500 text-white px-4 h-9 rounded-md "
>
Edit
{/* Delete Button */}
handleDelete(params.row)}
className="flex items-center bg-red-500 text-white px-4 h-9 rounded-md"
>
Delete
);
},
},
];
//table column for seller in admin panel
export const sellerTableColumns = [
{
disableColumnMenu: true,
field: "id",
headerName: "ID",
minWidth: 400,
headerAlign: "center",
align: "center",
editable: false,
headerClassName: "text-black font-semibold border",
cellClassName: "text-slate-700 font-normal border",
renderHeader: (params) => SellerID ,
},
{
disableColumnMenu: true,
field: "username",
headerName: "UserName",
minWidth: 400,
headerAlign: "center",
align: "center",
editable: false,
sortable: false,
headerClassName: "text-black font-semibold border",
cellClassName: "text-slate-700 font-normal border",
renderHeader: (params) => UserName ,
},
{
disableColumnMenu: true,
field: "email",
headerName: "Email",
align: "center",
width: 400,
editable: false,
sortable: false,
headerAlign: "center",
headerClassName: "text-black font-semibold text-center border ",
cellClassName: "text-slate-700 font-normal border text-center",
renderHeader: (params) => Email ,
renderCell: (params) => {
return (
{params?.row?.email}
);
},
},
];
================================================
FILE: ecom-frontend/src/components/home/HeroBanner.jsx
================================================
// Import Swiper React components
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css/navigation';
import 'swiper/css/pagination';
import 'swiper/css/scrollbar';
import 'swiper/css/effect-fade';
import 'swiper/css/autoplay';
// Import Swiper styles
import 'swiper/css';
import { Autoplay, Pagination, EffectFade, Navigation } from 'swiper/modules';
import { bannerLists } from '../../utils';
import { Link } from 'react-router-dom';
const colors = ["bg-banner-color1", "bg-banner-color2", "bg-banner-color3"];
const HeroBanner = () => {
return (
{bannerLists.map((item, i) => (
{item.title}
{item.subtitle}
{item.description}
Shop
))}
);
}
export default HeroBanner;
================================================
FILE: ecom-frontend/src/components/home/Home.jsx
================================================
import { useDispatch, useSelector } from "react-redux";
import HeroBanner from "./HeroBanner";
import { useEffect } from "react";
import { fetchProducts } from "../../store/actions";
import ProductCard from "../shared/ProductCard";
import Loader from "../shared/Loader";
import { FaExclamationTriangle } from "react-icons/fa";
const Home = () => {
const dispatch = useDispatch();
const {products} = useSelector((state) => state.products);
const { isLoading, errorMessage } = useSelector(
(state) => state.errors
);
useEffect(() => {
dispatch(fetchProducts());
}, [dispatch]);
return (
Products
Discover our handpicked selection of top-rated items just for you!
{isLoading ? (
) : errorMessage ? (
{errorMessage}
) : (
{products &&
products?.slice(0,4)
.map((item, i) =>
)}
)}
)
}
export default Home;
================================================
FILE: ecom-frontend/src/components/products/Filter.jsx
================================================
import { Button, FormControl, InputLabel, MenuItem, Select, Tooltip } from "@mui/material";
import { useEffect, useState } from "react";
import { FiArrowDown, FiArrowUp, FiRefreshCw, FiSearch } from "react-icons/fi";
import { useLocation, useNavigate, useSearchParams } from "react-router-dom";
const Filter = ({ categories }) => {
const [searchParams] = useSearchParams();
const params = new URLSearchParams(searchParams);
const pathname = useLocation().pathname;
const navigate = useNavigate();
const [category, setCategory] = useState("all");
const [sortOrder, setSortOrder] = useState("asc");
const [searchTerm, setSearchTerm] = useState("");
useEffect(() => {
const currentCategory = searchParams.get("category") || "all";
const currentSortOrder = searchParams.get("sortby") || "asc";
const currentSearchTerm = searchParams.get("keyword") || "";
setCategory(currentCategory);
setSortOrder(currentSortOrder);
setSearchTerm(currentSearchTerm);
}, [searchParams]);
useEffect(() => {
const handler = setTimeout(() => {
if (searchTerm) {
searchParams.set("keyword", searchTerm);
} else {
searchParams.delete("keyword");
}
navigate(`${pathname}?${searchParams.toString()}`);
}, 700);
return () => {
clearTimeout(handler);
};
}, [searchParams, searchTerm, navigate, pathname]);
const handleCategoryChange = (event) => {
const selectedCategory = event.target.value;
if (selectedCategory === "all") {
params.delete("category");
} else {
params.set("category", selectedCategory);
}
navigate(`${pathname}?${params}`);
setCategory(event.target.value);
};
const toggleSortOrder = () => {
setSortOrder((prevOrder) => {
const newOrder = (prevOrder === "asc") ? "desc" : "asc";
params.set("sortby", newOrder);
navigate(`${pathname}?${params}`);
return newOrder;
})
};
const handleClearFilters = () => {
navigate({ pathname : window.location.pathname });
};
return (
{/* SEARCH BAR */}
setSearchTerm(e.target.value)}
className="border border-gray-400 text-slate-800 rounded-md py-2 pl-10 pr-4 w-full focus:outline-hidden focus:ring-2 focus:ring-[#1976d2]"/>
{/* CATEGORY SELECTION */}
Category
All
{categories.map((item) => (
{item.categoryName}
))}
{/* SORT BUTTON & CLEAR FILTER */}
Sort By
{sortOrder === "asc" ? (
) : (
)}
Clear Filter
);
}
export default Filter;
================================================
FILE: ecom-frontend/src/components/products/Products.jsx
================================================
import { FaExclamationTriangle } from "react-icons/fa";
import ProductCard from "../shared/ProductCard";
import { useDispatch, useSelector } from "react-redux";
import { useEffect } from "react";
import { fetchCategories } from "../../store/actions";
import Filter from "./Filter";
import useProductFilter from "../../hooks/useProductFilter";
import Loader from "../shared/Loader";
import Paginations from "../shared/Paginations";
const Products = () => {
const { isLoading, errorMessage } = useSelector(
(state) => state.errors
);
const {products, categories, pagination} = useSelector(
(state) => state.products
)
const dispatch = useDispatch();
useProductFilter();
useEffect(() => {
dispatch(fetchCategories());
}, [dispatch]);
return (
{isLoading ? (
) : errorMessage ? (
{errorMessage}
) : (
{products &&
products.map((item, i) =>
)}
)}
)
}
export default Products;
================================================
FILE: ecom-frontend/src/components/shared/DeleteModal.jsx
================================================
import React from "react";
import { FaExclamationTriangle } from "react-icons/fa";
import { FaTimes } from "react-icons/fa";
import {
Dialog,
DialogBackdrop,
DialogPanel,
DialogTitle,
} from "@headlessui/react";
export const DeleteModal = ({
open,
setOpen,
title,
onDeleteHandler,
loader,
}) => {
return (
setOpen(false)}
className="rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
Close
{title}
Are you sure you want to delete?
{loader ? "Loading..." : "Delete"}
setOpen(false)}
className="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto"
>
Cancel
);
};
export default DeleteModal;
================================================
FILE: ecom-frontend/src/components/shared/ErrorPage.jsx
================================================
import React from 'react'
import { FaExclamationTriangle } from 'react-icons/fa'
const ErrorPage = ({ message}) => {
return (
{message ? message : "An unexpected error has occured"}
)
}
export default ErrorPage
================================================
FILE: ecom-frontend/src/components/shared/InputField.jsx
================================================
const InputField = ({
label,
id,
type,
errors,
register,
required,
message,
className,
min,
value,
placeholder,
}) => {
return (
{label}
{errors[id]?.message && (
{errors[id]?.message}
)}
);
};
export default InputField;
================================================
FILE: ecom-frontend/src/components/shared/Loader.jsx
================================================
import { RotatingLines } from "react-loader-spinner";
const Loader = ({ text }) => {
return (
{text ? text : "Please wait...." }
);
}
export default Loader;
================================================
FILE: ecom-frontend/src/components/shared/Modal.jsx
================================================
import { Description, Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react'
import { RxCross1 } from 'react-icons/rx';
function Modal({ open, setOpen, children, title = ""}) {
return (
<>
setOpen(false)} className="relative z-10">
Panel Title
{title}
setOpen(false)}>
{children}
>
)
}
export default Modal;
================================================
FILE: ecom-frontend/src/components/shared/Navbar.jsx
================================================
import { Badge } from "@mui/material";
import { useState } from "react";
import { FaShoppingCart, FaSignInAlt, FaStore } from "react-icons/fa";
import { IoIosMenu } from "react-icons/io";
import { RxCross2 } from "react-icons/rx";
import { useSelector } from "react-redux";
import { Link, useLocation } from "react-router-dom";
import UserMenu from "../UserMenu";
const Navbar = () => {
const path = useLocation().pathname;
const [navbarOpen, setNavbarOpen] = useState(false);
const { cart } = useSelector((state) => state.carts);
const { user } = useSelector((state) => state.auth);
return (
E-Shop
Home
Products
About
Contact
{(user && user.id) ? (
) : (
Login
)}
setNavbarOpen(!navbarOpen)}
className="sm:hidden flex items-center sm:mt-0 mt-2">
{navbarOpen ? (
) : (
)}
)
}
export default Navbar;
================================================
FILE: ecom-frontend/src/components/shared/Paginations.jsx
================================================
import { Pagination } from "@mui/material";
import { useLocation, useNavigate, useSearchParams } from "react-router-dom";
const Paginations = ({ numberOfPage, totalProducts }) => {
const [searchParams] = useSearchParams();
const pathname = useLocation().pathname;
const params = new URLSearchParams(searchParams);
const navigate = useNavigate();
const paramValue = searchParams.get("page")
? Number(searchParams.get("page"))
: 1;
const onChangeHandler = (event, value) => {
params.set("page", value.toString());
navigate(`${pathname}?${params}`);
};
return(
)
};
export default Paginations;
================================================
FILE: ecom-frontend/src/components/shared/ProductCard.jsx
================================================
import { useState } from "react";
import { FaShoppingCart } from "react-icons/fa";
import ProductViewModal from "./ProductViewModal";
import truncateText from "../../utils/truncateText";
import { useDispatch } from "react-redux";
import { addToCart } from "../../store/actions";
import toast from "react-hot-toast";
const ProductCard = ({
productId,
productName,
image,
description,
quantity,
price,
discount,
specialPrice,
about = false,
}) => {
const [openProductViewModal, setOpenProductViewModal] = useState(false);
const btnLoader = false;
const [selectedViewProduct, setSelectedViewProduct] = useState("");
const isAvailable = quantity && Number(quantity) > 0;
const dispatch = useDispatch();
const handleProductView = (product) => {
if (!about) {
setSelectedViewProduct(product);
setOpenProductViewModal(true);
}
};
const addToCartHandler = (cartItems) => {
dispatch(addToCart(cartItems, 1, toast));
};
return (
{
handleProductView({
id: productId,
productName,
image,
description,
quantity,
price,
discount,
specialPrice,
})
}}
className="w-full overflow-hidden aspect-3/2">
{
handleProductView({
id: productId,
productName,
image,
description,
quantity,
price,
discount,
specialPrice,
})
}}
className="text-lg font-semibold mb-2 cursor-pointer">
{truncateText(productName, 50)}
{truncateText(description, 80)}
{ !about && (
{specialPrice ? (
${Number(price).toFixed(2)}
${Number(specialPrice).toFixed(2)}
) : (
{" "}
${Number(price).toFixed(2)}
)}
addToCartHandler({
image,
productName,
description,
specialPrice,
price,
productId,
quantity,
})}
className={`bg-blue-500 ${isAvailable ? "opacity-100 hover:bg-blue-600" : "opacity-70"}
text-white py-2 px-3 rounded-lg items-center transition-colors duration-300 w-36 flex justify-center`}>
{isAvailable ? "Add to Cart" : "Stock Out"}
)}
)
}
export default ProductCard;
================================================
FILE: ecom-frontend/src/components/shared/ProductViewModal.jsx
================================================
import { Button, Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react'
import { Divider } from '@mui/material';
import { useState } from 'react'
import Status from './Status';
import { MdClose, MdDone } from 'react-icons/md';
function ProductViewModal({open, setOpen, product, isAvailable}) {
const {id, productName, image, description, quantity, price, discount, specialPrice} = product;
const handleClickOpen = () => {
setOpen(true);
}
return (
<>
{image && (
)}
{productName}
{specialPrice ? (
${Number(price).toFixed(2)}
${Number(specialPrice).toFixed(2)}
) : (
{" "}
${Number(price).toFixed(2)}
)}
{isAvailable ? (
) : (
)}
{description}
setOpen(false)}
type="button"
className="px-4 py-2 text-sm font-semibold text-slate-700 border border-slate-700 hover:text-slate-800 hover:border-slate-800 rounded-md "
>
Close
>
)
}
export default ProductViewModal;
================================================
FILE: ecom-frontend/src/components/shared/SelectTextField.jsx
================================================
import { Listbox, ListboxButton, ListboxOption, ListboxOptions } from "@headlessui/react";
import { FaCheck } from "react-icons/fa";
const SelectTextField = ({
label,
select,
setSelect,
lists
}) => {
return (
{label}
{select?.categoryName}
{lists?.map((category) => (
{category.categoryName}
))}
);
};
export default SelectTextField;
================================================
FILE: ecom-frontend/src/components/shared/Sidebar.jsx
================================================
import React from 'react'
import { FaTachometerAlt } from 'react-icons/fa';
import { useSelector } from 'react-redux';
import { Link, useLocation } from 'react-router-dom'
import { adminNavigation, sellerNavigation } from '../../utils';
import classNames from 'classnames';
const Sidebar = ({isProfileLayout = false}) => {
const pathName = useLocation().pathname;
const { user } = useSelector((state) => state.auth);
const isAdmin = user && user?.roles?.includes("ROLE_ADMIN");
const sideBarLayout = isAdmin ? adminNavigation : sellerNavigation;
return (
{isAdmin ? "Admin Panel" : "Seller Panel"}
{sideBarLayout.map((item) => (
{item.name}
))}
)
}
export default Sidebar
================================================
FILE: ecom-frontend/src/components/shared/Skeleton.jsx
================================================
import React from "react";
const Skeleton = () => {
return (
);
};
export default Skeleton;
================================================
FILE: ecom-frontend/src/components/shared/Spinners.jsx
================================================
import React from 'react'
const Spinners = () => {
return (
)
}
export default Spinners;
================================================
FILE: ecom-frontend/src/components/shared/Status.jsx
================================================
const Status = ({text, icon:Icon, bg, color}) => {
return (
{text}
)
};
export default Status;
================================================
FILE: ecom-frontend/src/hooks/useCategoryFilter.js
================================================
import { useEffect } from "react";
import { useSearchParams } from "react-router-dom";
import { useDispatch } from "react-redux";
import { fetchCategories } from "../store/actions";
const useCategoryFilter = () => {
const [searchParams] = useSearchParams(); // Access search params from the URL
const dispatch = useDispatch(); // Get the dispatch function to call actions
useEffect(() => {
const params = new URLSearchParams(); // Create new URLSearchParams object
// Get current page from URL search params, defaulting to 1 if not present
const currentPage = searchParams.get("page")
? Number(searchParams.get("page"))
: 1;
params.set("pageNumber", currentPage - 1); // Pagination starts from 0 for API
// Convert params to a query string
const queryString = params.toString();
// Dispatch action to fetch categories using the constructed query string
dispatch(fetchCategories(queryString));
}, [dispatch, searchParams]);
};
export default useCategoryFilter;
================================================
FILE: ecom-frontend/src/hooks/useOrderFilter.js
================================================
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useSearchParams } from "react-router-dom";
import { getOrdersForDashboard } from "../store/actions";
const useOrderFilter = () => {
const [searchParams] = useSearchParams();
const dispatch = useDispatch();
const { user } = useSelector((state) => state.auth);
const isAdmin = user && user?.roles?.includes("ROLE_ADMIN");
useEffect(() => {
const params = new URLSearchParams();
const currentPage = searchParams.get("page")
? Number(searchParams.get("page"))
: 1;
params.set("pageNumber", currentPage - 1);
const queryString = params.toString();
console.log("QUERY STRING", queryString);
dispatch(getOrdersForDashboard(queryString, isAdmin));
}, [dispatch, searchParams]);
};
export default useOrderFilter;
================================================
FILE: ecom-frontend/src/hooks/useProductFilter.js
================================================
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useSearchParams } from "react-router-dom";
import { dashboardProductsAction, fetchProducts } from "../store/actions";
const useProductFilter = () => {
const [searchParams] = useSearchParams();
const dispatch = useDispatch();
useEffect(() => {
const params = new URLSearchParams();
const currentPage = searchParams.get("page")
? Number(searchParams.get("page"))
: 1;
params.set("pageNumber", currentPage - 1);
const sortOrder = searchParams.get("sortby") || "asc";
const categoryParams = searchParams.get("category") || null;
const keyword = searchParams.get("keyword") || null;
params.set("sortBy","price");
params.set("sortOrder", sortOrder);
if (categoryParams) {
params.set("category", categoryParams);
}
if (keyword) {
params.set("keyword", keyword);
}
const queryString = params.toString();
console.log("QUERY STRING", queryString);
dispatch(fetchProducts(queryString));
}, [dispatch, searchParams]);
};
export const useDashboardProductFilter = () => {
const { user } = useSelector((state) => state.auth);
const isAdmin = user && user?.roles?.includes("ROLE_ADMIN");
const [searchParams] = useSearchParams();
const dispatch = useDispatch();
useEffect(() => {
const params = new URLSearchParams();
const currentPage = searchParams.get("page")
? Number(searchParams.get("page"))
: 1;
params.set("pageNumber", currentPage - 1);
const queryString = params.toString();
dispatch(dashboardProductsAction(queryString, isAdmin));
}, [dispatch, searchParams]);
};
export default useProductFilter;
================================================
FILE: ecom-frontend/src/index.css
================================================
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap')
layer(base);
@import 'tailwindcss';
@theme {
--font-montserrat: Montserrat, sans-serif;
--shadow-custom: 0 0 15px rgba(0, 0, 0, 0.3);
--shadow-right: 10px 0px 10px -5px rgba(0, 0, 0, 0.3);
--color-custom-blue: rgba(28, 100, 242, 1);
--color-banner-color1: #fdc200;
--color-banner-color2: #ff2c2c;
--color-banner-color3: #21ad61;
--color-banner-color4: #723da6;
--background-image-custom-gradient: linear-gradient(
to right,
#111827,
#1f2937
);
--background-image-button-gradient: linear-gradient(
to right,
#7e22ce,
#ef4444
);
--background-image-custom-gradient2: linear-gradient(
135deg,
#f5f5f5,
#eae7dc
);
}
/*
The default border color has changed to `currentcolor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentcolor);
}
}
================================================
FILE: ecom-frontend/src/main.jsx
================================================
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import { Provider } from 'react-redux'
import store from './store/reducers/store.js'
createRoot(document.getElementById('root')).render(
,
)
================================================
FILE: ecom-frontend/src/store/actions/index.js
================================================
import api from "../../api/api"
export const fetchProducts = (queryString) => async (dispatch) => {
try {
dispatch({ type: "IS_FETCHING" });
const { data } = await api.get(`/public/products?${queryString}`);
dispatch({
type: "FETCH_PRODUCTS",
payload: data.content,
pageNumber: data.pageNumber,
pageSize: data.pageSize,
totalElements: data.totalElements,
totalPages: data.totalPages,
lastPage: data.lastPage,
});
dispatch({ type: "IS_SUCCESS" });
} catch (error) {
console.log(error);
dispatch({
type: "IS_ERROR",
payload: error?.response?.data?.message || "Failed to fetch products",
});
}
};
export const fetchCategories = () => async (dispatch) => {
try {
dispatch({ type: "CATEGORY_LOADER" });
const { data } = await api.get(`/public/categories`);
dispatch({
type: "FETCH_CATEGORIES",
payload: data.content,
pageNumber: data.pageNumber,
pageSize: data.pageSize,
totalElements: data.totalElements,
totalPages: data.totalPages,
lastPage: data.lastPage,
});
dispatch({ type: "IS_ERROR" });
} catch (error) {
console.log(error);
dispatch({
type: "IS_ERROR",
payload: error?.response?.data?.message || "Failed to fetch categories",
});
}
};
export const addToCart = (data, qty = 1, toast) =>
(dispatch, getState) => {
// Find the product
const { products } = getState().products;
const getProduct = products.find(
(item) => item.productId === data.productId
);
// Check for stocks
const isQuantityExist = getProduct.quantity >= qty;
// If in stock -> add
if (isQuantityExist) {
dispatch({ type: "ADD_CART", payload: {...data, quantity: qty}});
toast.success(`${data?.productName} added to the cart`);
localStorage.setItem("cartItems", JSON.stringify(getState().carts.cart));
} else {
// error
toast.error("Out of stock");
}
};
export const increaseCartQuantity =
(data, toast, currentQuantity, setCurrentQuantity) =>
(dispatch, getState) => {
// Find the product
const { products } = getState().products;
const getProduct = products.find(
(item) => item.productId === data.productId
);
const isQuantityExist = getProduct.quantity >= currentQuantity + 1;
if (isQuantityExist) {
const newQuantity = currentQuantity + 1;
setCurrentQuantity(newQuantity);
dispatch({
type: "ADD_CART",
payload: {...data, quantity: newQuantity + 1 },
});
localStorage.setItem("cartItems", JSON.stringify(getState().carts.cart));
} else {
toast.error("Quantity Reached to Limit");
}
};
export const decreaseCartQuantity =
(data, newQuantity) => (dispatch, getState) => {
dispatch({
type: "ADD_CART",
payload: {...data, quantity: newQuantity},
});
localStorage.setItem("cartItems", JSON.stringify(getState().carts.cart));
}
export const removeFromCart = (data, toast) => (dispatch, getState) => {
dispatch({type: "REMOVE_CART", payload: data });
toast.success(`${data.productName} removed from cart`);
localStorage.setItem("cartItems", JSON.stringify(getState().carts.cart));
}
export const authenticateSignInUser
= (sendData, toast, reset, navigate, setLoader) => async (dispatch) => {
try {
setLoader(true);
const { data } = await api.post("/auth/signin", sendData);
dispatch({ type: "LOGIN_USER", payload: data });
localStorage.setItem("auth", JSON.stringify(data));
reset();
toast.success("Login Success");
navigate("/");
} catch (error) {
console.log(error);
toast.error(error?.response?.data?.message || "Internal Server Error");
} finally {
setLoader(false);
}
}
export const registerNewUser
= (sendData, toast, reset, navigate, setLoader) => async (dispatch) => {
try {
setLoader(true);
const { data } = await api.post("/auth/signup", sendData);
reset();
toast.success(data?.message || "User Registered Successfully");
navigate("/login");
} catch (error) {
console.log(error);
toast.error(error?.response?.data?.message || error?.response?.data?.password || "Internal Server Error");
} finally {
setLoader(false);
}
};
export const logOutUser = (navigate) => (dispatch) => {
dispatch({ type:"LOG_OUT" });
localStorage.removeItem("auth");
navigate("/login");
};
export const addUpdateUserAddress =
(sendData, toast, addressId, setOpenAddressModal) => async (dispatch, getState) => {
/*
const { user } = getState().auth;
await api.post(`/addresses`, sendData, {
headers: { Authorization: "Bearer " + user.jwtToken },
});
*/
dispatch({ type:"BUTTON_LOADER" });
try {
if (!addressId) {
const { data } = await api.post("/addresses", sendData);
} else {
await api.put(`/addresses/${addressId}`, sendData);
}
dispatch(getUserAddresses());
toast.success("Address saved successfully");
dispatch({ type:"IS_SUCCESS" });
} catch (error) {
console.log(error);
toast.error(error?.response?.data?.message || "Internal Server Error");
dispatch({ type:"IS_ERROR", payload: null });
} finally {
setOpenAddressModal(false);
}
};
export const deleteUserAddress =
(toast, addressId, setOpenDeleteModal) => async (dispatch, getState) => {
try {
dispatch({ type: "BUTTON_LOADER" });
await api.delete(`/addresses/${addressId}`);
dispatch({ type: "IS_SUCCESS" });
dispatch(getUserAddresses());
dispatch(clearCheckoutAddress());
toast.success("Address deleted successfully");
} catch (error) {
console.log(error);
dispatch({
type: "IS_ERROR",
payload: error?.response?.data?.message || "Some Error Occured",
});
} finally {
setOpenDeleteModal(false);
}
};
export const clearCheckoutAddress = () => {
return {
type: "REMOVE_CHECKOUT_ADDRESS",
}
};
export const getUserAddresses = () => async (dispatch, getState) => {
try {
dispatch({ type: "IS_FETCHING" });
const { data } = await api.get(`/addresses`);
dispatch({type: "USER_ADDRESS", payload: data});
dispatch({ type: "IS_SUCCESS" });
} catch (error) {
console.log(error);
dispatch({
type: "IS_ERROR",
payload: error?.response?.data?.message || "Failed to fetch user addresses",
});
}
};
export const selectUserCheckoutAddress = (address) => {
localStorage.setItem("CHECKOUT_ADDRESS", JSON.stringify(address));
return {
type: "SELECT_CHECKOUT_ADDRESS",
payload: address,
}
};
export const addPaymentMethod = (method) => {
return {
type: "ADD_PAYMENT_METHOD",
payload: method,
}
};
export const createUserCart = (sendCartItems) => async (dispatch, getState) => {
try {
dispatch({ type: "IS_FETCHING" });
await api.post('/cart/create', sendCartItems);
await dispatch(getUserCart());
} catch (error) {
console.log(error);
dispatch({
type: "IS_ERROR",
payload: error?.response?.data?.message || "Failed to create cart items",
});
}
};
export const getUserCart = () => async (dispatch, getState) => {
try {
dispatch({ type: "IS_FETCHING" });
const { data } = await api.get('/carts/users/cart');
dispatch({
type: "GET_USER_CART_PRODUCTS",
payload: data.products,
totalPrice: data.totalPrice,
cartId: data.cartId
})
localStorage.setItem("cartItems", JSON.stringify(getState().carts.cart));
dispatch({ type: "IS_SUCCESS" });
} catch (error) {
console.log(error);
dispatch({
type: "IS_ERROR",
payload: error?.response?.data?.message || "Failed to fetch cart items",
});
}
};
export const createStripePaymentSecret
= (sendData) => async (dispatch, getState) => {
try {
dispatch({ type: "IS_FETCHING" });
const { data } = await api.post("/order/stripe-client-secret", sendData);
dispatch({ type: "CLIENT_SECRET", payload: data });
localStorage.setItem("client-secret", JSON.stringify(data));
dispatch({ type: "IS_SUCCESS" });
} catch (error) {
console.log(error);
toast.error(error?.response?.data?.message || "Failed to create client secret");
}
};
export const stripePaymentConfirmation
= (sendData, setErrorMesssage, setLoadng, toast) => async (dispatch, getState) => {
try {
const response = await api.post("/order/users/payments/online", sendData);
if (response.data) {
localStorage.removeItem("CHECKOUT_ADDRESS");
localStorage.removeItem("cartItems");
localStorage.removeItem("client-secret");
dispatch({ type: "REMOVE_CLIENT_SECRET_ADDRESS"});
dispatch({ type: "CLEAR_CART"});
toast.success("Order Accepted");
} else {
setErrorMesssage("Payment Failed. Please try again.");
}
} catch (error) {
setErrorMesssage("Payment Failed. Please try again.");
}
};
export const analyticsAction = () => async (dispatch, getState) => {
try {
dispatch({ type: "IS_FETCHING"});
const { data } = await api.get('/admin/app/analytics');
dispatch({
type: "FETCH_ANALYTICS",
payload: data,
})
dispatch({ type: "IS_SUCCESS"});
} catch (error) {
dispatch({
type: "IS_ERROR",
payload: error?.response?.data?.message || "Failed to fetch analytics data",
});
}
};
export const getOrdersForDashboard = (queryString, isAdmin) => async (dispatch) => {
try {
dispatch({ type: "IS_FETCHING" });
const endpoint = isAdmin ? "/admin/orders" : "/seller/orders";
const { data } = await api.get(`${endpoint}?${queryString}`);
dispatch({
type: "GET_ADMIN_ORDERS",
payload: data.content,
pageNumber: data.pageNumber,
pageSize: data.pageSize,
totalElements: data.totalElements,
totalPages: data.totalPages,
lastPage: data.lastPage,
});
dispatch({ type: "IS_SUCCESS" });
} catch (error) {
console.log(error);
dispatch({
type: "IS_ERROR",
payload: error?.response?.data?.message || "Failed to fetch orders data",
});
}
};
export const updateOrderStatusFromDashboard =
(orderId, orderStatus, toast, setLoader, isAdmin) => async (dispatch, getState) => {
try {
setLoader(true);
const endpoint = isAdmin ? "/admin/orders/" : "/seller/orders/";
const { data } = await api.put(`${endpoint}${orderId}/status`, { status: orderStatus});
toast.success(data.message || "Order updated successfully");
await dispatch(getOrdersForDashboard());
} catch (error) {
console.log(error);
toast.error(error?.response?.data?.message || "Internal Server Error");
} finally {
setLoader(false)
}
};
export const dashboardProductsAction = (queryString, isAdmin) => async (dispatch) => {
try {
dispatch({ type: "IS_FETCHING" });
const endpoint = isAdmin ? "/admin/products" : "/seller/products";
const { data } = await api.get(`${endpoint}?${queryString}`);
dispatch({
type: "FETCH_PRODUCTS",
payload: data.content,
pageNumber: data.pageNumber,
pageSize: data.pageSize,
totalElements: data.totalElements,
totalPages: data.totalPages,
lastPage: data.lastPage,
});
dispatch({ type: "IS_SUCCESS" });
} catch (error) {
console.log(error);
dispatch({
type: "IS_ERROR",
payload: error?.response?.data?.message || "Failed to fetch dashboard products",
});
}
};
export const updateProductFromDashboard =
(sendData, toast, reset, setLoader, setOpen, isAdmin) => async (dispatch) => {
try {
setLoader(true);
const endpoint = isAdmin ? "/admin/products/" : "/seller/products/";
await api.put(`${endpoint}${sendData.id}`, sendData);
toast.success("Product update successful");
reset();
setLoader(false);
setOpen(false);
await dispatch(dashboardProductsAction());
} catch (error) {
toast.error(error?.response?.data?.description || "Product update failed");
}
};
export const addNewProductFromDashboard =
(sendData, toast, reset, setLoader, setOpen, isAdmin) => async(dispatch, getState) => {
try {
setLoader(true);
const endpoint = isAdmin ? "/admin/categories/" : "/seller/categories/";
await api.post(`${endpoint}${sendData.categoryId}/product`,
sendData
);
toast.success("Product created successfully");
reset();
setOpen(false);
await dispatch(dashboardProductsAction());
} catch (error) {
console.error(err);
toast.error(err?.response?.data?.description || "Product creation failed");
} finally {
setLoader(false);
}
}
export const deleteProduct =
(setLoader, productId, toast, setOpenDeleteModal, isAdmin) => async (dispatch, getState) => {
try {
setLoader(true)
const endpoint = isAdmin ? "/admin/products/" : "/seller/products/";
await api.delete(`${endpoint}${productId}`);
toast.success("Product deleted successfully");
setLoader(false);
setOpenDeleteModal(false);
await dispatch(dashboardProductsAction());
} catch (error) {
console.log(error);
toast.error(
error?.response?.data?.message || "Some Error Occured"
)
}
};
export const updateProductImageFromDashboard =
(formData, productId, toast, setLoader, setOpen, isAdmin) => async (dispatch) => {
try {
setLoader(true);
const endpoint = isAdmin ? "/admin/products/" : "/seller/products/";
await api.put(`${endpoint}${productId}/image`, formData);
toast.success("Image upload successful");
setLoader(false);
setOpen(false);
await dispatch(dashboardProductsAction());
} catch (error) {
toast.error(error?.response?.data?.description || "Product Image upload failed");
}
};
export const getAllCategoriesDashboard = (queryString) => async (dispatch) => {
dispatch({ type: "CATEGORY_LOADER" });
try {
const { data } = await api.get(`/public/categories?${queryString}`);
dispatch({
type: "FETCH_CATEGORIES",
payload: data["content"],
pageNumber: data["pageNumber"],
pageSize: data["pageSize"],
totalElements: data["totalElements"],
totalPages: data["totalPages"],
lastPage: data["lastPage"],
});
dispatch({ type: "CATEGORY_SUCCESS" });
} catch (err) {
console.log(err);
dispatch({
type: "IS_ERROR",
payload: err?.response?.data?.message || "Failed to fetch categories",
});
}
};
export const createCategoryDashboardAction =
(sendData, setOpen, reset, toast) => async (dispatch, getState) => {
try {
dispatch({ type: "CATEGORY_LOADER" });
await api.post("/admin/categories", sendData);
dispatch({ type: "CATEGORY_SUCCESS" });
reset();
toast.success("Category Created Successful");
setOpen(false);
await dispatch(getAllCategoriesDashboard());
} catch (err) {
console.log(err);
toast.error(
err?.response?.data?.categoryName || "Failed to create new category"
);
dispatch({
type: "IS_ERROR",
payload: err?.response?.data?.message || "Internal Server Error",
});
}
};
export const updateCategoryDashboardAction =
(sendData, setOpen, categoryID, reset, toast) =>
async (dispatch, getState) => {
try {
dispatch({ type: "CATEGORY_LOADER" });
await api.put(`/admin/categories/${categoryID}`, sendData);
dispatch({ type: "CATEGORY_SUCCESS" });
reset();
toast.success("Category Update Successful");
setOpen(false);
await dispatch(getAllCategoriesDashboard());
} catch (err) {
console.log(err);
toast.error(
err?.response?.data?.categoryName || "Failed to update category"
);
dispatch({
type: "IS_ERROR",
payload: err?.response?.data?.message || "Internal Server Error",
});
}
};
export const deleteCategoryDashboardAction =
(setOpen, categoryID, toast) => async (dispatch, getState) => {
try {
dispatch({ type: "CATEGORY_LOADER" });
await api.delete(`/admin/categories/${categoryID}`);
dispatch({ type: "CATEGORY_SUCCESS" });
toast.success("Category Delete Successful");
setOpen(false);
await dispatch(getAllCategoriesDashboard());
} catch (err) {
console.log(err);
toast.error(err?.response?.data?.message || "Failed to delete category");
dispatch({
type: "IS_ERROR",
payload: err?.response?.data?.message || "Internal Server Error",
});
}
};
export const getAllSellersDashboard =
(queryString) => async (dispatch, getState) => {
const { user } = getState().auth;
try {
dispatch({ type: "IS_FETCHING" });
const { data } = await api.get(`/auth/sellers?${queryString}`);
dispatch({
type: "GET_SELLERS",
payload: data["content"],
pageNumber: data["pageNumber"],
pageSize: data["pageSize"],
totalElements: data["totalElements"],
totalPages: data["totalPages"],
lastPage: data["lastPage"],
});
dispatch({ type: "IS_SUCCESS" });
} catch (err) {
console.log(err);
dispatch({
type: "IS_ERROR",
payload: err?.response?.data?.message || "Failed to fetch sellers data",
});
}
};
export const addNewDashboardSeller =
(sendData, toast, reset, setOpen, setLoader) => async (dispatch) => {
try {
setLoader(true);
await api.post("/auth/signup", sendData);
reset();
toast.success("Seller registered successfully!");
await dispatch(getAllSellersDashboard());
} catch (err) {
console.log(err);
toast.error(
err?.response?.data?.message ||
err?.response?.data?.password ||
"Internal Server Error"
);
} finally {
setLoader(false);
setOpen(false);
}
};
================================================
FILE: ecom-frontend/src/store/reducers/ProductReducer.js
================================================
const initialState = {
products: null,
categories: null,
pagination: {},
};
export const productReducer = (state = initialState, action) => {
switch (action.type) {
case "FETCH_PRODUCTS":
return {
...state,
products: action.payload,
pagination: {
...state.pagination,
pageNumber: action.pageNumber,
pageSize: action.pageSize,
totalElements: action.totalElements,
totalPages: action.totalPages,
lastPage: action.lastPage,
},
};
case "FETCH_PRODUCTS":
return {
...state,
products: action.payload,
pagination: {
...state.pagination,
pageNumber: action.pageNumber,
pageSize: action.pageSize,
totalElements: action.totalElements,
totalPages: action.totalPages,
lastPage: action.lastPage,
},
};
case "FETCH_CATEGORIES":
return {
...state,
categories: action.payload,
pagination: {
...state.pagination,
pageNumber: action.pageNumber,
pageSize: action.pageSize,
totalElements: action.totalElements,
totalPages: action.totalPages,
lastPage: action.lastPage,
},
};
default:
return state;
}
};
================================================
FILE: ecom-frontend/src/store/reducers/adminReducer.js
================================================
const initialState = {
analytics: {},
};
export const adminReducer = (state = initialState, action) => {
switch (action.type) {
case "FETCH_ANALYTICS":
return {
...state,
analytics: action.payload,
};
default:
return state;
}
};
================================================
FILE: ecom-frontend/src/store/reducers/authReducer.js
================================================
const initialState = {
user: null,
address: [],
clientSecret: null,
selectedUserCheckoutAddress: null,
}
export const authReducer = (state = initialState, action) => {
switch (action.type) {
case "LOGIN_USER":
return { ...state, user: action.payload };
case "USER_ADDRESS":
return { ...state, address: action.payload };
case "SELECT_CHECKOUT_ADDRESS":
return { ...state, selectedUserCheckoutAddress: action.payload };
case "REMOVE_CHECKOUT_ADDRESS":
return { ...state, selectedUserCheckoutAddress: null };
case "CLIENT_SECRET":
return { ...state, clientSecret: action.payload };
case "REMOVE_CLIENT_SECRET_ADDRESS":
return { ...state, clientSecret: null, selectedUserCheckoutAddress: null };
case "LOG_OUT":
return {
user: null,
address: null,
};
default:
return state;
}
};
================================================
FILE: ecom-frontend/src/store/reducers/cartReducer.js
================================================
const initialState = {
cart: [],
totalPrice: 0,
cartId: null,
}
export const cartReducer = (state = initialState, action) => {
switch (action.type) {
case "ADD_CART":
const productToAdd = action.payload;
const existingProduct = state.cart.find(
(item) => item.productId === productToAdd.productId
);
if(existingProduct) {
const updatedCart = state.cart.map((item) => {
if (item.productId === productToAdd.productId) {
return productToAdd;
} else {
return item;
}
});
return {
...state,
cart: updatedCart,
};
} else {
const newCart = [...state.cart, productToAdd];
return {
...state,
cart: newCart,
};
}
case "REMOVE_CART":
return {
...state,
cart: state.cart.filter(
(item) => item.productId !== action.payload.productId
),
};
case "GET_USER_CART_PRODUCTS":
return {
...state,
cart: action.payload,
totalPrice: action.totalPrice,
cartId: action.cartId,
};
case "CLEAR_CART":
return { cart:[], totalPrice: 0, cartId: null};
default:
return state;
}
return state;
}
================================================
FILE: ecom-frontend/src/store/reducers/errorReducer.js
================================================
const initialState = {
isLoading: false,
errorMessage: null,
categoryLoader: false,
categoryError: null,
btnLoader: false,
};
export const errorReducer = (state = initialState, action) => {
switch (action.type) {
case "IS_FETCHING":
return {
...state,
isLoading: true,
errorMessage: null,
};
case "BUTTON_LOADER":
return {
...state,
btnLoader: true,
errorMessage: null,
categoryError: null,
};
case "IS_SUCCESS":
return {
...state,
isLoading: false,
errorMessage: null,
btnLoader: false,
categoryError: null,
categoryLoader: false,
};
case "IS_ERROR":
return {
...state,
isLoading: false,
errorMessage: action.payload,
btnLoader: false,
categoryLoader: false,
}
case "CATEGORY_SUCCESS":
return {
...state,
categoryLoader: false,
categoryError: null,
};
case "CATEGORY_LOADER":
return {
...state,
categoryLoader: true,
categoryError: null,
errorMessage: null,
}
default:
return state;
}
};
================================================
FILE: ecom-frontend/src/store/reducers/orderReducer.js
================================================
const initialState = {
adminOrder: null,
pagination: {},
};
export const orderReducer = (state = initialState, action) => {
switch (action.type) {
case "GET_ADMIN_ORDERS":
return {
...state,
adminOrder: action.payload,
pagination: {
...state.pagination,
pageNumber: action.pageNumber,
pageSize: action.pageSize,
totalElements: action.totalElements,
totalPages: action.totalPages,
lastPage: action.lastPage,
},
};
default:
return state;
}
};
================================================
FILE: ecom-frontend/src/store/reducers/paymentMethodReducer.js
================================================
const initialState = {
paymentMethod: null,
};
export const paymentMethodReducer = (state = initialState, action) => {
switch (action.type) {
case "ADD_PAYMENT_METHOD":
return {
...state,
paymentMethod: action.payload,
};
default:
return state;
}
};
================================================
FILE: ecom-frontend/src/store/reducers/sellerReducer.js
================================================
const initialState = {
sellers: null,
pagination: {},
};
export const sellerReducer = (state = initialState, action) => {
switch (action.type) {
case "GET_SELLERS":
return {
...state,
sellers: action.payload,
pagination: {
...state.pagination,
pageNumber: action.pageNumber,
pageSize: action.pageSize,
totalElements: action.totalElements,
totalPages: action.totalPages,
lastPage: action.lastPage,
},
};
default:
return state;
}
};
================================================
FILE: ecom-frontend/src/store/reducers/store.js
================================================
import { configureStore } from "@reduxjs/toolkit";
import { productReducer } from "./ProductReducer";
import { errorReducer } from "./errorReducer";
import { cartReducer } from "./cartReducer";
import { authReducer } from "./authReducer";
import { paymentMethodReducer } from "./paymentMethodReducer";
import { adminReducer } from "./adminReducer";
import { orderReducer } from "./orderReducer";
import { sellerReducer } from "./sellerReducer";
const user = localStorage.getItem("auth")
? JSON.parse(localStorage.getItem("auth"))
: null;
const cartItems = localStorage.getItem("cartItems")
? JSON.parse(localStorage.getItem("cartItems"))
: [];
const selectUserCheckoutAddress = localStorage.getItem("CHECKOUT_ADDRESS")
? JSON.parse(localStorage.getItem("CHECKOUT_ADDRESS"))
: [];
const initialState = {
auth: { user: user, selectUserCheckoutAddress },
carts: { cart: cartItems },
};
export const store = configureStore({
reducer: {
products: productReducer,
errors: errorReducer,
carts: cartReducer,
auth: authReducer,
payment: paymentMethodReducer,
admin: adminReducer,
order: orderReducer,
seller: sellerReducer,
},
preloadedState: initialState,
});
export default store;
================================================
FILE: ecom-frontend/src/utils/constant.js
================================================
import bannerImageOne from "../assets/sliders/s_1.webp";
import bannerImageTwo from "../assets/sliders/s_2.webp";
import bannerImageThree from "../assets/sliders/s_3.webp";
export {
bannerImageOne,
bannerImageTwo,
bannerImageThree
}
================================================
FILE: ecom-frontend/src/utils/formatPrice.js
================================================
export const formatPrice = (amount) => {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(amount);
}
export const formatPriceCalculation = (quantity, price) => {
return (Number(quantity) * Number(price)).toFixed(2);
}
export const formatRevenue = (value) => {
if (value >= 1e9) {
return (value / 1e9).toFixed(1) + "B";
} else if (value >= 1e6) {
return (value / 1e6).toFixed(1) + "M";
} else if (value >= 1e3) {
return (value / 1e3).toFixed(1) + "K";
} else {
return value;
}
};
================================================
FILE: ecom-frontend/src/utils/index.js
================================================
import { FaBoxOpen, FaHome, FaShoppingCart, FaStore, FaThList } from "react-icons/fa";
import { bannerImageOne, bannerImageThree, bannerImageTwo } from "./constant";
export const bannerLists = [
{
id: 1,
image: bannerImageOne,
title: "Home Comfort",
subtitle: "Living Room",
description: "Upgrade your space with cozy and stylish sofas",
},
{
id: 2,
image: bannerImageTwo,
title: "Entertainment Hub",
subtitle: "Smart TV",
description: "Experience the latest in home entertainment",
},
{
id: 3,
image: bannerImageThree,
title: "Playful Picks",
subtitle: "Kids' Clothing",
description: "Bright and fun styles for kids, up to 20% off",
}
];
export const adminNavigation = [
{
name: "Dashboard",
href: "/admin",
icon: FaHome,
current: true
}, {
name: "Orders",
href: "/admin/orders",
icon: FaShoppingCart
}, {
name: "Products",
href: "/admin/products",
icon: FaBoxOpen
}, {
name: "Categories",
href: "/admin/categories",
icon: FaThList
}, {
name: "Sellers",
href: "/admin/sellers",
icon: FaStore
}
];
export const sellerNavigation = [
{
name: "Orders",
href: "/admin/orders",
icon: FaShoppingCart,
current: true
}, {
name: "Products",
href: "/admin/products",
icon: FaBoxOpen
}
];
================================================
FILE: ecom-frontend/src/utils/truncateText.js
================================================
const truncateText = (text, charLimit = 90) => {
if (text?.length > charLimit) {
return text.slice(0, charLimit) + "...";
}
return text;
};
export default truncateText;
================================================
FILE: ecom-frontend/vite.config.js
================================================
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
})
================================================
FILE: media/.gitignore
================================================
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
================================================
FILE: media/.mvn/wrapper/maven-wrapper.properties
================================================
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
================================================
FILE: media/mvnw
================================================
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' < "$1"
fi
}
log() {
if [ "$MVNW_VERBOSE" = true ]; then
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1
fi
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
# shellcheck disable=SC2086 # safe args
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
================================================
FILE: media/mvnw.cmd
================================================
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.2.0
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%
================================================
FILE: media/pom.xml
================================================
4.0.0
org.springframework.boot
spring-boot-starter-parent
4.0.1
com.social
media
0.0.1-SNAPSHOT
media
Demo project for Spring Boot
24
org.springframework.boot
spring-boot-starter-data-jpa
org.springframework.boot
spring-boot-starter-webmvc
com.h2database
h2
runtime
org.springframework.boot
spring-boot-starter-test
test
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-maven-plugin
================================================
FILE: media/src/main/java/com/social/media/DataInitializer.java
================================================
package com.social.media;
import com.social.media.repositories.PostRepository;
import com.social.media.repositories.SocialProfileRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.social.media.models.Post;
import com.social.media.models.SocialGroup;
import com.social.media.models.SocialProfile;
import com.social.media.models.SocialUser;
import com.social.media.repositories.SocialGroupRepository;
import com.social.media.repositories.SocialUserRepository;
@Configuration
public class DataInitializer {
private final SocialUserRepository userRepository;
private final SocialGroupRepository groupRepository;
private final SocialProfileRepository socialProfileRepository;
private final PostRepository postRepository;
public DataInitializer(SocialUserRepository userRepository, SocialGroupRepository groupRepository, SocialProfileRepository socialProfileRepository, PostRepository postRepository) {
this.userRepository = userRepository;
this.groupRepository = groupRepository;
this.socialProfileRepository = socialProfileRepository;
this.postRepository = postRepository;
}
@Bean
public CommandLineRunner initializeData() {
return args -> {
// Create some users
SocialUser user1 = new SocialUser();
SocialUser user2 = new SocialUser();
SocialUser user3 = new SocialUser();
// Save users to the database
userRepository.save(user1);
userRepository.save(user2);
userRepository.save(user3);
// Create some groups
SocialGroup group1 = new SocialGroup();
SocialGroup group2 = new SocialGroup();
// Add users to groups
group1.getSocialUsers().add(user1);
group1.getSocialUsers().add(user2);
group2.getSocialUsers().add(user2);
group2.getSocialUsers().add(user3);
// Save groups to the database
groupRepository.save(group1);
groupRepository.save(group2);
// Associate users with groups
user1.getGroups().add(group1);
user2.getGroups().add(group1);
user2.getGroups().add(group2);
user3.getGroups().add(group2);
// Save users back to database to update associations
userRepository.save(user1);
userRepository.save(user2);
userRepository.save(user3);
// Create some posts
Post post1 = new Post();
Post post2 = new Post();
Post post3 = new Post();
// Associate posts with users
post1.setSocialUser(user1);
post2.setSocialUser(user2);
post3.setSocialUser(user3);
// Save posts to the database (assuming you have a PostRepository)
postRepository.save(post1);
postRepository.save(post2);
postRepository.save(post3);
// Create some social profiles
SocialProfile profile1 = new SocialProfile();
SocialProfile profile2 = new SocialProfile();
SocialProfile profile3 = new SocialProfile();
// Associate profiles with users
profile1.setUser(user1);
profile2.setUser(user2);
profile3.setUser(user3);
// Save profiles to the database (assuming you have a SocialProfileRepository)
socialProfileRepository.save(profile1);
socialProfileRepository.save(profile2);
socialProfileRepository.save(profile3);
// FETCH TYPES
System.out.println("FETCHING SOCIAL USER");
userRepository.findById(1L);
};
}
}
================================================
FILE: media/src/main/java/com/social/media/MediaApplication.java
================================================
package com.social.media;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MediaApplication {
public static void main(String[] args) {
SpringApplication.run(MediaApplication.class, args);
}
}
================================================
FILE: media/src/main/java/com/social/media/controllers/SocialController.java
================================================
package com.social.media.controllers;
import com.social.media.models.SocialUser;
import com.social.media.services.SocialService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
public class SocialController {
@Autowired
private SocialService socialService;
@GetMapping("/social/users")
public ResponseEntity> getUsers(){
return new ResponseEntity<>(socialService.getAllUsers(), HttpStatus.OK);
}
@PostMapping("/social/users")
public ResponseEntity saveUser(@RequestBody SocialUser socialUser){
return new ResponseEntity<>(socialService.saveUser(socialUser), HttpStatus.CREATED);
}
@DeleteMapping("/social/users/{userId}")
public ResponseEntity deleteUser(@PathVariable Long userId){
socialService.deleteUser(userId);
return new ResponseEntity<>("Deleted Successfully", HttpStatus.OK);
}
}
================================================
FILE: media/src/main/java/com/social/media/models/Post.java
================================================
package com.social.media.models;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "user_id")
@JsonIgnore
private SocialUser socialUser;
}
================================================
FILE: media/src/main/java/com/social/media/models/SocialGroup.java
================================================
package com.social.media.models;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SocialGroup {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToMany(mappedBy = "groups")
@JsonIgnore
private Set socialUsers = new HashSet<>();
@Override
public int hashCode(){
return Objects.hash(id);
}
}
================================================
FILE: media/src/main/java/com/social/media/models/SocialProfile.java
================================================
package com.social.media.models;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SocialProfile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne
@JoinColumn(name = "social_user")
@JsonIgnore
private SocialUser user;
private String description;
public void setSocialUser(SocialUser socialUser){
this.user = socialUser;
if (user.getSocialProfile() != this)
user.setSocialProfile(this);
}
}
================================================
FILE: media/src/main/java/com/social/media/models/SocialUser.java
================================================
package com.social.media.models;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.*;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SocialUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(mappedBy = "user",
cascade = {CascadeType.REMOVE, CascadeType.PERSIST, CascadeType.MERGE})
//@JoinColumn(name = "social_profile_id")
private SocialProfile socialProfile;
@OneToMany(mappedBy = "socialUser", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List posts = new ArrayList<>();
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "user_group",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "group_id")
)
private Set groups = new HashSet<>();
@Override
public int hashCode(){
return Objects.hash(id);
}
public void setSocialProfile(SocialProfile socialProfile){
socialProfile.setUser(this);
this.socialProfile = socialProfile;
}
}
================================================
FILE: media/src/main/java/com/social/media/repositories/PostRepository.java
================================================
package com.social.media.repositories;
import com.social.media.models.Post;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostRepository extends JpaRepository {
}
================================================
FILE: media/src/main/java/com/social/media/repositories/SocialGroupRepository.java
================================================
package com.social.media.repositories;
import com.social.media.models.SocialGroup;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SocialGroupRepository extends JpaRepository {
}
================================================
FILE: media/src/main/java/com/social/media/repositories/SocialProfileRepository.java
================================================
package com.social.media.repositories;
import com.social.media.models.SocialProfile;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SocialProfileRepository extends JpaRepository {
}
================================================
FILE: media/src/main/java/com/social/media/repositories/SocialUserRepository.java
================================================
package com.social.media.repositories;
import com.social.media.models.SocialUser;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SocialUserRepository extends JpaRepository {
}
================================================
FILE: media/src/main/java/com/social/media/services/SocialService.java
================================================
package com.social.media.services;
import com.social.media.models.SocialUser;
import com.social.media.repositories.SocialUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class SocialService {
@Autowired
SocialUserRepository socialUserRepository;
public List getAllUsers() {
return socialUserRepository.findAll();
}
public SocialUser saveUser(SocialUser socialUser) {
return socialUserRepository.save(socialUser);
}
public SocialUser deleteUser(Long id) {
SocialUser socialUser = socialUserRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found"));
socialUserRepository.delete(socialUser);
return socialUser;
}
}
================================================
FILE: media/src/main/resources/application.properties
================================================
spring.application.name=media
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:test
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
================================================
FILE: media/src/test/java/com/social/media/MediaApplicationTests.java
================================================
package com.social.media;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MediaApplicationTests {
@Test
void contextLoads() {
}
}
================================================
FILE: sb-ecom/.gitignore
================================================
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
# Ignore the images folder
images/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
================================================
FILE: sb-ecom/.mvn/wrapper/maven-wrapper.properties
================================================
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
================================================
FILE: sb-ecom/mvnw
================================================
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' < "$1"
fi
}
log() {
if [ "$MVNW_VERBOSE" = true ]; then
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1
fi
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
# shellcheck disable=SC2086 # safe args
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
================================================
FILE: sb-ecom/mvnw.cmd
================================================
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.2.0
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%
================================================
FILE: sb-ecom/pom.xml
================================================
4.0.0
org.springframework.boot
spring-boot-starter-parent
4.0.1
com.ecommerce
sb-ecom
0.0.1-SNAPSHOT
sb-ecom
Spring Boot Ecommerce Project
24
org.springframework.boot
spring-boot-starter-webmvc
org.springframework.boot
spring-boot-starter-data-jpa
org.springdoc
springdoc-openapi-starter-webmvc-ui
3.0.0
com.stripe
stripe-java
29.3.0
org.postgresql
postgresql
runtime
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-validation
org.springframework.boot
spring-boot-starter-test
test
org.modelmapper
modelmapper
3.0.0
org.springframework.boot
spring-boot-starter-security
io.jsonwebtoken
jjwt-api
0.13.0
io.jsonwebtoken
jjwt-impl
0.13.0
runtime
io.jsonwebtoken
jjwt-jackson
0.13.0
runtime
org.springframework.security
spring-security-test
test
org.springframework.boot
spring-boot-maven-plugin
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/SbEcomApplication.java
================================================
package com.ecommerce.project;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SbEcomApplication {
public static void main(String[] args) {
SpringApplication.run(SbEcomApplication.class, args);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/config/AppConfig.java
================================================
package com.ecommerce.project.config;
import org.modelmapper.ModelMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public ModelMapper modelMapper(){
return new ModelMapper();
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/config/AppConstants.java
================================================
package com.ecommerce.project.config;
public class AppConstants {
public static final String PAGE_NUMBER = "0";
public static final String PAGE_SIZE = "10";
public static final String SORT_CATEGORIES_BY = "categoryId";
public static final String SORT_PRODUCTS_BY = "productId";
public static final String SORT_DIR = "asc";
public static final String SORT_ORDERS_BY = "totalAmount";
public static final String SORT_USERS_BY = "userId";
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/config/SwaggerConfig.java
================================================
package com.ecommerce.project.config;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI customOpenAPI() {
SecurityScheme bearerScheme = new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.description("JWT Bearer Token");
SecurityRequirement bearerRequirement = new SecurityRequirement()
.addList("Bearer Authentication");
return new OpenAPI()
.info(new Info()
.title("Spring Boot eCommerce API")
.version("1.0")
.description("This is a Spring Boot Project for eCommerce")
.license(new License().name("Our License Link").url("http://embarkx.com"))
.contact(new Contact()
.name("Faisal Memon")
.email("faisal@embarkx.com")
.url("https://github.com/EmbarkxOfficial")))
.externalDocs(new ExternalDocumentation()
.description("Project Documentation")
.url("http://embarkx.com"))
.components(new Components()
.addSecuritySchemes("Bearer Authentication", bearerScheme))
.addSecurityItem(bearerRequirement);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/config/WebMvcConfig.java
================================================
package com.ecommerce.project.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**").addResourceLocations("file:images/");
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/controller/AddressController.java
================================================
package com.ecommerce.project.controller;
import com.ecommerce.project.model.User;
import com.ecommerce.project.payload.AddressDTO;
import com.ecommerce.project.service.AddressService;
import com.ecommerce.project.util.AuthUtil;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api")
public class AddressController {
@Autowired
AuthUtil authUtil;
@Autowired
AddressService addressService;
@PostMapping("/addresses")
public ResponseEntity createAddress(@Valid @RequestBody AddressDTO addressDTO){
User user = authUtil.loggedInUser();
AddressDTO savedAddressDTO = addressService.createAddress(addressDTO, user);
return new ResponseEntity<>(savedAddressDTO, HttpStatus.CREATED);
}
@GetMapping("/addresses")
public ResponseEntity> getAddresses(){
List addressList = addressService.getAddresses();
return new ResponseEntity<>(addressList, HttpStatus.OK);
}
@GetMapping("/addresses/{addressId}")
public ResponseEntity getAddressById(@PathVariable Long addressId){
AddressDTO addressDTO = addressService.getAddressesById(addressId);
return new ResponseEntity<>(addressDTO, HttpStatus.OK);
}
@GetMapping("/users/addresses")
public ResponseEntity> getUserAddresses(){
User user = authUtil.loggedInUser();
List addressList = addressService.getUserAddresses(user);
return new ResponseEntity<>(addressList, HttpStatus.OK);
}
@PutMapping("/addresses/{addressId}")
public ResponseEntity updateAddress(@PathVariable Long addressId
, @RequestBody AddressDTO addressDTO){
AddressDTO updatedAddress = addressService.updateAddress(addressId, addressDTO);
return new ResponseEntity<>(updatedAddress, HttpStatus.OK);
}
@DeleteMapping("/addresses/{addressId}")
public ResponseEntity updateAddress(@PathVariable Long addressId){
String status = addressService.deleteAddress(addressId);
return new ResponseEntity<>(status, HttpStatus.OK);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/controller/AnalyticsController.java
================================================
package com.ecommerce.project.controller;
import com.ecommerce.project.payload.AnalyticsResponse;
import com.ecommerce.project.service.AnalyticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class AnalyticsController {
@Autowired
private AnalyticsService analyticsService;
@GetMapping("/admin/app/analytics")
public ResponseEntity getAnalytics() {
AnalyticsResponse response = analyticsService.getAnalyticsData();
return new ResponseEntity(response, HttpStatus.OK);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/controller/AuthController.java
================================================
package com.ecommerce.project.controller;
import com.ecommerce.project.config.AppConstants;
import com.ecommerce.project.payload.AuthenticationResult;
import com.ecommerce.project.security.request.LoginRequest;
import com.ecommerce.project.security.request.SignupRequest;
import com.ecommerce.project.security.response.MessageResponse;
import com.ecommerce.project.service.AuthService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
AuthService authService;
@PostMapping("/signin")
public ResponseEntity> authenticateUser(@RequestBody LoginRequest loginRequest) {
AuthenticationResult result = authService.login(loginRequest);
return ResponseEntity.ok().header(HttpHeaders.SET_COOKIE,
result.getJwtCookie().toString())
.body(result.getResponse());
}
@PostMapping("/signup")
public ResponseEntity> registerUser(@Valid @RequestBody SignupRequest signUpRequest) {
return authService.register(signUpRequest);
}
@GetMapping("/username")
public String currentUserName(Authentication authentication){
if (authentication != null)
return authentication.getName();
else
return "";
}
@GetMapping("/user")
public ResponseEntity> getUserDetails(Authentication authentication){
return ResponseEntity.ok().body(authService.getCurrentUserDetails(authentication));
}
@PostMapping("/signout")
public ResponseEntity> signoutUser(){
ResponseCookie cookie = authService.logoutUser();
return ResponseEntity.ok().header(HttpHeaders.SET_COOKIE,
cookie.toString())
.body(new MessageResponse("You've been signed out!"));
}
@GetMapping("/sellers")
public ResponseEntity> getAllSellers(
@RequestParam(name = "pageNumber", defaultValue = AppConstants.PAGE_NUMBER, required = false) Integer pageNumber) {
Sort sortByAndOrder = Sort.by(AppConstants.SORT_USERS_BY).descending();
Pageable pageDetails = PageRequest.of(pageNumber ,
Integer.parseInt(AppConstants.PAGE_SIZE), sortByAndOrder);
return ResponseEntity.ok(authService.getAllSellers(pageDetails));
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/controller/CartController.java
================================================
package com.ecommerce.project.controller;
import com.ecommerce.project.model.Cart;
import com.ecommerce.project.payload.CartDTO;
import com.ecommerce.project.payload.CartItemDTO;
import com.ecommerce.project.repositories.CartRepository;
import com.ecommerce.project.service.CartService;
import com.ecommerce.project.util.AuthUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api")
public class CartController {
@Autowired
private CartRepository cartRepository;
@Autowired
private AuthUtil authUtil;
@Autowired
private CartService cartService;
@PostMapping("/cart/create")
public ResponseEntity createOrUpdateCart(@RequestBody List cartItems){
String response = cartService.createOrUpdateCartWithItems(cartItems);
return new ResponseEntity<>(response, HttpStatus.CREATED);
}
@PostMapping("/carts/products/{productId}/quantity/{quantity}")
public ResponseEntity addProductToCart(@PathVariable Long productId,
@PathVariable Integer quantity){
CartDTO cartDTO = cartService.addProductToCart(productId, quantity);
return new ResponseEntity(cartDTO, HttpStatus.CREATED);
}
@GetMapping("/carts")
public ResponseEntity> getCarts() {
List cartDTOs = cartService.getAllCarts();
return new ResponseEntity>(cartDTOs, HttpStatus.FOUND);
}
@GetMapping("/carts/users/cart")
public ResponseEntity getCartById(){
String emailId = authUtil.loggedInEmail();
Cart cart = cartRepository.findCartByEmail(emailId);
Long cartId = cart.getCartId();
CartDTO cartDTO = cartService.getCart(emailId, cartId);
return new ResponseEntity(cartDTO, HttpStatus.OK);
}
@PutMapping("/cart/products/{productId}/quantity/{operation}")
public ResponseEntity updateCartProduct(@PathVariable Long productId,
@PathVariable String operation) {
CartDTO cartDTO = cartService.updateProductQuantityInCart(productId,
operation.equalsIgnoreCase("delete") ? -1 : 1);
return new ResponseEntity(cartDTO, HttpStatus.OK);
}
@DeleteMapping("/carts/{cartId}/product/{productId}")
public ResponseEntity deleteProductFromCart(@PathVariable Long cartId,
@PathVariable Long productId) {
String status = cartService.deleteProductFromCart(cartId, productId);
return new ResponseEntity(status, HttpStatus.OK);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/controller/CategoryController.java
================================================
package com.ecommerce.project.controller;
import com.ecommerce.project.config.AppConstants;
import com.ecommerce.project.payload.CategoryDTO;
import com.ecommerce.project.payload.CategoryResponse;
import com.ecommerce.project.service.CategoryService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class CategoryController {
@Autowired
private CategoryService categoryService;
@GetMapping("/public/categories")
public ResponseEntity getAllCategories(
@RequestParam(name = "pageNumber", defaultValue = AppConstants.PAGE_NUMBER, required = false) Integer pageNumber,
@RequestParam(name = "pageSize", defaultValue = AppConstants.PAGE_SIZE, required = false) Integer pageSize,
@RequestParam(name = "sortBy", defaultValue = AppConstants.SORT_CATEGORIES_BY, required = false) String sortBy,
@RequestParam(name = "sortOrder", defaultValue = AppConstants.SORT_DIR, required = false) String sortOrder) {
CategoryResponse categoryResponse = categoryService.getAllCategories(pageNumber, pageSize, sortBy, sortOrder);
return new ResponseEntity<>(categoryResponse, HttpStatus.OK);
}
@PostMapping("/admin/categories")
public ResponseEntity createCategory(@Valid @RequestBody CategoryDTO categoryDTO){
CategoryDTO savedCategoryDTO = categoryService.createCategory(categoryDTO);
return new ResponseEntity<>(savedCategoryDTO, HttpStatus.CREATED);
}
@DeleteMapping("/admin/categories/{categoryId}")
public ResponseEntity deleteCategory(@PathVariable Long categoryId){
CategoryDTO deletedCategory = categoryService.deleteCategory(categoryId);
return new ResponseEntity<>(deletedCategory, HttpStatus.OK);
}
@PutMapping("/admin/categories/{categoryId}")
public ResponseEntity updateCategory(@Valid @RequestBody CategoryDTO categoryDTO,
@PathVariable Long categoryId){
CategoryDTO savedCategoryDTO = categoryService.updateCategory(categoryDTO, categoryId);
return new ResponseEntity<>(savedCategoryDTO, HttpStatus.OK);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/controller/OrderController.java
================================================
package com.ecommerce.project.controller;
import com.ecommerce.project.config.AppConstants;
import com.ecommerce.project.payload.*;
import com.ecommerce.project.security.services.UserDetailsImpl;
import com.ecommerce.project.service.OrderService;
import com.ecommerce.project.service.StripeService;
import com.ecommerce.project.util.AuthUtil;
import com.stripe.exception.StripeException;
import com.stripe.model.PaymentIntent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private AuthUtil authUtil;
@Autowired
private StripeService stripeService;
@PostMapping("/order/users/payments/{paymentMethod}")
public ResponseEntity orderProducts(@PathVariable String paymentMethod, @RequestBody OrderRequestDTO orderRequestDTO) {
String emailId = authUtil.loggedInEmail();
System.out.println("orderRequestDTO DATA: " + orderRequestDTO);
OrderDTO order = orderService.placeOrder(
emailId,
orderRequestDTO.getAddressId(),
paymentMethod,
orderRequestDTO.getPgName(),
orderRequestDTO.getPgPaymentId(),
orderRequestDTO.getPgStatus(),
orderRequestDTO.getPgResponseMessage()
);
return new ResponseEntity<>(order, HttpStatus.CREATED);
}
@PostMapping("/order/stripe-client-secret")
public ResponseEntity createStripeClientSecret(@RequestBody StripePaymentDto stripePaymentDto) throws StripeException {
System.out.println("StripePaymentDTO Received " + stripePaymentDto);
PaymentIntent paymentIntent = stripeService.paymentIntent(stripePaymentDto);
return new ResponseEntity<>(paymentIntent.getClientSecret(), HttpStatus.CREATED);
}
@GetMapping("/admin/orders")
public ResponseEntity getAllOrders(
@RequestParam(name = "pageNumber", defaultValue = AppConstants.PAGE_NUMBER, required = false) Integer pageNumber,
@RequestParam(name = "pageSize", defaultValue = AppConstants.PAGE_SIZE, required = false) Integer pageSize,
@RequestParam(name = "sortBy", defaultValue = AppConstants.SORT_ORDERS_BY, required = false) String sortBy,
@RequestParam(name = "sortOrder", defaultValue = AppConstants.SORT_DIR, required = false) String sortOrder
) {
OrderResponse orderResponse = orderService.getAllOrders(pageNumber, pageSize, sortBy, sortOrder);
return new ResponseEntity(orderResponse, HttpStatus.OK);
}
@GetMapping("/seller/orders")
public ResponseEntity getAllSellerOrders(
@RequestParam(name = "pageNumber", defaultValue = AppConstants.PAGE_NUMBER, required = false) Integer pageNumber,
@RequestParam(name = "pageSize", defaultValue = AppConstants.PAGE_SIZE, required = false) Integer pageSize,
@RequestParam(name = "sortBy", defaultValue = AppConstants.SORT_ORDERS_BY, required = false) String sortBy,
@RequestParam(name = "sortOrder", defaultValue = AppConstants.SORT_DIR, required = false) String sortOrder
) {
OrderResponse orderResponse = orderService.getAllSellerOrders(pageNumber, pageSize, sortBy, sortOrder);
return new ResponseEntity(orderResponse, HttpStatus.OK);
}
@PutMapping("/admin/orders/{orderId}/status")
public ResponseEntity updateOrderStatus(@PathVariable Long orderId,
@RequestBody OrderStatusUpdateDto orderStatusUpdateDto) {
OrderDTO order = orderService.updateOrder(orderId, orderStatusUpdateDto.getStatus());
return new ResponseEntity(order, HttpStatus.OK);
}
@PutMapping("/seller/orders/{orderId}/status")
public ResponseEntity updateOrderStatusSeller(@PathVariable Long orderId,
@RequestBody OrderStatusUpdateDto orderStatusUpdateDto) {
OrderDTO order = orderService.updateOrder(orderId, orderStatusUpdateDto.getStatus());
return new ResponseEntity(order, HttpStatus.OK);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/controller/ProductController.java
================================================
package com.ecommerce.project.controller;
import com.ecommerce.project.config.AppConstants;
import com.ecommerce.project.payload.ProductDTO;
import com.ecommerce.project.payload.ProductResponse;
import com.ecommerce.project.service.ProductService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
@RestController
@RequestMapping("/api")
public class ProductController {
@Autowired
ProductService productService;
@PostMapping("/admin/categories/{categoryId}/product")
public ResponseEntity addProduct(@Valid @RequestBody ProductDTO productDTO,
@PathVariable Long categoryId){
ProductDTO savedProductDTO = productService.addProduct(categoryId, productDTO);
return new ResponseEntity<>(savedProductDTO, HttpStatus.CREATED);
}
@PostMapping("/seller/categories/{categoryId}/product")
public ResponseEntity addProductSeller(@Valid @RequestBody ProductDTO productDTO,
@PathVariable Long categoryId){
ProductDTO savedProductDTO = productService.addProduct(categoryId, productDTO);
return new ResponseEntity<>(savedProductDTO, HttpStatus.CREATED);
}
@GetMapping("/public/products")
public ResponseEntity getAllProducts(
@RequestParam(name = "keyword", required = false) String keyword,
@RequestParam(name = "category", required = false) String category,
@RequestParam(name = "pageNumber", defaultValue = AppConstants.PAGE_NUMBER, required = false) Integer pageNumber,
@RequestParam(name = "pageSize", defaultValue = AppConstants.PAGE_SIZE, required = false) Integer pageSize,
@RequestParam(name = "sortBy", defaultValue = AppConstants.SORT_PRODUCTS_BY, required = false) String sortBy,
@RequestParam(name = "sortOrder", defaultValue = AppConstants.SORT_DIR, required = false) String sortOrder
){
ProductResponse productResponse = productService.getAllProducts(pageNumber, pageSize, sortBy, sortOrder, keyword, category);
return new ResponseEntity<>(productResponse,HttpStatus.OK);
}
@GetMapping("/public/categories/{categoryId}/products")
public ResponseEntity getProductsByCategory(@PathVariable Long categoryId,
@RequestParam(name = "pageNumber", defaultValue = AppConstants.PAGE_NUMBER, required = false) Integer pageNumber,
@RequestParam(name = "pageSize", defaultValue = AppConstants.PAGE_SIZE, required = false) Integer pageSize,
@RequestParam(name = "sortBy", defaultValue = AppConstants.SORT_PRODUCTS_BY, required = false) String sortBy,
@RequestParam(name = "sortOrder", defaultValue = AppConstants.SORT_DIR, required = false) String sortOrder){
ProductResponse productResponse = productService.searchByCategory(categoryId, pageNumber, pageSize, sortBy, sortOrder);
return new ResponseEntity<>(productResponse, HttpStatus.OK);
}
@GetMapping("/public/products/keyword/{keyword}")
public ResponseEntity getProductsByKeyword(@PathVariable String keyword,
@RequestParam(name = "pageNumber", defaultValue = AppConstants.PAGE_NUMBER, required = false) Integer pageNumber,
@RequestParam(name = "pageSize", defaultValue = AppConstants.PAGE_SIZE, required = false) Integer pageSize,
@RequestParam(name = "sortBy", defaultValue = AppConstants.SORT_PRODUCTS_BY, required = false) String sortBy,
@RequestParam(name = "sortOrder", defaultValue = AppConstants.SORT_DIR, required = false) String sortOrder){
ProductResponse productResponse = productService.searchProductByKeyword(keyword, pageNumber, pageSize, sortBy, sortOrder);
return new ResponseEntity<>(productResponse, HttpStatus.FOUND);
}
@PutMapping("/admin/products/{productId}")
public ResponseEntity updateProduct(@Valid @RequestBody ProductDTO productDTO,
@PathVariable Long productId){
ProductDTO updatedProductDTO = productService.updateProduct(productId, productDTO);
return new ResponseEntity<>(updatedProductDTO, HttpStatus.OK);
}
@DeleteMapping("/admin/products/{productId}")
public ResponseEntity deleteProduct(@PathVariable Long productId){
ProductDTO deletedProduct = productService.deleteProduct(productId);
return new ResponseEntity<>(deletedProduct, HttpStatus.OK);
}
@PutMapping("/admin/products/{productId}/image")
public ResponseEntity updateProductImage(@PathVariable Long productId,
@RequestParam("image")MultipartFile image) throws IOException {
ProductDTO updatedProduct = productService.updateProductImage(productId, image);
return new ResponseEntity<>(updatedProduct, HttpStatus.OK);
}
@GetMapping("/admin/products")
public ResponseEntity getAllProductsForAdmin(
@RequestParam(name = "pageNumber", defaultValue = AppConstants.PAGE_NUMBER, required = false) Integer pageNumber,
@RequestParam(name = "pageSize", defaultValue = AppConstants.PAGE_SIZE, required = false) Integer pageSize,
@RequestParam(name = "sortBy", defaultValue = AppConstants.SORT_PRODUCTS_BY, required = false) String sortBy,
@RequestParam(name = "sortOrder", defaultValue = AppConstants.SORT_DIR, required = false) String sortOrder
){
ProductResponse productResponse = productService.getAllProductsForAdmin(pageNumber, pageSize, sortBy, sortOrder);
return new ResponseEntity<>(productResponse,HttpStatus.OK);
}
@GetMapping("/seller/products")
public ResponseEntity getAllProductsForSeller(
@RequestParam(name = "pageNumber", defaultValue = AppConstants.PAGE_NUMBER, required = false) Integer pageNumber,
@RequestParam(name = "pageSize", defaultValue = AppConstants.PAGE_SIZE, required = false) Integer pageSize,
@RequestParam(name = "sortBy", defaultValue = AppConstants.SORT_PRODUCTS_BY, required = false) String sortBy,
@RequestParam(name = "sortOrder", defaultValue = AppConstants.SORT_DIR, required = false) String sortOrder
){
ProductResponse productResponse = productService.getAllProductsForSeller(pageNumber, pageSize, sortBy, sortOrder);
return new ResponseEntity<>(productResponse,HttpStatus.OK);
}
@PutMapping("/seller/products/{productId}")
public ResponseEntity updateProductSeller(@Valid @RequestBody ProductDTO productDTO,
@PathVariable Long productId){
ProductDTO updatedProductDTO = productService.updateProduct(productId, productDTO);
return new ResponseEntity<>(updatedProductDTO, HttpStatus.OK);
}
@DeleteMapping("/seller/products/{productId}")
public ResponseEntity deleteProductSeller(@PathVariable Long productId){
ProductDTO deletedProduct = productService.deleteProduct(productId);
return new ResponseEntity<>(deletedProduct, HttpStatus.OK);
}
@PutMapping("/seller/products/{productId}/image")
public ResponseEntity updateProductImageSeller(@PathVariable Long productId,
@RequestParam("image")MultipartFile image) throws IOException {
ProductDTO updatedProduct = productService.updateProductImage(productId, image);
return new ResponseEntity<>(updatedProduct, HttpStatus.OK);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/exceptions/APIException.java
================================================
package com.ecommerce.project.exceptions;
public class APIException extends RuntimeException {
private static final long serialVersionUID = 1L;
public APIException() {
}
public APIException(String message) {
super(message);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/exceptions/MyGlobalExceptionHandler.java
================================================
package com.ecommerce.project.exceptions;
import com.ecommerce.project.payload.APIResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class MyGlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity> myMethodArgumentNotValidException(MethodArgumentNotValidException e) {
Map response = new HashMap<>();
e.getBindingResult().getAllErrors().forEach(err -> {
String fieldName = ((FieldError) err).getField();
String message = err.getDefaultMessage();
response.put(fieldName, message);
});
return new ResponseEntity>(response,
HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity myResourceNotFoundException(ResourceNotFoundException e) {
String message = e.getMessage();
APIResponse apiResponse = new APIResponse(message, false);
return new ResponseEntity<>(apiResponse, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(APIException.class)
public ResponseEntity myAPIException(APIException e) {
String message = e.getMessage();
APIResponse apiResponse = new APIResponse(message, false);
return new ResponseEntity<>(apiResponse, HttpStatus.BAD_REQUEST);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/exceptions/ResourceNotFoundException.java
================================================
package com.ecommerce.project.exceptions;
public class ResourceNotFoundException extends RuntimeException {
String resourceName;
String field;
String fieldName;
Long fieldId;
public ResourceNotFoundException() {
}
public ResourceNotFoundException(String resourceName, String field, String fieldName) {
super(String.format("%s not found with %s: %s", resourceName, field, fieldName));
this.resourceName = resourceName;
this.field = field;
this.fieldName = fieldName;
}
public ResourceNotFoundException(String resourceName, String field, Long fieldId) {
super(String.format("%s not found with %s: %d", resourceName, field, fieldId));
this.resourceName = resourceName;
this.field = field;
this.fieldId = fieldId;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/model/Address.java
================================================
package com.ecommerce.project.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "addresses")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long addressId;
@NotBlank
@Size(min = 5, message = "Street name must be atleast 5 characters")
private String street;
@NotBlank
@Size(min = 5, message = "Building name must be atleast 5 characters")
private String buildingName;
@NotBlank
@Size(min = 4, message = "City name must be atleast 4 characters")
private String city;
@NotBlank
@Size(min = 2, message = "State name must be atleast 2 characters")
private String state;
@NotBlank
@Size(min = 2, message = "Country name must be atleast 2 characters")
private String country;
@NotBlank
@Size(min = 5, message = "Pincode must be atleast 5 characters")
private String pincode;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
public Address(String street, String buildingName, String city, String state, String country, String pincode) {
this.street = street;
this.buildingName = buildingName;
this.city = city;
this.state = state;
this.country = country;
this.pincode = pincode;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/model/AppRole.java
================================================
package com.ecommerce.project.model;
public enum AppRole {
ROLE_USER,
ROLE_SELLER,
ROLE_ADMIN
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/model/Cart.java
================================================
package com.ecommerce.project.model;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Entity
@Data
@Table(name = "carts")
@NoArgsConstructor
@AllArgsConstructor
public class Cart {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long cartId;
@OneToOne
@JoinColumn(name = "user_id")
private User user;
@OneToMany(mappedBy = "cart", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, orphanRemoval = true)
private List cartItems = new ArrayList<>();
private Double totalPrice = 0.0;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/model/CartItem.java
================================================
package com.ecommerce.project.model;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Data
@Table(name = "cart_items")
@NoArgsConstructor
@AllArgsConstructor
public class CartItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long cartItemId;
@ManyToOne
@JoinColumn(name = "cart_id")
private Cart cart;
@ManyToOne
@JoinColumn(name = "product_id")
private Product product;
private Integer quantity;
private double discount;
private double productPrice;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/model/Category.java
================================================
package com.ecommerce.project.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Entity(name = "categories")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long categoryId;
@NotBlank
@Size(min = 5, message = "Category name must contain atleast 5 characters")
private String categoryName;
@OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
private List products;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/model/Order.java
================================================
package com.ecommerce.project.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "orders")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long orderId;
@Email
@Column(nullable = false)
private String email;
@OneToMany(mappedBy = "order", cascade = { CascadeType.PERSIST, CascadeType.MERGE })
private List orderItems = new ArrayList<>();
private LocalDate orderDate;
@OneToOne
@JoinColumn(name = "payment_id")
private Payment payment;
private Double totalAmount;
private String orderStatus;
// Reference to Address
@ManyToOne
@JoinColumn(name = "address_id")
private Address address;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/model/OrderItem.java
================================================
package com.ecommerce.project.model;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Data
@Table(name = "order_items")
@AllArgsConstructor
@NoArgsConstructor
public class OrderItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long orderItemId;
@ManyToOne
@JoinColumn(name = "product_id")
private Product product;
@ManyToOne
@JoinColumn(name = "order_id")
private Order order;
private Integer quantity;
private double discount;
private double orderedProductPrice;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/model/Payment.java
================================================
package com.ecommerce.project.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Table(name = "payments")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Payment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long paymentId;
@OneToOne(mappedBy = "payment", cascade = { CascadeType.PERSIST, CascadeType.MERGE })
private Order order;
@NotBlank
@Size(min = 4, message = "Payment method must contain at least 4 characters")
private String paymentMethod;
private String pgPaymentId;
private String pgStatus;
private String pgResponseMessage;
private String pgName;
public Payment(String paymentMethod, String pgPaymentId, String pgStatus,
String pgResponseMessage, String pgName) {
this.paymentMethod = paymentMethod;
this.pgPaymentId = pgPaymentId;
this.pgStatus = pgStatus;
this.pgResponseMessage = pgResponseMessage;
this.pgName = pgName;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/model/Product.java
================================================
package com.ecommerce.project.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.ArrayList;
import java.util.List;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "products")
@ToString
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long productId;
@NotBlank
@Size(min = 3, message = "Product name must contain atleast 3 characters")
private String productName;
private String image;
@NotBlank
@Size(min = 6, message = "Product description must contain atleast 6 characters")
private String description;
private Integer quantity;
private double price;
private double discount;
private double specialPrice;
@ManyToOne
@JoinColumn(name = "category_id")
private Category category;
@ManyToOne
@JoinColumn(name = "seller_id")
private User user;
@OneToMany(mappedBy = "product", cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.EAGER)
private List products = new ArrayList<>();
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/model/Role.java
================================================
package com.ecommerce.project.model;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "role_id")
private Integer roleId;
@ToString.Exclude
@Enumerated(EnumType.STRING)
@Column(length = 20, name = "role_name")
private AppRole roleName;
public Role(AppRole roleName) {
this.roleName = roleName;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/model/User.java
================================================
package com.ecommerce.project.model;
import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "users",
uniqueConstraints = {
@UniqueConstraint(columnNames = "username"),
@UniqueConstraint(columnNames = "email")
})
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long userId;
@NotBlank
@Size(max = 20)
@Column(name = "username")
private String userName;
@NotBlank
@Size(max = 50)
@Email
@Column(name = "email")
private String email;
@NotBlank
@Size(max = 120)
@Column(name = "password")
private String password;
public User(String userName, String email, String password) {
this.userName = userName;
this.email = email;
this.password = password;
}
@Setter
@Getter
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE},
fetch = FetchType.EAGER)
@JoinTable(name = "user_role",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set roles = new HashSet<>();
@Getter
@Setter
@OneToMany(mappedBy = "user", cascade = {CascadeType.PERSIST, CascadeType.MERGE}, orphanRemoval = true)
// @JoinTable(name = "user_address",
// joinColumns = @JoinColumn(name = "user_id"),
// inverseJoinColumns = @JoinColumn(name = "address_id"))
private List addresses = new ArrayList<>();
@ToString.Exclude
@OneToOne(mappedBy = "user", cascade = { CascadeType.PERSIST, CascadeType.MERGE}, orphanRemoval = true)
private Cart cart;
@ToString.Exclude
@OneToMany(mappedBy = "user",
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
orphanRemoval = true)
private Set products;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/APIResponse.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class APIResponse {
public String message;
private boolean status;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/AddressDTO.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AddressDTO {
private Long addressId;
private String street;
private String buildingName;
private String city;
private String state;
private String country;
private String pincode;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/AnalyticsResponse.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AnalyticsResponse {
private String productCount;
private String totalRevenue;
private String totalOrders;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/AuthenticationResult.java
================================================
package com.ecommerce.project.payload;
import com.ecommerce.project.security.response.UserInfoResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.http.ResponseCookie;
@Data
@AllArgsConstructor
public class AuthenticationResult {
private final UserInfoResponse response;
private final ResponseCookie jwtCookie;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/CartDTO.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CartDTO {
private Long cartId;
private Double totalPrice = 0.0;
private List products = new ArrayList<>();
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/CartItemDTO.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CartItemDTO {
private Long productId;
private Integer quantity;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/CategoryDTO.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CategoryDTO {
private Long categoryId;
private String categoryName;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/CategoryResponse.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CategoryResponse {
private List content;
private Integer pageNumber;
private Integer pageSize;
private Long totalElements;
private Integer totalPages;
private boolean lastPage;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/OrderDTO.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrderDTO {
private Long orderId;
private String email;
private List orderItems;
private LocalDate orderDate;
private PaymentDTO payment;
private Double totalAmount;
private String orderStatus;
private Long addressId;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/OrderItemDTO.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrderItemDTO {
private Long orderItemId;
private ProductDTO product;
private Integer quantity;
private double discount;
private double orderedProductPrice;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/OrderRequestDTO.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrderRequestDTO {
private Long addressId;
private String paymentMethod;
private String pgName;
private String pgPaymentId;
private String pgStatus;
private String pgResponseMessage;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/OrderResponse.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrderResponse {
private List content;
private Integer pageNumber;
private Integer pageSize;
private Long totalElements;
private Integer totalPages;
private boolean lastPage;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/OrderStatusUpdateDto.java
================================================
package com.ecommerce.project.payload;
import lombok.Data;
@Data
public class OrderStatusUpdateDto {
private String status;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/PaymentDTO.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PaymentDTO {
private Long paymentId;
private String paymentMethod;
private String pgPaymentId;
private String pgStatus;
private String pgResponseMessage;
private String pgName;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/ProductDTO.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductDTO {
private Long productId;
private String productName;
private String image;
private String description;
private Integer quantity;
private double price;
private double discount;
private double specialPrice;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/ProductResponse.java
================================================
package com.ecommerce.project.payload;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductResponse {
private List content;
private Integer pageNumber;
private Integer pageSize;
private Long totalElements;
private Integer totalPages;
private boolean lastPage;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/StripePaymentDto.java
================================================
package com.ecommerce.project.payload;
import com.ecommerce.project.model.Address;
import lombok.Data;
import java.util.Map;
@Data
public class StripePaymentDto {
private Long amount;
private String currency;
private String email;
private String name;
private Address address;
private String description;
private Map metadata;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/UserDTO.java
================================================
package com.ecommerce.project.payload;
import java.util.HashSet;
import java.util.Set;
import com.ecommerce.project.model.Role;
import com.ecommerce.project.model.Role;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
private Long userId;
private String username;
private String email;
private String password;
private Set roles = new HashSet<>();
private AddressDTO address;
private CartDTO cart;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/payload/UserResponse.java
================================================
package com.ecommerce.project.payload;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserResponse {
private List content;
private Integer pageNumber;
private Integer pageSize;
private Long totalElements;
private Integer totalPages;
private boolean lastPage;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/repositories/AddressRepository.java
================================================
package com.ecommerce.project.repositories;
import com.ecommerce.project.model.Address;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AddressRepository extends JpaRepository {
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/repositories/CartItemRepository.java
================================================
package com.ecommerce.project.repositories;
import com.ecommerce.project.model.CartItem;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
public interface CartItemRepository extends JpaRepository {
@Query("SELECT ci FROM CartItem ci WHERE ci.cart.id = ?1 AND ci.product.id = ?2")
CartItem findCartItemByProductIdAndCartId(Long cartId, Long productId);
@Modifying
@Query("DELETE FROM CartItem ci WHERE ci.cart.id = ?1 AND ci.product.id = ?2")
void deleteCartItemByProductIdAndCartId(Long cartId, Long productId);
@Modifying
@Query("DELETE FROM CartItem ci WHERE ci.cart.id = ?1")
void deleteAllByCartId(Long cartId);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/repositories/CartRepository.java
================================================
package com.ecommerce.project.repositories;
import com.ecommerce.project.model.Cart;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface CartRepository extends JpaRepository {
@Query("SELECT c FROM Cart c WHERE c.user.email = ?1")
Cart findCartByEmail(String email);
@Query("SELECT c FROM Cart c WHERE c.user.email = ?1 AND c.id = ?2")
Cart findCartByEmailAndCartId(String emailId, Long cartId);
@Query("SELECT c FROM Cart c JOIN FETCH c.cartItems ci JOIN FETCH ci.product p WHERE p.id = ?1")
List findCartsByProductId(Long productId);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/repositories/CategoryRepository.java
================================================
package com.ecommerce.project.repositories;
import com.ecommerce.project.model.Category;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CategoryRepository extends JpaRepository {
Category findByCategoryName(String categoryName);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/repositories/OrderItemRepository.java
================================================
package com.ecommerce.project.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.ecommerce.project.model.OrderItem;
@Repository
public interface OrderItemRepository extends JpaRepository {
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/repositories/OrderRepository.java
================================================
package com.ecommerce.project.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.ecommerce.project.model.Order;
@Repository
public interface OrderRepository extends JpaRepository {
@Query("SELECT COALESCE(SUM(o.totalAmount), 0) FROM Order o")
Double getTotalRevenue();
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/repositories/PaymentRepository.java
================================================
package com.ecommerce.project.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.ecommerce.project.model.Payment;
@Repository
public interface PaymentRepository extends JpaRepository{
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/repositories/ProductRepository.java
================================================
package com.ecommerce.project.repositories;
import com.ecommerce.project.model.Category;
import com.ecommerce.project.model.Product;
import com.ecommerce.project.model.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
@Repository
public interface ProductRepository extends JpaRepository, JpaSpecificationExecutor {
Page findByCategoryOrderByPriceAsc(Category category, Pageable pageDetails);
Page findByProductNameLikeIgnoreCase(String keyword, Pageable pageDetails);
Page findByUser(User user, Pageable pageDetails);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/repositories/RoleRepository.java
================================================
package com.ecommerce.project.repositories;
import com.ecommerce.project.model.AppRole;
import com.ecommerce.project.model.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface RoleRepository extends JpaRepository {
Optional findByRoleName(AppRole appRole);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/repositories/UserRepository.java
================================================
package com.ecommerce.project.repositories;
import com.ecommerce.project.model.AppRole;
import com.ecommerce.project.model.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface UserRepository extends JpaRepository {
Optional findByUserName(String username);
Boolean existsByUserName(String username);
Boolean existsByEmail(String email);
@Query("SELECT u FROM User u JOIN u.roles r WHERE r.roleName = :role")
Page findByRoleName(@Param("role") AppRole role, Pageable pageable);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/security/WebConfig.java
================================================
package com.ecommerce.project.security;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Value("${frontend.url}")
String frontEndUrl;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000", frontEndUrl)
.allowedMethods("GET","POST","PUT","DELETE","OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/security/WebSecurityConfig.java
================================================
package com.ecommerce.project.security;
import com.ecommerce.project.model.AppRole;
import com.ecommerce.project.model.Role;
import com.ecommerce.project.model.User;
import com.ecommerce.project.repositories.RoleRepository;
import com.ecommerce.project.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
//import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
//import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
//import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.ecommerce.project.security.jwt.AuthEntryPointJwt;
import com.ecommerce.project.security.jwt.AuthTokenFilter;
import com.ecommerce.project.security.services.UserDetailsServiceImpl;
import java.util.Set;
@Configuration
@EnableWebSecurity
//@EnableMethodSecurity
public class WebSecurityConfig {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Autowired
private AuthEntryPointJwt unauthorizedHandler;
@Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(userDetailsService);
// authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
return authConfig.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable())
.cors(cors -> {})
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth ->
auth.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/v3/api-docs/**").permitAll()
.requestMatchers("/h2-console/**").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.requestMatchers("/api/seller/**").hasAnyRole("ADMIN","SELLER")
//.requestMatchers("/api/admin/**").permitAll()
.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/swagger-ui/**").permitAll()
.requestMatchers("/api/test/**").permitAll()
.requestMatchers("/images/**").permitAll()
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.anyRequest().authenticated()
);
http.authenticationProvider(authenticationProvider());
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
http.headers(headers -> headers.frameOptions(
frameOptions -> frameOptions.sameOrigin()));
return http.build();
}
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web -> web.ignoring().requestMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**"));
}
@Bean
public CommandLineRunner initData(RoleRepository roleRepository, UserRepository userRepository, PasswordEncoder passwordEncoder) {
return args -> {
// Retrieve or create roles
Role userRole = roleRepository.findByRoleName(AppRole.ROLE_USER)
.orElseGet(() -> {
Role newUserRole = new Role(AppRole.ROLE_USER);
return roleRepository.save(newUserRole);
});
Role sellerRole = roleRepository.findByRoleName(AppRole.ROLE_SELLER)
.orElseGet(() -> {
Role newSellerRole = new Role(AppRole.ROLE_SELLER);
return roleRepository.save(newSellerRole);
});
Role adminRole = roleRepository.findByRoleName(AppRole.ROLE_ADMIN)
.orElseGet(() -> {
Role newAdminRole = new Role(AppRole.ROLE_ADMIN);
return roleRepository.save(newAdminRole);
});
Set userRoles = Set.of(userRole);
Set sellerRoles = Set.of(sellerRole);
Set adminRoles = Set.of(userRole, sellerRole, adminRole);
// Create users if not already present
if (!userRepository.existsByUserName("user1")) {
User user1 = new User("user1", "user1@example.com", passwordEncoder.encode("password1"));
userRepository.save(user1);
}
if (!userRepository.existsByUserName("seller1")) {
User seller1 = new User("seller1", "seller1@example.com", passwordEncoder.encode("password2"));
userRepository.save(seller1);
}
if (!userRepository.existsByUserName("admin")) {
User admin = new User("admin", "admin@example.com", passwordEncoder.encode("adminPass"));
userRepository.save(admin);
}
// Update roles for existing users
userRepository.findByUserName("user1").ifPresent(user -> {
user.setRoles(userRoles);
userRepository.save(user);
});
userRepository.findByUserName("seller1").ifPresent(seller -> {
seller.setRoles(sellerRoles);
userRepository.save(seller);
});
userRepository.findByUserName("admin").ifPresent(admin -> {
admin.setRoles(adminRoles);
userRepository.save(admin);
});
};
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/security/jwt/AuthEntryPointJwt.java
================================================
package com.ecommerce.project.security.jwt;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Component
public class AuthEntryPointJwt implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class);
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
final Map body = new HashMap<>();
body.put("status", HttpServletResponse.SC_UNAUTHORIZED);
body.put("error", "Unauthorized");
body.put("message", authException.getMessage());
body.put("path", request.getServletPath());
final ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getOutputStream(), body);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/security/jwt/AuthTokenFilter.java
================================================
package com.ecommerce.project.security.jwt;
import com.ecommerce.project.security.services.UserDetailsServiceImpl;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
@Component
public class AuthTokenFilter extends OncePerRequestFilter {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private UserDetailsServiceImpl userDetailsService;
private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
logger.debug("AuthTokenFilter called for URI: {}", request.getRequestURI());
try {
String jwt = parseJwt(request);
if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
String username = jwtUtils.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails,
null,
userDetails.getAuthorities());
logger.debug("Roles from JWT: {}", userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
logger.error("Cannot set user authentication: {}", e);
}
filterChain.doFilter(request, response);
}
// private String parseJwt(HttpServletRequest request) {
// String jwt = jwtUtils.getJwtFromCookies(request);
// logger.debug("AuthTokenFilter.java: {}", jwt);
// return jwt;
// }
private String parseJwt(HttpServletRequest request) {
String jwtFromCookie = jwtUtils.getJwtFromCookies(request);
if (jwtFromCookie != null) {
return jwtFromCookie;
}
String jwtFromHeader = jwtUtils.getJwtFromHeader(request);
if (jwtFromHeader != null) {
return jwtFromHeader;
}
return null;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/security/jwt/JwtUtils.java
================================================
package com.ecommerce.project.security.jwt;
import com.ecommerce.project.security.services.UserDetailsImpl;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseCookie;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.util.WebUtils;
import javax.crypto.SecretKey;
import java.security.Key;
import java.util.Date;
@Component
public class JwtUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
@Value("${spring.app.jwtSecret}")
private String jwtSecret;
@Value("${spring.app.jwtExpirationMs}")
private int jwtExpirationMs;
@Value("${spring.ecom.app.jwtCookieName}")
private String jwtCookie;
public String getJwtFromCookies(HttpServletRequest request) {
Cookie cookie = WebUtils.getCookie(request, jwtCookie);
if (cookie != null) {
return cookie.getValue();
} else {
return null;
}
}
public String getJwtFromHeader(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
public ResponseCookie generateJwtCookie(UserDetailsImpl userPrincipal) {
String jwt = generateTokenFromUsername(userPrincipal.getUsername());
ResponseCookie cookie = ResponseCookie.from(jwtCookie, jwt)
.path("/api")
.maxAge(24 * 60 * 60)
.httpOnly(false)
.secure(false)
.build();
return cookie;
}
public ResponseCookie getCleanJwtCookie() {
ResponseCookie cookie = ResponseCookie.from(jwtCookie, null)
.path("/api")
.build();
return cookie;
}
public String generateTokenFromUsername(String username) {
return Jwts.builder()
.subject(username)
.issuedAt(new Date())
.expiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(key())
.compact();
}
public String getUserNameFromJwtToken(String token) {
return Jwts.parser()
.verifyWith((SecretKey) key())
.build().parseSignedClaims(token)
.getPayload().getSubject();
}
private Key key() {
return Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtSecret));
}
public boolean validateJwtToken(String authToken) {
try {
Jwts.parser().verifyWith((SecretKey) key()).build().parseSignedClaims(authToken);
return true;
} catch (MalformedJwtException e) {
logger.error("Invalid JWT token: {}", e.getMessage());
} catch (ExpiredJwtException e) {
logger.error("JWT token is expired: {}", e.getMessage());
} catch (UnsupportedJwtException e) {
logger.error("JWT token is unsupported: {}", e.getMessage());
} catch (IllegalArgumentException e) {
logger.error("JWT claims string is empty: {}", e.getMessage());
}
return false;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/security/request/LoginRequest.java
================================================
package com.ecommerce.project.security.request;
import jakarta.validation.constraints.NotBlank;
public class LoginRequest {
@NotBlank
private String username;
@NotBlank
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/security/request/SignupRequest.java
================================================
package com.ecommerce.project.security.request;
import java.util.Set;
import jakarta.validation.constraints.*;
import lombok.Data;
@Data
public class SignupRequest {
@NotBlank
@Size(min = 3, max = 20)
private String username;
@NotBlank
@Size(max = 50)
@Email
private String email;
private Set role;
@NotBlank
@Size(min = 6, max = 40)
private String password;
public Set getRole() {
return this.role;
}
public void setRole(Set role) {
this.role = role;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/security/response/MessageResponse.java
================================================
package com.ecommerce.project.security.response;
public class MessageResponse {
private String message;
public MessageResponse(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/security/response/UserInfoResponse.java
================================================
package com.ecommerce.project.security.response;
import java.util.List;
public class UserInfoResponse {
private Long id;
private String jwtToken;
private String username;
private String email;
private List roles;
public UserInfoResponse(Long id, String username, List roles, String email, String jwtToken) {
this.id = id;
this.username = username;
this.roles = roles;
this.email = email;
this.jwtToken = jwtToken;
}
public UserInfoResponse(Long id, String username, List roles) {
this.id = id;
this.username = username;
this.roles = roles;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getJwtToken() {
return jwtToken;
}
public void setJwtToken(String jwtToken) {
this.jwtToken = jwtToken;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public List getRoles() {
return roles;
}
public void setRoles(List roles) {
this.roles = roles;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/security/services/UserDetailsImpl.java
================================================
package com.ecommerce.project.security.services;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.ecommerce.project.model.User;
import com.fasterxml.jackson.annotation.JsonIgnore;
@NoArgsConstructor
@Data
public class UserDetailsImpl implements UserDetails {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String email;
@JsonIgnore
private String password;
private Collection extends GrantedAuthority> authorities;
public UserDetailsImpl(Long id, String username, String email, String password,
Collection extends GrantedAuthority> authorities) {
this.id = id;
this.username = username;
this.email = email;
this.password = password;
this.authorities = authorities;
}
public static UserDetailsImpl build(User user) {
List authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getRoleName().name()))
.collect(Collectors.toList());
return new UserDetailsImpl(
user.getUserId(),
user.getUserName(),
user.getEmail(),
user.getPassword(),
authorities);
}
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return authorities;
}
public Long getId() {
return id;
}
public String getEmail() {
return email;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
UserDetailsImpl user = (UserDetailsImpl) o;
return Objects.equals(id, user.id);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/security/services/UserDetailsServiceImpl.java
================================================
package com.ecommerce.project.security.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ecommerce.project.model.User;
import com.ecommerce.project.repositories.UserRepository;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
UserRepository userRepository;
@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUserName(username)
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
return UserDetailsImpl.build(user);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/AddressService.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.model.User;
import com.ecommerce.project.payload.AddressDTO;
import java.util.List;
public interface AddressService {
AddressDTO createAddress(AddressDTO addressDTO, User user);
List getAddresses();
AddressDTO getAddressesById(Long addressId);
List getUserAddresses(User user);
AddressDTO updateAddress(Long addressId, AddressDTO addressDTO);
String deleteAddress(Long addressId);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/AddressServiceImpl.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.exceptions.ResourceNotFoundException;
import com.ecommerce.project.model.Address;
import com.ecommerce.project.model.User;
import com.ecommerce.project.payload.AddressDTO;
import com.ecommerce.project.repositories.AddressRepository;
import com.ecommerce.project.repositories.UserRepository;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class AddressServiceImpl implements AddressService{
@Autowired
private AddressRepository addressRepository;
@Autowired
private ModelMapper modelMapper;
@Autowired
UserRepository userRepository;
@Override
public AddressDTO createAddress(AddressDTO addressDTO, User user) {
Address address = modelMapper.map(addressDTO, Address.class);
address.setUser(user);
List addressesList = user.getAddresses();
addressesList.add(address);
user.setAddresses(addressesList);
Address savedAddress = addressRepository.save(address);
return modelMapper.map(savedAddress, AddressDTO.class);
}
@Override
public List getAddresses() {
List addresses = addressRepository.findAll();
return addresses.stream()
.map(address -> modelMapper.map(address, AddressDTO.class))
.toList();
}
@Override
public AddressDTO getAddressesById(Long addressId) {
Address address = addressRepository.findById(addressId)
.orElseThrow(() -> new ResourceNotFoundException("Address", "addressId", addressId));
return modelMapper.map(address, AddressDTO.class);
}
@Override
public List getUserAddresses(User user) {
List addresses = user.getAddresses();
return addresses.stream()
.map(address -> modelMapper.map(address, AddressDTO.class))
.toList();
}
@Override
public AddressDTO updateAddress(Long addressId, AddressDTO addressDTO) {
Address addressFromDatabase = addressRepository.findById(addressId)
.orElseThrow(() -> new ResourceNotFoundException("Address", "addressId", addressId));
addressFromDatabase.setCity(addressDTO.getCity());
addressFromDatabase.setPincode(addressDTO.getPincode());
addressFromDatabase.setState(addressDTO.getState());
addressFromDatabase.setCountry(addressDTO.getCountry());
addressFromDatabase.setStreet(addressDTO.getStreet());
addressFromDatabase.setBuildingName(addressDTO.getBuildingName());
Address updatedAddress = addressRepository.save(addressFromDatabase);
User user = addressFromDatabase.getUser();
user.getAddresses().removeIf(address -> address.getAddressId().equals(addressId));
user.getAddresses().add(updatedAddress);
userRepository.save(user);
return modelMapper.map(updatedAddress, AddressDTO.class);
}
@Override
public String deleteAddress(Long addressId) {
Address addressFromDatabase = addressRepository.findById(addressId)
.orElseThrow(() -> new ResourceNotFoundException("Address", "addressId", addressId));
User user = addressFromDatabase.getUser();
user.getAddresses().removeIf(address -> address.getAddressId().equals(addressId));
userRepository.save(user);
addressRepository.delete(addressFromDatabase);
return "Address deleted successfully with addressId: " + addressId;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/AnalyticsService.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.payload.AnalyticsResponse;
public interface AnalyticsService {
AnalyticsResponse getAnalyticsData();
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/AnalyticsServiceImpl.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.payload.AnalyticsResponse;
import com.ecommerce.project.repositories.OrderRepository;
import com.ecommerce.project.repositories.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AnalyticsServiceImpl implements AnalyticsService{
@Autowired
private ProductRepository productRepository;
@Autowired
private OrderRepository orderRepository;
@Override
public AnalyticsResponse getAnalyticsData() {
AnalyticsResponse response = new AnalyticsResponse();
long productCount = productRepository.count();
long totalOrders = orderRepository.count();;
Double totalRevenue = orderRepository.getTotalRevenue();
response.setProductCount(String.valueOf(productCount));
response.setTotalOrders(String.valueOf(totalOrders));
response.setTotalRevenue(String.valueOf(totalRevenue != null ? totalRevenue : 0));
return response;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/AuthService.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.payload.AuthenticationResult;
import com.ecommerce.project.payload.UserResponse;
import com.ecommerce.project.security.request.LoginRequest;
import com.ecommerce.project.security.request.SignupRequest;
import com.ecommerce.project.security.response.MessageResponse;
import com.ecommerce.project.security.response.UserInfoResponse;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseCookie;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
public interface AuthService {
AuthenticationResult login(LoginRequest loginRequest);
ResponseEntity register(SignupRequest signUpRequest);
UserInfoResponse getCurrentUserDetails(Authentication authentication);
ResponseCookie logoutUser();
UserResponse getAllSellers(Pageable pageable);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/AuthServiceImpl.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.model.AppRole;
import com.ecommerce.project.model.Role;
import com.ecommerce.project.model.User;
import com.ecommerce.project.payload.AuthenticationResult;
import com.ecommerce.project.payload.UserDTO;
import com.ecommerce.project.payload.UserResponse;
import com.ecommerce.project.repositories.RoleRepository;
import com.ecommerce.project.repositories.UserRepository;
import com.ecommerce.project.security.jwt.JwtUtils;
import com.ecommerce.project.security.request.LoginRequest;
import com.ecommerce.project.security.request.SignupRequest;
import com.ecommerce.project.security.response.MessageResponse;
import com.ecommerce.project.security.response.UserInfoResponse;
import com.ecommerce.project.security.services.UserDetailsImpl;
import jakarta.transaction.Transactional;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseCookie;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@Transactional
public class AuthServiceImpl implements AuthService {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtils jwtUtils;
@Autowired
UserRepository userRepository;
@Autowired
RoleRepository roleRepository;
@Autowired
PasswordEncoder encoder;
@Autowired
ModelMapper modelMapper;
@Override
public AuthenticationResult login(LoginRequest loginRequest) {
Authentication authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
ResponseCookie jwtCookie = jwtUtils.generateJwtCookie(userDetails);
List roles = userDetails.getAuthorities().stream()
.map(item -> item.getAuthority())
.collect(Collectors.toList());
UserInfoResponse response = new UserInfoResponse(userDetails.getId(),
userDetails.getUsername(), roles, userDetails.getEmail(), jwtCookie.toString());
return new AuthenticationResult(response, jwtCookie);
}
@Override
public ResponseEntity register(SignupRequest signUpRequest) {
if (userRepository.existsByUserName(signUpRequest.getUsername())) {
return ResponseEntity.badRequest().body(new MessageResponse("Error: Username is already taken!"));
}
if (userRepository.existsByEmail(signUpRequest.getEmail())) {
return ResponseEntity.badRequest().body(new MessageResponse("Error: Email is already in use!"));
}
// Create new user's account
User user = new User(signUpRequest.getUsername(),
signUpRequest.getEmail(),
encoder.encode(signUpRequest.getPassword()));
Set strRoles = signUpRequest.getRole();
Set roles = new HashSet<>();
if (strRoles == null) {
Role userRole = roleRepository.findByRoleName(AppRole.ROLE_USER)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(userRole);
} else {
strRoles.forEach(role -> {
switch (role) {
case "admin":
Role adminRole = roleRepository.findByRoleName(AppRole.ROLE_ADMIN)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(adminRole);
break;
case "seller":
Role modRole = roleRepository.findByRoleName(AppRole.ROLE_SELLER)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(modRole);
break;
default:
Role userRole = roleRepository.findByRoleName(AppRole.ROLE_USER)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(userRole);
}
});
}
user.setRoles(roles);
userRepository.save(user);
return ResponseEntity.ok(new MessageResponse("User registered successfully!"));
}
@Override
public UserInfoResponse getCurrentUserDetails(Authentication authentication) {
UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
List roles = userDetails.getAuthorities().stream()
.map(item -> item.getAuthority())
.collect(Collectors.toList());
UserInfoResponse response = new UserInfoResponse(userDetails.getId(),
userDetails.getUsername(), roles);
return response;
}
@Override
public ResponseCookie logoutUser() {
return jwtUtils.getCleanJwtCookie();
}
@Override
public UserResponse getAllSellers(Pageable pageable) {
Page allUsers = userRepository.findByRoleName(AppRole.ROLE_SELLER, pageable);
List userDtos = allUsers.getContent()
.stream()
.map(p -> modelMapper.map(p, UserDTO.class))
.collect(Collectors.toList());
UserResponse response = new UserResponse();
response.setContent(userDtos);
response.setPageNumber(allUsers.getNumber());
response.setPageSize(allUsers.getSize());
response.setTotalElements(allUsers.getTotalElements());
response.setTotalPages(allUsers.getTotalPages());
response.setLastPage(allUsers.isLast());
return response;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/CartService.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.payload.CartDTO;
import com.ecommerce.project.payload.CartItemDTO;
import jakarta.transaction.Transactional;
import java.util.List;
public interface CartService {
CartDTO addProductToCart(Long productId, Integer quantity);
List getAllCarts();
CartDTO getCart(String emailId, Long cartId);
@Transactional
CartDTO updateProductQuantityInCart(Long productId, Integer quantity);
String deleteProductFromCart(Long cartId, Long productId);
void updateProductInCarts(Long cartId, Long productId);
String createOrUpdateCartWithItems(List cartItems);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/CartServiceImpl.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.exceptions.APIException;
import com.ecommerce.project.exceptions.ResourceNotFoundException;
import com.ecommerce.project.model.Cart;
import com.ecommerce.project.model.CartItem;
import com.ecommerce.project.model.Product;
import com.ecommerce.project.payload.CartDTO;
import com.ecommerce.project.payload.CartItemDTO;
import com.ecommerce.project.payload.ProductDTO;
import com.ecommerce.project.repositories.CartItemRepository;
import com.ecommerce.project.repositories.CartRepository;
import com.ecommerce.project.repositories.ProductRepository;
import com.ecommerce.project.util.AuthUtil;
import jakarta.transaction.Transactional;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
public class CartServiceImpl implements CartService{
@Autowired
private CartRepository cartRepository;
@Autowired
private AuthUtil authUtil;
@Autowired
ProductRepository productRepository;
@Autowired
CartItemRepository cartItemRepository;
@Autowired
ModelMapper modelMapper;
@Override
public CartDTO addProductToCart(Long productId, Integer quantity) {
Cart cart = createCart();
Product product = productRepository.findById(productId)
.orElseThrow(() -> new ResourceNotFoundException("Product", "productId", productId));
CartItem cartItem = cartItemRepository.findCartItemByProductIdAndCartId(cart.getCartId(), productId);
if (cartItem != null) {
throw new APIException("Product " + product.getProductName() + " already exists in the cart");
}
if (product.getQuantity() == 0) {
throw new APIException(product.getProductName() + " is not available");
}
if (product.getQuantity() < quantity) {
throw new APIException("Please, make an order of the " + product.getProductName()
+ " less than or equal to the quantity " + product.getQuantity() + ".");
}
CartItem newCartItem = new CartItem();
newCartItem.setProduct(product);
newCartItem.setCart(cart);
newCartItem.setQuantity(quantity);
newCartItem.setDiscount(product.getDiscount());
newCartItem.setProductPrice(product.getSpecialPrice());
cartItemRepository.save(newCartItem);
product.setQuantity(product.getQuantity());
cart.setTotalPrice(cart.getTotalPrice() + (product.getSpecialPrice() * quantity));
cartRepository.save(cart);
CartDTO cartDTO = modelMapper.map(cart, CartDTO.class);
List cartItems = cart.getCartItems();
Stream productStream = cartItems.stream().map(item -> {
ProductDTO map = modelMapper.map(item.getProduct(), ProductDTO.class);
map.setQuantity(item.getQuantity());
return map;
});
cartDTO.setProducts(productStream.toList());
return cartDTO;
}
@Override
public List getAllCarts() {
List carts = cartRepository.findAll();
if (carts.size() == 0) {
throw new APIException("No cart exists");
}
List cartDTOs = carts.stream().map(cart -> {
CartDTO cartDTO = modelMapper.map(cart, CartDTO.class);
List products = cart.getCartItems().stream().map(cartItem -> {
ProductDTO productDTO = modelMapper.map(cartItem.getProduct(), ProductDTO.class);
productDTO.setQuantity(cartItem.getQuantity()); // Set the quantity from CartItem
return productDTO;
}).collect(Collectors.toList());
cartDTO.setProducts(products);
return cartDTO;
}).collect(Collectors.toList());
return cartDTOs;
}
@Override
public CartDTO getCart(String emailId, Long cartId) {
Cart cart = cartRepository.findCartByEmailAndCartId(emailId, cartId);
if (cart == null){
throw new ResourceNotFoundException("Cart", "cartId", cartId);
}
CartDTO cartDTO = modelMapper.map(cart, CartDTO.class);
cart.getCartItems().forEach(c ->
c.getProduct().setQuantity(c.getQuantity()));
List products = cart.getCartItems().stream()
.map(p -> modelMapper.map(p.getProduct(), ProductDTO.class))
.toList();
cartDTO.setProducts(products);
return cartDTO;
}
@Transactional
@Override
public CartDTO updateProductQuantityInCart(Long productId, Integer quantity) {
String emailId = authUtil.loggedInEmail();
Cart userCart = cartRepository.findCartByEmail(emailId);
Long cartId = userCart.getCartId();
Cart cart = cartRepository.findById(cartId)
.orElseThrow(() -> new ResourceNotFoundException("Cart", "cartId", cartId));
Product product = productRepository.findById(productId)
.orElseThrow(() -> new ResourceNotFoundException("Product", "productId", productId));
if (product.getQuantity() == 0) {
throw new APIException(product.getProductName() + " is not available");
}
if (product.getQuantity() < quantity) {
throw new APIException("Please, make an order of the " + product.getProductName()
+ " less than or equal to the quantity " + product.getQuantity() + ".");
}
CartItem cartItem = cartItemRepository.findCartItemByProductIdAndCartId(cartId, productId);
if (cartItem == null) {
throw new APIException("Product " + product.getProductName() + " not available in the cart!!!");
}
// Calculate new quantity
int newQuantity = cartItem.getQuantity() + quantity;
// Validation to prevent negative quantities
if (newQuantity < 0) {
throw new APIException("The resulting quantity cannot be negative.");
}
if (newQuantity == 0){
deleteProductFromCart(cartId, productId);
} else {
cartItem.setProductPrice(product.getSpecialPrice());
cartItem.setQuantity(cartItem.getQuantity() + quantity);
cartItem.setDiscount(product.getDiscount());
cart.setTotalPrice(cart.getTotalPrice() + (cartItem.getProductPrice() * quantity));
cartRepository.save(cart);
}
CartItem updatedItem = cartItemRepository.save(cartItem);
if(updatedItem.getQuantity() == 0){
cartItemRepository.deleteById(updatedItem.getCartItemId());
}
CartDTO cartDTO = modelMapper.map(cart, CartDTO.class);
List cartItems = cart.getCartItems();
Stream productStream = cartItems.stream().map(item -> {
ProductDTO prd = modelMapper.map(item.getProduct(), ProductDTO.class);
prd.setQuantity(item.getQuantity());
return prd;
});
cartDTO.setProducts(productStream.toList());
return cartDTO;
}
private Cart createCart() {
Cart userCart = cartRepository.findCartByEmail(authUtil.loggedInEmail());
if(userCart != null){
return userCart;
}
Cart cart = new Cart();
cart.setTotalPrice(0.00);
cart.setUser(authUtil.loggedInUser());
Cart newCart = cartRepository.save(cart);
return newCart;
}
@Transactional
@Override
public String deleteProductFromCart(Long cartId, Long productId) {
Cart cart = cartRepository.findById(cartId)
.orElseThrow(() -> new ResourceNotFoundException("Cart", "cartId", cartId));
CartItem cartItem = cartItemRepository.findCartItemByProductIdAndCartId(cartId, productId);
if (cartItem == null) {
throw new ResourceNotFoundException("Product", "productId", productId);
}
cart.setTotalPrice(cart.getTotalPrice() -
(cartItem.getProductPrice() * cartItem.getQuantity()));
cartItemRepository.deleteCartItemByProductIdAndCartId(cartId, productId);
return "Product " + cartItem.getProduct().getProductName() + " removed from the cart !!!";
}
@Override
public void updateProductInCarts(Long cartId, Long productId) {
Cart cart = cartRepository.findById(cartId)
.orElseThrow(() -> new ResourceNotFoundException("Cart", "cartId", cartId));
Product product = productRepository.findById(productId)
.orElseThrow(() -> new ResourceNotFoundException("Product", "productId", productId));
CartItem cartItem = cartItemRepository.findCartItemByProductIdAndCartId(cartId, productId);
if (cartItem == null) {
throw new APIException("Product " + product.getProductName() + " not available in the cart!!!");
}
double cartPrice = cart.getTotalPrice()
- (cartItem.getProductPrice() * cartItem.getQuantity());
cartItem.setProductPrice(product.getSpecialPrice());
cart.setTotalPrice(cartPrice
+ (cartItem.getProductPrice() * cartItem.getQuantity()));
cartItem = cartItemRepository.save(cartItem);
}
@Transactional
@Override
public String createOrUpdateCartWithItems(List cartItems) {
// Get user's email
String emailId = authUtil.loggedInEmail();
// Check if an existing cart is available or create a new one
Cart existingCart = cartRepository.findCartByEmail(emailId);
if (existingCart == null) {
existingCart = new Cart();
existingCart.setTotalPrice(0.00);
existingCart.setUser(authUtil.loggedInUser());
existingCart = cartRepository.save(existingCart);
} else {
// Clear all current items in the existing cart
cartItemRepository.deleteAllByCartId(existingCart.getCartId());
}
double totalPrice = 0.00;
// Process each item in the request to add to the cart
for (CartItemDTO cartItemDTO : cartItems) {
Long productId = cartItemDTO.getProductId();
Integer quantity = cartItemDTO.getQuantity();
// Find the product by ID
Product product = productRepository.findById(productId)
.orElseThrow(() -> new ResourceNotFoundException("Product", "productId", productId));
// Directly update product stock and total price
// product.setQuantity(product.getQuantity() - quantity);
totalPrice += product.getSpecialPrice() * quantity;
// Create and save cart item
CartItem cartItem = new CartItem();
cartItem.setProduct(product);
cartItem.setCart(existingCart);
cartItem.setQuantity(quantity);
cartItem.setProductPrice(product.getSpecialPrice());
cartItem.setDiscount(product.getDiscount());
cartItemRepository.save(cartItem);
}
// Update the cart's total price and save
existingCart.setTotalPrice(totalPrice);
cartRepository.save(existingCart);
return "Cart created/updated with the new items successfully";
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/CategoryService.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.model.Category;
import com.ecommerce.project.payload.CategoryDTO;
import com.ecommerce.project.payload.CategoryResponse;
public interface CategoryService {
CategoryResponse getAllCategories(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder);
CategoryDTO createCategory(CategoryDTO categoryDTO);
CategoryDTO deleteCategory(Long categoryId);
CategoryDTO updateCategory(CategoryDTO categoryDTO, Long categoryId);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/CategoryServiceImpl.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.exceptions.APIException;
import com.ecommerce.project.exceptions.ResourceNotFoundException;
import com.ecommerce.project.model.Category;
import com.ecommerce.project.payload.CategoryDTO;
import com.ecommerce.project.payload.CategoryResponse;
import com.ecommerce.project.repositories.CategoryRepository;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CategoryServiceImpl implements CategoryService{
@Autowired
private CategoryRepository categoryRepository;
@Autowired
private ModelMapper modelMapper;
@Override
public CategoryResponse getAllCategories(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder) {
Sort sortByAndOrder = sortOrder.equalsIgnoreCase("asc")
? Sort.by(sortBy).ascending()
: Sort.by(sortBy).descending();
Pageable pageDetails = PageRequest.of(pageNumber, pageSize, sortByAndOrder);
Page categoryPage = categoryRepository.findAll(pageDetails);
List categories = categoryPage.getContent();
if (categories.isEmpty())
throw new APIException("No category created till now.");
List categoryDTOS = categories.stream()
.map(category -> modelMapper.map(category, CategoryDTO.class))
.toList();
CategoryResponse categoryResponse = new CategoryResponse();
categoryResponse.setContent(categoryDTOS);
categoryResponse.setPageNumber(categoryPage.getNumber());
categoryResponse.setPageSize(categoryPage.getSize());
categoryResponse.setTotalElements(categoryPage.getTotalElements());
categoryResponse.setTotalPages(categoryPage.getTotalPages());
categoryResponse.setLastPage(categoryPage.isLast());
return categoryResponse;
}
@Override
public CategoryDTO createCategory(CategoryDTO categoryDTO) {
Category category = modelMapper.map(categoryDTO, Category.class);
Category categoryFromDb = categoryRepository.findByCategoryName(category.getCategoryName());
if (categoryFromDb != null)
throw new APIException("Category with the name " + category.getCategoryName() + " already exists !!!");
Category savedCategory = categoryRepository.save(category);
return modelMapper.map(savedCategory, CategoryDTO.class);
}
@Override
public CategoryDTO deleteCategory(Long categoryId) {
Category category = categoryRepository.findById(categoryId)
.orElseThrow(() -> new ResourceNotFoundException("Category","categoryId",categoryId));
categoryRepository.delete(category);
return modelMapper.map(category, CategoryDTO.class);
}
@Override
public CategoryDTO updateCategory(CategoryDTO categoryDTO, Long categoryId) {
Category savedCategory = categoryRepository.findById(categoryId)
.orElseThrow(() -> new ResourceNotFoundException("Category","categoryId",categoryId));
Category category = modelMapper.map(categoryDTO, Category.class);
category.setCategoryId(categoryId);
savedCategory = categoryRepository.save(category);
return modelMapper.map(savedCategory, CategoryDTO.class);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/FileService.java
================================================
package com.ecommerce.project.service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
public interface FileService {
String uploadImage(String path, MultipartFile file) throws IOException;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/FileServiceImpl.java
================================================
package com.ecommerce.project.service;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;
@Service
public class FileServiceImpl implements FileService {
@Override
public String uploadImage(String path, MultipartFile file) throws IOException {
String originalFileName = file.getOriginalFilename();
String randomId = UUID.randomUUID().toString();
String fileName = randomId.concat(originalFileName.substring(originalFileName.lastIndexOf('.')));
String filePath = path + File.separator + fileName;
File folder = new File(path);
if (!folder.exists())
folder.mkdir();
Files.copy(file.getInputStream(), Paths.get(filePath));
return fileName;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/OrderService.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.payload.OrderDTO;
import com.ecommerce.project.payload.OrderResponse;
import jakarta.transaction.Transactional;
public interface OrderService {
@Transactional
OrderDTO placeOrder(String emailId, Long addressId, String paymentMethod, String pgName, String pgPaymentId, String pgStatus, String pgResponseMessage);
OrderResponse getAllOrders(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder);
OrderDTO updateOrder(Long orderId, String status);
OrderResponse getAllSellerOrders(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/OrderServiceImpl.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.exceptions.APIException;
import com.ecommerce.project.exceptions.ResourceNotFoundException;
import com.ecommerce.project.model.*;
import com.ecommerce.project.payload.OrderDTO;
import com.ecommerce.project.payload.OrderItemDTO;
import com.ecommerce.project.payload.OrderResponse;
import com.ecommerce.project.repositories.*;
import com.ecommerce.project.util.AuthUtil;
import jakarta.transaction.Transactional;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
CartRepository cartRepository;
@Autowired
AddressRepository addressRepository;
@Autowired
OrderItemRepository orderItemRepository;
@Autowired
OrderRepository orderRepository;
@Autowired
PaymentRepository paymentRepository;
@Autowired
CartService cartService;
@Autowired
ModelMapper modelMapper;
@Autowired
ProductRepository productRepository;
@Autowired
AuthUtil authUtil;
@Override
@Transactional
public OrderDTO placeOrder(String emailId, Long addressId, String paymentMethod, String pgName, String pgPaymentId, String pgStatus, String pgResponseMessage) {
Cart cart = cartRepository.findCartByEmail(emailId);
if (cart == null) {
throw new ResourceNotFoundException("Cart", "email", emailId);
}
Address address = addressRepository.findById(addressId)
.orElseThrow(() -> new ResourceNotFoundException("Address", "addressId", addressId));
Order order = new Order();
order.setEmail(emailId);
order.setOrderDate(LocalDate.now());
order.setTotalAmount(cart.getTotalPrice());
order.setOrderStatus("Accepted");
order.setAddress(address);
Payment payment = new Payment(paymentMethod, pgPaymentId, pgStatus, pgResponseMessage, pgName);
payment.setOrder(order);
payment = paymentRepository.save(payment);
order.setPayment(payment);
Order savedOrder = orderRepository.save(order);
List cartItems = cart.getCartItems();
if (cartItems.isEmpty()) {
throw new APIException("Cart is empty");
}
List orderItems = new ArrayList<>();
for (CartItem cartItem : cartItems) {
OrderItem orderItem = new OrderItem();
orderItem.setProduct(cartItem.getProduct());
orderItem.setQuantity(cartItem.getQuantity());
orderItem.setDiscount(cartItem.getDiscount());
orderItem.setOrderedProductPrice(cartItem.getProductPrice());
orderItem.setOrder(savedOrder);
orderItems.add(orderItem);
}
orderItems = orderItemRepository.saveAll(orderItems);
cart.getCartItems().forEach(item -> {
int quantity = item.getQuantity();
Product product = item.getProduct();
// Reduce stock quantity
product.setQuantity(product.getQuantity() - quantity);
// Save product back to the database
productRepository.save(product);
// Remove items from cart
cartService.deleteProductFromCart(cart.getCartId(), item.getProduct().getProductId());
});
OrderDTO orderDTO = modelMapper.map(savedOrder, OrderDTO.class);
orderItems.forEach(item -> orderDTO.getOrderItems().add(modelMapper.map(item, OrderItemDTO.class)));
orderDTO.setAddressId(addressId);
return orderDTO;
}
@Override
public OrderResponse getAllOrders(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder) {
Sort sortByAndOrder = sortOrder.equalsIgnoreCase("asc")
? Sort.by(sortBy).ascending()
: Sort.by(sortBy).descending();
Pageable pageDetails = PageRequest.of(pageNumber, pageSize, sortByAndOrder);
Page pageOrders = orderRepository.findAll(pageDetails);
List orders = pageOrders.getContent();
List orderDTOs = orders.stream()
.map(order -> modelMapper.map(order, OrderDTO.class))
.toList();
OrderResponse orderResponse = new OrderResponse();
orderResponse.setContent(orderDTOs);
orderResponse.setPageNumber(pageOrders.getNumber());
orderResponse.setPageSize(pageOrders.getSize());
orderResponse.setTotalElements(pageOrders.getTotalElements());
orderResponse.setTotalPages(pageOrders.getTotalPages());
orderResponse.setLastPage(pageOrders.isLast());
return orderResponse;
}
@Override
public OrderDTO updateOrder(Long orderId, String status) {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new ResourceNotFoundException("Order","orderId",orderId));
order.setOrderStatus(status);
orderRepository.save(order);
return modelMapper.map(order, OrderDTO.class);
}
@Override
public OrderResponse getAllSellerOrders(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder) {
Sort sortByAndOrder = sortOrder.equalsIgnoreCase("asc")
? Sort.by(sortBy).ascending()
: Sort.by(sortBy).descending();
Pageable pageDetails = PageRequest.of(pageNumber, pageSize, sortByAndOrder);
User seller = authUtil.loggedInUser();
Page pageOrders = orderRepository.findAll(pageDetails);
List sellerOrders = pageOrders.getContent().stream()
.filter(order -> order.getOrderItems().stream()
.anyMatch(orderItem -> {
var product = orderItem.getProduct();
if (product == null || product.getUser() == null) {
return false;
}
return product.getUser().getUserId().equals(
seller.getUserId());
}))
.toList();
List orderDTOs = sellerOrders.stream()
.map(order -> modelMapper.map(order, OrderDTO.class))
.toList();
OrderResponse orderResponse = new OrderResponse();
orderResponse.setContent(orderDTOs);
orderResponse.setPageNumber(pageOrders.getNumber());
orderResponse.setPageSize(pageOrders.getSize());
orderResponse.setTotalElements(pageOrders.getTotalElements());
orderResponse.setTotalPages(pageOrders.getTotalPages());
orderResponse.setLastPage(pageOrders.isLast());
return orderResponse;
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/ProductService.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.payload.ProductDTO;
import com.ecommerce.project.payload.ProductResponse;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
public interface ProductService {
ProductDTO addProduct(Long categoryId, ProductDTO product);
ProductResponse getAllProducts(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder, String keyword, String category);
ProductResponse searchByCategory(Long categoryId, Integer pageNumber, Integer pageSize, String sortBy, String sortOrder);
ProductResponse searchProductByKeyword(String keyword, Integer pageNumber, Integer pageSize, String sortBy, String sortOrder);
ProductDTO updateProduct(Long productId, ProductDTO product);
ProductDTO deleteProduct(Long productId);
ProductDTO updateProductImage(Long productId, MultipartFile image) throws IOException;
ProductResponse getAllProductsForAdmin(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder);
ProductResponse getAllProductsForSeller(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder);
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/ProductServiceImpl.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.exceptions.APIException;
import com.ecommerce.project.exceptions.ResourceNotFoundException;
import com.ecommerce.project.model.Cart;
import com.ecommerce.project.model.Category;
import com.ecommerce.project.model.Product;
import com.ecommerce.project.model.User;
import com.ecommerce.project.payload.CartDTO;
import com.ecommerce.project.payload.ProductDTO;
import com.ecommerce.project.payload.ProductResponse;
import com.ecommerce.project.repositories.CartRepository;
import com.ecommerce.project.repositories.CategoryRepository;
import com.ecommerce.project.repositories.ProductRepository;
import com.ecommerce.project.util.AuthUtil;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private CartRepository cartRepository;
@Autowired
private CartService cartService;
@Autowired
private ProductRepository productRepository;
@Autowired
private CategoryRepository categoryRepository;
@Autowired
private ModelMapper modelMapper;
@Autowired
private FileService fileService;
@Autowired
AuthUtil authUtil;
@Value("${project.image}")
private String path;
@Value("${image.base.url}")
private String imageBaseUrl;
@Override
public ProductDTO addProduct(Long categoryId, ProductDTO productDTO) {
Category category = categoryRepository.findById(categoryId)
.orElseThrow(() ->
new ResourceNotFoundException("Category", "categoryId", categoryId));
boolean isProductNotPresent = true;
List products = category.getProducts();
for (Product value : products) {
if (value.getProductName().equals(productDTO.getProductName())) {
isProductNotPresent = false;
break;
}
}
if (isProductNotPresent) {
Product product = modelMapper.map(productDTO, Product.class);
product.setImage("default.png");
product.setCategory(category);
product.setUser(authUtil.loggedInUser());
double specialPrice = product.getPrice() -
((product.getDiscount() * 0.01) * product.getPrice());
product.setSpecialPrice(specialPrice);
Product savedProduct = productRepository.save(product);
return modelMapper.map(savedProduct, ProductDTO.class);
} else {
throw new APIException("Product already exist!!");
}
}
@Override
public ProductResponse getAllProducts(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder, String keyword, String category) {
Sort sortByAndOrder = sortOrder.equalsIgnoreCase("asc")
? Sort.by(sortBy).ascending()
: Sort.by(sortBy).descending();
Pageable pageDetails = PageRequest.of(pageNumber, pageSize, sortByAndOrder);
Specification spec = (root, query, cb) -> cb.conjunction();
if (keyword != null && !keyword.isEmpty()) {
spec = spec.and((root, query, criteriaBuilder) ->
criteriaBuilder.like(criteriaBuilder.lower(root.get("productName")), "%" + keyword.toLowerCase() + "%"));
}
if (category != null && !category.isEmpty()) {
spec = spec.and((root, query, criteriaBuilder) ->
criteriaBuilder.like(root.get("category").get("categoryName"), category));
}
Page pageProducts = productRepository.findAll(spec, pageDetails);
List products = pageProducts.getContent();
List productDTOS = products.stream()
.map(product -> {
ProductDTO productDTO = modelMapper.map(product, ProductDTO.class);
productDTO.setImage(constructImageUrl(product.getImage()));
return productDTO;
})
.toList();
ProductResponse productResponse = new ProductResponse();
productResponse.setContent(productDTOS);
productResponse.setPageNumber(pageProducts.getNumber());
productResponse.setPageSize(pageProducts.getSize());
productResponse.setTotalElements(pageProducts.getTotalElements());
productResponse.setTotalPages(pageProducts.getTotalPages());
productResponse.setLastPage(pageProducts.isLast());
return productResponse;
}
@Override
public ProductResponse getAllProductsForAdmin(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder) {
Sort sortByAndOrder = sortOrder.equalsIgnoreCase("asc")
? Sort.by(sortBy).ascending()
: Sort.by(sortBy).descending();
Pageable pageDetails = PageRequest.of(pageNumber, pageSize, sortByAndOrder);
Page pageProducts = productRepository.findAll(pageDetails);
List products = pageProducts.getContent();
List productDTOS = products.stream()
.map(product -> {
ProductDTO productDTO = modelMapper.map(product, ProductDTO.class);
productDTO.setImage(constructImageUrl(product.getImage()));
return productDTO;
})
.toList();
ProductResponse productResponse = new ProductResponse();
productResponse.setContent(productDTOS);
productResponse.setPageNumber(pageProducts.getNumber());
productResponse.setPageSize(pageProducts.getSize());
productResponse.setTotalElements(pageProducts.getTotalElements());
productResponse.setTotalPages(pageProducts.getTotalPages());
productResponse.setLastPage(pageProducts.isLast());
return productResponse;
}
@Override
public ProductResponse getAllProductsForSeller(Integer pageNumber, Integer pageSize, String sortBy, String sortOrder) {
Sort sortByAndOrder = sortOrder.equalsIgnoreCase("asc")
? Sort.by(sortBy).ascending()
: Sort.by(sortBy).descending();
Pageable pageDetails = PageRequest.of(pageNumber, pageSize, sortByAndOrder);
User user = authUtil.loggedInUser();
Page pageProducts = productRepository.findByUser(user, pageDetails);
List products = pageProducts.getContent();
List productDTOS = products.stream()
.map(product -> {
ProductDTO productDTO = modelMapper.map(product, ProductDTO.class);
productDTO.setImage(constructImageUrl(product.getImage()));
return productDTO;
})
.toList();
ProductResponse productResponse = new ProductResponse();
productResponse.setContent(productDTOS);
productResponse.setPageNumber(pageProducts.getNumber());
productResponse.setPageSize(pageProducts.getSize());
productResponse.setTotalElements(pageProducts.getTotalElements());
productResponse.setTotalPages(pageProducts.getTotalPages());
productResponse.setLastPage(pageProducts.isLast());
return productResponse;
}
private String constructImageUrl(String imageName) {
return imageBaseUrl.endsWith("/") ? imageBaseUrl + imageName : imageBaseUrl + "/" + imageName;
}
@Override
public ProductResponse searchByCategory(Long categoryId, Integer pageNumber, Integer pageSize, String sortBy, String sortOrder) {
Category category = categoryRepository.findById(categoryId)
.orElseThrow(() ->
new ResourceNotFoundException("Category", "categoryId", categoryId));
Sort sortByAndOrder = sortOrder.equalsIgnoreCase("asc")
? Sort.by(sortBy).ascending()
: Sort.by(sortBy).descending();
Pageable pageDetails = PageRequest.of(pageNumber, pageSize, sortByAndOrder);
Page pageProducts = productRepository.findByCategoryOrderByPriceAsc(category, pageDetails);
List products = pageProducts.getContent();
if(products.isEmpty()){
throw new APIException(category.getCategoryName() + " category does not have any products");
}
List productDTOS = products.stream()
.map(product -> modelMapper.map(product, ProductDTO.class))
.toList();
ProductResponse productResponse = new ProductResponse();
productResponse.setContent(productDTOS);
productResponse.setPageNumber(pageProducts.getNumber());
productResponse.setPageSize(pageProducts.getSize());
productResponse.setTotalElements(pageProducts.getTotalElements());
productResponse.setTotalPages(pageProducts.getTotalPages());
productResponse.setLastPage(pageProducts.isLast());
return productResponse;
}
@Override
public ProductResponse searchProductByKeyword(String keyword, Integer pageNumber, Integer pageSize, String sortBy, String sortOrder) {
Sort sortByAndOrder = sortOrder.equalsIgnoreCase("asc")
? Sort.by(sortBy).ascending()
: Sort.by(sortBy).descending();
Pageable pageDetails = PageRequest.of(pageNumber, pageSize, sortByAndOrder);
Page pageProducts = productRepository.findByProductNameLikeIgnoreCase('%' + keyword + '%', pageDetails);
List products = pageProducts.getContent();
List productDTOS = products.stream()
.map(product -> modelMapper.map(product, ProductDTO.class))
.toList();
if(products.isEmpty()){
throw new APIException("Products not found with keyword: " + keyword);
}
ProductResponse productResponse = new ProductResponse();
productResponse.setContent(productDTOS);
productResponse.setPageNumber(pageProducts.getNumber());
productResponse.setPageSize(pageProducts.getSize());
productResponse.setTotalElements(pageProducts.getTotalElements());
productResponse.setTotalPages(pageProducts.getTotalPages());
productResponse.setLastPage(pageProducts.isLast());
return productResponse;
}
@Override
public ProductDTO updateProduct(Long productId, ProductDTO productDTO) {
Product productFromDb = productRepository.findById(productId)
.orElseThrow(() -> new ResourceNotFoundException("Product", "productId", productId));
Product product = modelMapper.map(productDTO, Product.class);
productFromDb.setProductName(product.getProductName());
productFromDb.setDescription(product.getDescription());
productFromDb.setQuantity(product.getQuantity());
productFromDb.setDiscount(product.getDiscount());
productFromDb.setPrice(product.getPrice());
productFromDb.setSpecialPrice(product.getSpecialPrice());
Product savedProduct = productRepository.save(productFromDb);
List carts = cartRepository.findCartsByProductId(productId);
List cartDTOs = carts.stream().map(cart -> {
CartDTO cartDTO = modelMapper.map(cart, CartDTO.class);
List products = cart.getCartItems().stream()
.map(p -> modelMapper.map(p.getProduct(), ProductDTO.class)).collect(Collectors.toList());
cartDTO.setProducts(products);
return cartDTO;
}).collect(Collectors.toList());
cartDTOs.forEach(cart -> cartService.updateProductInCarts(cart.getCartId(), productId));
return modelMapper.map(savedProduct, ProductDTO.class);
}
@Override
public ProductDTO deleteProduct(Long productId) {
Product product = productRepository.findById(productId)
.orElseThrow(() -> new ResourceNotFoundException("Product", "productId", productId));
// DELETE
List carts = cartRepository.findCartsByProductId(productId);
carts.forEach(cart -> cartService.deleteProductFromCart(cart.getCartId(), productId));
productRepository.delete(product);
return modelMapper.map(product, ProductDTO.class);
}
@Override
public ProductDTO updateProductImage(Long productId, MultipartFile image) throws IOException {
Product productFromDb = productRepository.findById(productId)
.orElseThrow(() -> new ResourceNotFoundException("Product", "productId", productId));
String fileName = fileService.uploadImage(path, image);
productFromDb.setImage(fileName);
Product updatedProduct = productRepository.save(productFromDb);
return modelMapper.map(updatedProduct, ProductDTO.class);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/StripeService.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.payload.StripePaymentDto;
import com.stripe.exception.StripeException;
import com.stripe.model.PaymentIntent;
public interface StripeService {
PaymentIntent paymentIntent(StripePaymentDto stripePaymentDto) throws StripeException;
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/service/StripeServiceImpl.java
================================================
package com.ecommerce.project.service;
import com.ecommerce.project.payload.StripePaymentDto;
import com.stripe.Stripe;
import com.stripe.exception.StripeException;
import com.stripe.model.Customer;
import com.stripe.model.CustomerSearchResult;
import com.stripe.model.PaymentIntent;
import com.stripe.param.CustomerCreateParams;
import com.stripe.param.CustomerSearchParams;
import com.stripe.param.PaymentIntentCreateParams;
import jakarta.annotation.PostConstruct;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
@Transactional
public class StripeServiceImpl implements StripeService {
@Value("${stripe.secret.key}")
private String stripeApiKey;
@PostConstruct
public void init(){
Stripe.apiKey = stripeApiKey;
}
@Override
public PaymentIntent paymentIntent(StripePaymentDto stripePaymentDto) throws StripeException {
Customer customer;
// Retrieve and check if customer exist
CustomerSearchParams searchParams =
CustomerSearchParams.builder()
.setQuery("email:'" + stripePaymentDto.getEmail() + "'")
.build();
CustomerSearchResult customers = Customer.search(searchParams);
if (customers.getData().isEmpty()) {
// Create new customer
CustomerCreateParams customerParams = CustomerCreateParams.builder()
.setEmail(stripePaymentDto.getEmail())
.setName(stripePaymentDto.getName())
.setAddress(
CustomerCreateParams.Address.builder()
.setLine1(stripePaymentDto.getAddress().getStreet())
.setCity(stripePaymentDto.getAddress().getCity())
.setState(stripePaymentDto.getAddress().getState())
.setPostalCode(stripePaymentDto.getAddress().getPincode())
.setCountry(stripePaymentDto.getAddress().getCountry())
.build()
)
.build();
customer = Customer.create(customerParams);
} else {
// Fetch the customer that exist
customer = customers.getData().get(0);
}
PaymentIntentCreateParams params =
PaymentIntentCreateParams.builder()
.setAmount(stripePaymentDto.getAmount())
.setCurrency(stripePaymentDto.getCurrency())
.setCustomer(customer.getId())
.setDescription(stripePaymentDto.getDescription())
.setAutomaticPaymentMethods(
PaymentIntentCreateParams.AutomaticPaymentMethods.builder()
.setEnabled(true)
.build()
)
.build();
return PaymentIntent.create(params);
}
}
================================================
FILE: sb-ecom/src/main/java/com/ecommerce/project/util/AuthUtil.java
================================================
package com.ecommerce.project.util;
import com.ecommerce.project.model.User;
import com.ecommerce.project.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
@Component
public class AuthUtil {
@Autowired
UserRepository userRepository;
public String loggedInEmail(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
User user = userRepository.findByUserName(authentication.getName())
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + authentication.getName()));
return user.getEmail();
}
public Long loggedInUserId(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
User user = userRepository.findByUserName(authentication.getName())
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + authentication.getName()));
return user.getUserId();
}
public User loggedInUser(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
User user = userRepository.findByUserName(authentication.getName())
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + authentication.getName()));
return user;
}
}
================================================
FILE: sb-ecom/src/main/resources/application.properties
================================================
spring.application.name=sb-ecom
spring.datasource.url=jdbc:postgresql://localhost:5432/ecommerce
spring.datasource.username=postgres
spring.datasource.password=admin@123
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
#spring.h2.console.enabled=true
#spring.datasource.url=jdbc:h2:mem:test
project.image=images/
#spring.jpa.show-sql=true
#spring.jpa.properties.hibernate.format_sql=true
spring.app.jwtSecret=mySecretKey123912738aopsgjnspkmndfsopkvajoirjg94gf2opfng2moknm
spring.app.jwtExpirationMs=300000000
spring.ecom.app.jwtCookieName=springBootEcom
#logging.level.org.springframework=DEBUG
#logging.level.org.hibernate.SQL=DEBUG
#logging.level.org.springframework.security=DEBUG
#logging.level.com.ecommerce.project=DEBUG
# Needed if you are using elastic beanstalk
#server.port=5000
frontend.url=http://localhost:5173/
image.base.url=http://localhost:8080/images
#STRIPE KEY
stripe.secret.key=${STRIPE_SECRET_KEY}
================================================
FILE: sb-ecom/src/test/java/com/ecommerce/project/SbEcomApplicationTests.java
================================================
package com.ecommerce.project;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SbEcomApplicationTests {
@Test
void contextLoads() {
}
}