diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..e69de29 diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..18c2841 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20.11.0 \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 70b80e0..6e212ac 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -20,6 +20,7 @@ import Buyers from './pages/admin/Buyers'; import Messages from './pages/admin/Messages'; import Settings from './pages/admin/Settings'; +import CategoriesPage from './pages/CategoriesPage'; const App = () => { const { data, error, isLoading } = useGetProductsQuery(); const dispatch = useDispatch(); @@ -65,6 +66,10 @@ const App = () => { path: 'auth/success/:token', element: , }, + { + path: 'categories/:categoryId', + element: , + } ], }, { diff --git a/src/assets/Hero.png b/src/assets/Hero.png new file mode 100644 index 0000000..6bc1f70 Binary files /dev/null and b/src/assets/Hero.png differ diff --git a/src/components/Products/ProductCard.tsx b/src/components/Products/ProductCard.tsx index 2c9aa7c..54628c5 100644 --- a/src/components/Products/ProductCard.tsx +++ b/src/components/Products/ProductCard.tsx @@ -1,20 +1,23 @@ +import { FaHeart } from 'react-icons/fa6'; import { Product } from '../../types/Types'; +import { TiShoppingCart } from 'react-icons/ti'; +import StarRating from '../common/Ratings'; interface ProductCardProps { product: Product; } const ProductCard: React.FC = ({ product }) => { - const imageUrl = product?.images?.[0] ?? 'default-image-url'; - const price = product?.sizes?.[0]?.price ?? 'default-image-url'; + const imageUrl = product?.images?.[0] ?? ''; + const price = product?.sizes?.[0]?.price ?? ''; return ( -
-
+
+
{product.name}
@@ -25,10 +28,16 @@ const ProductCard: React.FC = ({ product }) => {

{product.manufacturer}

-
- +
+
+
+ + +
+
+ +
+
diff --git a/src/components/categories/CategoriesSkeleton.tsx b/src/components/categories/CategoriesSkeleton.tsx new file mode 100644 index 0000000..6078448 --- /dev/null +++ b/src/components/categories/CategoriesSkeleton.tsx @@ -0,0 +1,17 @@ +const CategorySkeleton = () => { + const skeletons = Array.from({ length: 7 }); + + return ( +
+ {skeletons.map((_, index) => ( +
+
+

Loading

+
+
+ ))} +
+ ); +}; + +export default CategorySkeleton; diff --git a/src/components/common/Ratings.tsx b/src/components/common/Ratings.tsx new file mode 100644 index 0000000..90e3c1d --- /dev/null +++ b/src/components/common/Ratings.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { FaStar, FaStarHalfAlt } from 'react-icons/fa'; +import { CiStar } from 'react-icons/ci'; +import { Review } from '../../types/Types'; + +interface RatingsProps { + reviews: Review[]; +} + +const StarRating: React.FC = ({ reviews }) => { + // Calculate the average rating + const calculateAverageRating = (reviews: Review[]): number => { + if (reviews.length === 0) return 0; + const totalRating = reviews.reduce((sum, review) => sum + review.rating, 0); + return totalRating / reviews.length; + }; + + const averageRating = calculateAverageRating(reviews); + + const renderStars = () => { + const stars = []; + for (let i = 1; i <= 5; i++) { + if (averageRating >= i) { + stars.push(); + } else if (averageRating >= i - 0.5) { + stars.push(); + } else { + stars.push(); + } + } + return stars; + }; + + return
{renderStars()}
; +}; + +export default StarRating; diff --git a/src/components/navbar/Navbar.tsx b/src/components/navbar/Navbar.tsx index c42d837..6918eec 100644 --- a/src/components/navbar/Navbar.tsx +++ b/src/components/navbar/Navbar.tsx @@ -195,6 +195,7 @@ const Navbar: React.FC = () => { type='text' className='w-full p-1 px-3 rounded-full text-blackColor outline-none text-xs py-2 md:text-sm md:py-2 font-light md:border md:border-blackColor' placeholder='Search everything at Mavericks online' + required onChange={e => setSearchQuery(e.target.value)} /> +
+ +
+ Sale banner +
+ + +
+
+ +
+ setMinPrice(e.target.value)} + /> +
+
+ setMaxPrice(e.target.value)} + /> +
+
+
+ +
+
+ {/* Products */} +
+
+
+ {currentProducts.length ===0 ? ( +

No products found.

+ ):(currentProducts.map((product, index) => ( +
+
+ {product.name} +
+
+
+
+

{product.name}

+

${product?.sizes?.[0]?.price}

+
+

{product.manufacturer}

+
+
+
+
+ + +
+
+ +
+
+
+
+
+ )) + )} +
+
+ + +
+
+
+ +