diff --git a/package-lock.json b/package-lock.json index 84689ae1..e837c0f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@mui/material": "^5.16.4", "@reduxjs/toolkit": "^2.2.5", "antd": "^5.19.2", + "aos": "^2.3.4", "axios": "^1.7.2", "cors": "^2.8.5", "dotenv": "^16.4.5", @@ -59,6 +60,7 @@ "@testing-library/dom": "^10.2.0", "@testing-library/jest-dom": "^6.4.6", "@testing-library/react": "^16.0.0", + "@types/aos": "^3.0.7", "@types/fork-ts-checker-webpack-plugin": "^0.4.5", "@types/jest": "^29.5.12", "@types/mini-css-extract-plugin": "^2.5.1", @@ -7492,6 +7494,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/aos": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/aos/-/aos-3.0.7.tgz", + "integrity": "sha512-sEhyFqvKauUJZDbvAB3Pggynrq6g+2PS4XB3tmUr+mDL1gfDJnwslUC4QQ7/l8UD+LWpr3RxZVR/rHoZrLqZVg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/aria-query": { "version": "5.0.4", "dev": true, @@ -8865,6 +8874,17 @@ "node": ">= 8" } }, + "node_modules/aos": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/aos/-/aos-2.3.4.tgz", + "integrity": "sha512-zh/ahtR2yME4I51z8IttIt4lC1Nw0ktsFtmeDzID1m9naJnWXhCoARaCgNOGXb5CLy3zm+wqmRAEgMYB5E2HUw==", + "license": "MIT", + "dependencies": { + "classlist-polyfill": "^1.0.3", + "lodash.debounce": "^4.0.6", + "lodash.throttle": "^4.0.1" + } + }, "node_modules/app-root-dir": { "version": "1.0.2", "dev": true, @@ -10730,6 +10750,12 @@ "dev": true, "license": "MIT" }, + "node_modules/classlist-polyfill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/classlist-polyfill/-/classlist-polyfill-1.2.0.tgz", + "integrity": "sha512-GzIjNdcEtH4ieA2S8NmrSxv7DfEV5fmixQeyTmqmRmRJPGpRBaSnA2a0VrCjyT8iW8JjEdMbKzDotAJf+ajgaQ==", + "license": "Unlicense" + }, "node_modules/classnames": { "version": "2.5.1", "license": "MIT" @@ -20051,7 +20077,6 @@ }, "node_modules/lodash.debounce": { "version": "4.0.8", - "dev": true, "license": "MIT" }, "node_modules/lodash.memoize": { @@ -20065,6 +20090,12 @@ "license": "MIT", "peer": true }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, "node_modules/log-driver": { "version": "1.2.7", "dev": true, diff --git a/package.json b/package.json index 296ec452..d13b0be5 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@mui/material": "^5.16.4", "@reduxjs/toolkit": "^2.2.5", "antd": "^5.19.2", + "aos": "^2.3.4", "axios": "^1.7.2", "cors": "^2.8.5", "dotenv": "^16.4.5", @@ -61,6 +62,7 @@ "@testing-library/dom": "^10.2.0", "@testing-library/jest-dom": "^6.4.6", "@testing-library/react": "^16.0.0", + "@types/aos": "^3.0.7", "@types/fork-ts-checker-webpack-plugin": "^0.4.5", "@types/jest": "^29.5.12", "@types/mini-css-extract-plugin": "^2.5.1", diff --git a/public/assets/images/23172.jpg b/public/assets/images/23172.jpg new file mode 100644 index 00000000..0f100dda Binary files /dev/null and b/public/assets/images/23172.jpg differ diff --git a/public/assets/images/add-cart-buy-now-online-commerce-graphic-concept.jpg b/public/assets/images/add-cart-buy-now-online-commerce-graphic-concept.jpg new file mode 100644 index 00000000..dd9f5cb3 Binary files /dev/null and b/public/assets/images/add-cart-buy-now-online-commerce-graphic-concept.jpg differ diff --git a/public/assets/images/cropped-image-woman-inputting-card-information-key-phone-laptop-while-shopping-online.jpg b/public/assets/images/cropped-image-woman-inputting-card-information-key-phone-laptop-while-shopping-online.jpg new file mode 100644 index 00000000..e79ff491 Binary files /dev/null and b/public/assets/images/cropped-image-woman-inputting-card-information-key-phone-laptop-while-shopping-online.jpg differ diff --git a/public/assets/images/cyber-monday-shopping-sales.jpg b/public/assets/images/cyber-monday-shopping-sales.jpg new file mode 100644 index 00000000..f4e761e8 Binary files /dev/null and b/public/assets/images/cyber-monday-shopping-sales.jpg differ diff --git a/public/assets/images/happy-man-with-handbags-dancing-after-shopping-spree.jpg b/public/assets/images/happy-man-with-handbags-dancing-after-shopping-spree.jpg new file mode 100644 index 00000000..0961433d Binary files /dev/null and b/public/assets/images/happy-man-with-handbags-dancing-after-shopping-spree.jpg differ diff --git a/public/assets/images/laptop-shopping-bags-online-shopping-concept.jpg b/public/assets/images/laptop-shopping-bags-online-shopping-concept.jpg new file mode 100644 index 00000000..e419aed7 Binary files /dev/null and b/public/assets/images/laptop-shopping-bags-online-shopping-concept.jpg differ diff --git a/public/assets/images/shopping-cart-gift-boxes.jpg b/public/assets/images/shopping-cart-gift-boxes.jpg new file mode 100644 index 00000000..6ebaab30 Binary files /dev/null and b/public/assets/images/shopping-cart-gift-boxes.jpg differ diff --git a/public/assets/images/still-life-say-no-fast-fashion.jpg b/public/assets/images/still-life-say-no-fast-fashion.jpg new file mode 100644 index 00000000..886e5c6e Binary files /dev/null and b/public/assets/images/still-life-say-no-fast-fashion.jpg differ diff --git a/public/assets/shoe1.jpeg b/public/assets/shoe1.jpeg deleted file mode 100644 index aa06ea37..00000000 Binary files a/public/assets/shoe1.jpeg and /dev/null differ diff --git a/public/assets/shoe2.jpeg b/public/assets/shoe2.jpeg deleted file mode 100644 index 45f67048..00000000 Binary files a/public/assets/shoe2.jpeg and /dev/null differ diff --git a/public/assets/shoe3.jpeg b/public/assets/shoe3.jpeg deleted file mode 100644 index aac735c5..00000000 Binary files a/public/assets/shoe3.jpeg and /dev/null differ diff --git a/public/assets/shoe4.jpeg b/public/assets/shoe4.jpeg deleted file mode 100644 index 2e6ea55a..00000000 Binary files a/public/assets/shoe4.jpeg and /dev/null differ diff --git a/src/App.scss b/src/App.scss index b109170a..a09dbd44 100644 --- a/src/App.scss +++ b/src/App.scss @@ -1,5 +1,6 @@ @import './assets/styles/Colors.scss'; @import './assets/styles/style.scss'; +@import './assets/styles/toastify.scss'; @import './assets/styles/Sample.scss'; @import './assets/styles/signup.scss'; @import './assets/styles/Login.scss'; diff --git a/src/assets/styles/Colors.scss b/src/assets/styles/Colors.scss index 6a8af75a..be501a2e 100644 --- a/src/assets/styles/Colors.scss +++ b/src/assets/styles/Colors.scss @@ -26,9 +26,24 @@ $text-family: 'Averia Serif Libre'; $white-color: #FFFFFF; $border-color: #D9D9D9; $red-color:red; +$grayColor:gray; $primary-color-half: rgb(248,244,244); $red-color:red; $menu-hover: #FE975B; $green-color: rgb(3, 216, 3); $green-middle-color: rgba(3, 216, 3, 0.3); $red-middle-color: rgba(216, 8, 3, 0.3); + + +$toastify-color-light: #fff; +$toastify-color-dark: #121212; +$toastify-color-info: #3498db; +$toastify-color-success: orange; +$toastify-color-warning: #f1c40f; +$toastify-color-error: #e74c3c; + + +$toastify-icon-color-info: var($toastify-color-info); +$toastify-icon-color-success: var($toastify-color-success); +$toastify-icon-color-warning: var($toastify-color-warning); +$toastify-icon-color-error: var($toastify-color-error); \ No newline at end of file diff --git a/src/assets/styles/LandingPage.scss b/src/assets/styles/LandingPage.scss index a9b41e22..44bfc785 100644 --- a/src/assets/styles/LandingPage.scss +++ b/src/assets/styles/LandingPage.scss @@ -1,6 +1,7 @@ .landing-container { padding: 3rem 2rem 4rem 5rem; background-color: $container-color; + .loader { display: flex; justify-content: center; @@ -8,6 +9,44 @@ height: 100vh; } + .load-more { + display: flex; + justify-content: center; + align-items: center; + margin-top: 2rem; + padding: 1rem 2rem; + cursor: pointer; + + button { + background-color: $primary-color; + color: $white-color; + border: none; + padding: 0.8rem 1rem; + border-radius: 0.5rem; + cursor: pointer; + } + + button:hover { + background-color: $primary-color-dark; + padding: 0.8rem 2rem; + transition: all 0.5s ease-in-out; + animation: bounce 1s infinite; + + } + + @keyframes bounce { + + 0%, + 100% { + transform: translateY(0); + } + + 50% { + transform: translateY(-10px); + } + } + } + .error-message { display: flex; justify-content: center; @@ -21,11 +60,13 @@ padding: 2rem; } + .head { display: flex; justify-content: space-between; align-items: center; + h1 { font-size: 3.6rem; } @@ -51,7 +92,8 @@ label { width: 15rem; } - .span{ + + .span { width: 20rem; } } @@ -161,6 +203,7 @@ width: 40vw; } + .not-found-text { font-family: $text-family; font-weight: 700; @@ -173,8 +216,20 @@ color: $text2-color; text-decoration: none; transition: all 0.3s ease-in-out; + font-family: $text-family; + font-weight: 700; + font-size: 1.2rem; + margin-top: 1rem; + margin-bottom: 2rem; + text-align: center; + line-height: 1.5; + letter-spacing: 0.05em; + color: $text2-color; + text-decoration: none; + transition: all 0.3s ease-in-out; } + .btn-link { border: none; background-color: $primary-color; @@ -186,6 +241,16 @@ font-size: 1.2rem; border-radius: 2rem; cursor: pointer; + border: none; + background-color: $primary-color; + padding: 1rem 4rem; + text-decoration: none; + color: $white-color; + font-family: $text-family; + font-weight: 700; + font-size: 1.2rem; + border-radius: 2rem; + cursor: pointer; } .btn-link:hover { @@ -194,6 +259,11 @@ border: 1px solid $border-color; box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.5); transition: all 0.3s ease-in-out; + background-color: $white-color; + color: $primary-color; + border: 1px solid $border-color; + box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.5); + transition: all 0.3s ease-in-out; } } @@ -201,6 +271,7 @@ .landing-container { padding: 3rem 4rem 4rem 4rem; + .head { h1 { font-size: 2.6rem; diff --git a/src/assets/styles/Sample.scss b/src/assets/styles/Sample.scss index 581bc697..f4d8ff1f 100644 --- a/src/assets/styles/Sample.scss +++ b/src/assets/styles/Sample.scss @@ -1,31 +1,30 @@ .sampleImages1 { display: flex; - width: 100%; + width: 100vw; color: $white; background-color: $white; - z-index: -1; gap: 1rem; - height: 30rem; + height: 40rem; .sample1, .sample3 { flex: 1; display: flex; flex-direction: column; - width: 30%; - z-index: 100; + width: 20%; + height: 40rem; gap: 1rem; } .sample2 { - flex: 1; - background-size: cover; - background-position: center; - background-repeat: no-repeat; - width: 30%; - z-index: 100; + width: 40%; display: flex; position: relative; + img{ + width: 100%; + height: 100%; + object-fit: fill; + } .arrow { position: absolute; top: 50%; @@ -72,14 +71,13 @@ display: flex; align-items: center; position: relative; - z-index: 100; + height: 40rem; img{ width: 100%; - height: 14.5rem; - object-fit: cover; + height: 100%; } p { - font-size: 1.4rem; + font-size: 1.8rem; } button { @@ -103,6 +101,7 @@ flex-direction: column; align-items: flex-start; left: 3rem; + gap: 1rem; } button { @@ -118,6 +117,8 @@ align-items: flex-start; position: absolute; left: 3rem; + gap: 1rem; + } button { @@ -136,6 +137,8 @@ align-items: flex-end; position: absolute; right: 3rem; + gap: 1rem; + } button { @@ -144,7 +147,6 @@ } .accessories { - // background-image: url('../../public/assets/right-bottom.png'); .text-container { display: flex; @@ -152,8 +154,10 @@ align-items: flex-end; position: absolute; right: 3rem; + gap: 1rem; + p { - padding-right: 1.5rem; + padding-right: .1rem; } button { diff --git a/src/assets/styles/toastify.scss b/src/assets/styles/toastify.scss new file mode 100644 index 00000000..9d847f69 --- /dev/null +++ b/src/assets/styles/toastify.scss @@ -0,0 +1,44 @@ +.Toastify__toast-container { + z-index: 100; + width: 380px; + font-size: 1.5rem; + font-weight: 500; + .Toastify__toast--success { + font-size: medium; + text-align: center; + color: $white; + background: $toastify-color-success; + } + .Toastify__toast--info { + color: $white-color; + text-align: center; + background: $toastify-color-info; + } + .Toastify__toast--warning { + text-align: center; + color: $white-color; + background: $toastify-color-warning; + } + .Toastify__toast--error { + color: $white-color; + text-align: center; + background:$toastify-color-error; + } + .Toastify__progress-bar--info { + background: $primary-color-light; + } + .Toastify__progress-bar--success { + background: $primary-color-light; + } + .Toastify__progress-bar--warning { + background: $primary-color-light; + } + .Toastify__progress-bar--error { + background: $primary-color-light; + } + .Toastify__toast-icon{ + svg{ + fill: white; + } + } + } \ No newline at end of file diff --git a/src/components/layout/Sample.tsx b/src/components/layout/Sample.tsx index bd757f27..2975a3e6 100644 --- a/src/components/layout/Sample.tsx +++ b/src/components/layout/Sample.tsx @@ -12,8 +12,12 @@ import leftBottom from "../../../public/assets/images/left-bottom.png"; import rightBottom from "../../../public/assets/images/right-bottom.png"; const images = [ '/assets/middle.png', - '/assets/shoe2.jpeg', - '/assets/shoe3.jpeg' + '/assets/images/1293.jpg', + '/assets/images/add-cart-buy-now-online-commerce-graphic-concept.jpg', + '/assets/images/cropped-image-woman-inputting-card-information-key-phone-laptop-while-shopping-online.jpg', + '/assets/images/cyber-monday-shopping-sales.jpg', + '/assets/images/happy-man-with-handbags-dancing-after-shopping-spree.jpg', + '/assets/images/laptop-shopping-bags-online-shopping-concept.jpg', ]; const Sample: React.FC = () => { @@ -69,7 +73,8 @@ const Sample: React.FC = () => { -
+
+
diff --git a/src/components/product/Product.tsx b/src/components/product/Product.tsx index 02f9bc88..d24de3b0 100644 --- a/src/components/product/Product.tsx +++ b/src/components/product/Product.tsx @@ -7,6 +7,7 @@ import { useAppDispatch, useAppSelector } from '../../store/store'; import { createCart, getUserCarts } from "../../store/features/carts/cartSlice"; import { addProductToWishlist, removeProductFromWishlist, fetchWishlistProducts } from '../../store/features/wishlist/wishlistSlice'; import { toast } from "react-toastify"; +import aos from "aos" interface ProductProps { id: string; @@ -36,6 +37,9 @@ const Product: React.FC = ({ const isProductInWishlist = wishlist.some((item: any) => item.id === id); const [isInWishlist, setIsInWishlist] = useState(isProductInWishlist); + useEffect(()=>{ + aos.init({ once: true }); + },[]); useEffect(() => { setIsInWishlist(isProductInWishlist); }, [isProductInWishlist]); @@ -142,7 +146,7 @@ const Product: React.FC = ({ return ( -
+
{ const { products, isError, isSuccess, isLoading, message } = useAppSelector( (state: any) => state.products ); + const [visibleProducts, setVisibleProducts] = useState(20); useEffect(() => { dispatch(fetchProducts()); }, [dispatch]); @@ -60,6 +61,10 @@ const LandingPage: React.FC = () => { checkProductToCartPending(); }, []); + const handleLoadMore = () => { + setVisibleProducts((prevVisibleProducts) => prevVisibleProducts + 20); + }; + return ( <> @@ -81,7 +86,9 @@ const LandingPage: React.FC = () => {
{isSuccess && Array.isArray(products) && - products?.map((product: any) => ( + products + .slice(0,visibleProducts) + .map((product: any) => ( { /> ))}
+ {visibleProducts < products.length && (
+ +
)}
)}
diff --git a/src/pages/Products.tsx b/src/pages/Products.tsx index a22ec25d..6c6da9ed 100644 --- a/src/pages/Products.tsx +++ b/src/pages/Products.tsx @@ -21,6 +21,8 @@ const ProductsPage: React.FC = () => { const [maxPrice, setMaxPrice] = useState(0); const [minPrice, setMinPrice] = useState(0); + const [visibleProducts, setVisibleProducts] = useState(20); + useEffect(() => { dispatch(fetchProducts()); }, [dispatch]); @@ -36,6 +38,17 @@ const ProductsPage: React.FC = () => { } }, [products]); + useEffect(() => { + if (products.length > 0) { + const calculatedMaxPrice = products.reduce((max, product) => Math.max(max, product.price), 0); + const calculatedMinPrice = products.reduce((min, product) => Math.min(min, product.price), calculatedMaxPrice); + + setMaxPrice(calculatedMaxPrice); + setMinPrice(calculatedMinPrice); + setPriceRange([calculatedMinPrice, calculatedMaxPrice]); + } + }, [products]); + const handleAddProductToCart = async (productId: string, quantity = 1) => { try { const response = await dispatch( @@ -60,6 +73,7 @@ const ProductsPage: React.FC = () => { } }; + useEffect(() => { const checkProductToCartPending = async () => { const pendingProduct = localStorage.getItem("pendingCartProduct"); @@ -81,8 +95,13 @@ const ProductsPage: React.FC = () => { return price >= priceRange[0] && price <= priceRange[1]; }); + const handleLoadMore = () => { + setVisibleProducts((prevVisibleProducts) => prevVisibleProducts + 20); + }; + return ( <> +
{isLoading ? ( @@ -98,6 +117,22 @@ const ProductsPage: React.FC = () => {

Products

+
+
+ + + setPriceRange([priceRange[0], Number(e.target.value)]) + } + /> + ${priceRange[0]} - ${priceRange[1]} +
+

Products

+
@@ -116,7 +151,9 @@ const ProductsPage: React.FC = () => {
{isSuccess && Array.isArray(filteredProducts) && - filteredProducts.map((product: any) => ( + filteredProducts + .slice(0,visibleProducts) + .map((product: any) => ( { /> ))}
+ {visibleProducts < products.length && (
+ +
)}
)}