Skip to content

Commit e27a38e

Browse files
Merge pull request #41 from bhagirathpaliyal/products
feat: add support for category-wise product filtering (Men, Women, El…
2 parents 9a0cc10 + a189f1a commit e27a38e

File tree

6 files changed

+160
-83
lines changed

6 files changed

+160
-83
lines changed

src/components/AddProducts.jsx

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,17 @@ const AddProducts = () => {
1818
const [price, setPrice] = useState("");
1919
const [image, setImage] = useState("");
2020
const [isChecked, setIsChecked] = useState(false);
21+
const [category, setCategory] = useState("");
2122
const [errors, setErrors] = useState({
2223
name: "",
2324
price: "",
2425
image: "",
26+
category: "",
2527
});
2628

2729
useEffect(() => {
2830
if (user) {
29-
dispatch(fetchProduct({userId: user.uid}));
31+
dispatch(fetchProduct({ userId: user.uid }));
3032
}
3133
}, [user, dispatch]);
3234

@@ -46,6 +48,10 @@ const AddProducts = () => {
4648
newErrors.image = "Product image URL is required";
4749
isValid = false;
4850
}
51+
if (!category) {
52+
newErrors.category = "Product category is required";
53+
isValid = false;
54+
}
4955

5056
setErrors(newErrors);
5157
return isValid;
@@ -64,14 +70,15 @@ const AddProducts = () => {
6470
dispatch(
6571
addProduct({
6672
userId: user.uid,
67-
item: { name, price, image: imageUrl },
73+
item: { name, price, image: imageUrl ,category, },
6874
})
6975
).then(() => dispatch(fetchProduct(user.uid)));
7076
setName("");
7177
setPrice("");
7278
setImage("");
7379
setIsChecked(false);
74-
setErrors({ name: "", price: "", image: "" });
80+
setCategory("")
81+
setErrors({ name: "", price: "", image: "",category:"" });
7582
}
7683
}
7784
};
@@ -118,6 +125,23 @@ const AddProducts = () => {
118125
/>
119126
</div>
120127

128+
<label htmlFor="category">Category</label>
129+
<select
130+
id="category"
131+
className="border p-2 rounded-md"
132+
value={category}
133+
onChange={(e) => setCategory(e.target.value)}
134+
>
135+
<option value="">Select category</option>
136+
<option value="Men">Men</option>
137+
<option value="Women">Women</option>
138+
<option value="Electronics">Electronics</option>
139+
<option value="Jewellery">Jewellery</option>
140+
</select>
141+
{errors.category && (
142+
<FormHelperText error>{errors.category}</FormHelperText>
143+
)}
144+
121145
{!isChecked && (
122146
<Input
123147
className="border rounded-md"
@@ -144,15 +168,9 @@ const AddProducts = () => {
144168
<div className="mt-8 flex flex-col items-center gap-5">
145169
<div className="text-lg font-bold">Your Products</div>
146170
<ul className="flex flex-wrap gap-[20px] justify-center">
147-
{products.map((item, index) =>
148-
(
149-
<Item
150-
key={index}
151-
index={index + 20}
152-
data={item}
153-
/>
154-
)
155-
)}
171+
{products.map((item, index) => (
172+
<Item key={index} index={index + 20} data={item} />
173+
))}
156174
</ul>
157175
</div>
158176
</div>

src/components/Item.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ function Item(prop) {
7777
<h2 className="text-[12px] md:text-[15px] ">
7878
Merchant: <span className="font-medium">{merchant ? merchant.name : "Loading"}</span>
7979
</h2>
80+
<h2 className="text-[12px] md:text-[15px] ">
81+
category: <span className="font-medium">{prop.data?.category}</span>
82+
</h2>
8083

8184
{!user?.isMerchant && !prop.isCart && (
8285
<Button onClick={() => handleAction("addToCart")}>

src/pages/Electronics/Electronics.jsx

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,48 @@
1-
2-
import { useEffect, useState } from "react";
1+
import { useEffect } from "react";
32
import Footer from "../../components/Footer/Footer";
43
import Item from "../../components/Item";
4+
import { useDispatch, useSelector } from "react-redux";
5+
import { fetchProduct } from "../../store/feature/productSlice";
6+
import ItemSkeleton from "../../components/ItemSkeleton";
57

6-
function Electronics(){
7-
8-
const [product, setProduct] = useState([]);
8+
function Electronics() {
9+
const dispatch = useDispatch();
10+
const { status, items: product } = useSelector((state) => state.product);
11+
const loading = !status || status === "loading" || status === "idle";
912

1013
useEffect(() => {
11-
fetch("https://fakestoreapi.com/products/category/electronics")
12-
.then((res) => res.json())
13-
.then((data) => {
14-
15-
setProduct(data);
16-
});
17-
}, []);
14+
if (!status || status === "idle" || status === "error") {
15+
dispatch(fetchProduct({}));
16+
}
17+
}, [dispatch, status]);
18+
19+
const ElectronicsProducts = product.filter((item) => item.category === "Electronics");
1820

19-
return(
20-
<div className="bg-primary flex flex-col gap-[50px] ">
21+
return (
22+
<div className="bg-secondary flex flex-col pt-[50px] gap-[50px]">
23+
<div className="text-white text-2xl text-center font-bold">Electronics Products</div>
2124

2225
<div className="flex flex-wrap gap-[20px] justify-center">
23-
{product.length > 0 &&
24-
product.slice(0, 10).map((item, index) => (
25-
<Item key={index} index={index+20} data={item} />
26-
))}
26+
{loading ? (
27+
[...Array(12).keys()].map((_, i) => <ItemSkeleton key={i} />)
28+
) : ElectronicsProducts.length > 0 ? (
29+
ElectronicsProducts.slice(0, 100).map((item, index) => (
30+
<Item
31+
key={index}
32+
index={index + 20}
33+
data={item}
34+
reference={item.productRef}
35+
name={item.merchant?.name}
36+
/>
37+
))
38+
) : (
39+
<div className="text-white">No Electronics Products Found</div>
40+
)}
2741
</div>
2842

29-
<Footer/>
43+
<Footer />
3044
</div>
31-
)
45+
);
3246
}
3347

34-
export default Electronics;
48+
export default Electronics;

src/pages/Jewelery/Jewelery.jsx

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,46 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect } from "react";
22
import Footer from "../../components/Footer/Footer";
3-
43
import Item from "../../components/Item";
4+
import { useDispatch, useSelector } from "react-redux";
5+
import { fetchProduct } from "../../store/feature/productSlice";
6+
import ItemSkeleton from "../../components/ItemSkeleton";
57

68
function Jewelery() {
7-
8-
9-
const [product, setProduct] = useState([]);
9+
const dispatch = useDispatch();
10+
const { status, items: product } = useSelector((state) => state.product);
11+
const loading = !status || status === "loading" || status === "idle";
1012

1113
useEffect(() => {
12-
fetch("https://fakestoreapi.com/products/category/jewelery")
13-
.then((res) => res.json())
14-
.then((data) => {
15-
16-
setProduct(data);
17-
});
18-
}, []);
19-
14+
if (!status || status === "idle" || status === "error") {
15+
dispatch(fetchProduct({}));
16+
}
17+
}, [dispatch, status]);
2018

21-
19+
const JewelleryProducts = product.filter((item) => item.category === "Jewellery");
2220

2321
return (
24-
<div className="bg-secondary flex flex-col gap-[50px] ">
22+
<div className="bg-secondary flex flex-col pt-[50px] gap-[50px]">
23+
<div className="text-white text-2xl text-center font-bold">Jewellery Products</div>
2524

2625
<div className="flex flex-wrap gap-[20px] justify-center">
27-
{product?.length > 0 &&
28-
product?.slice(0, 10).map((item, index) => (
29-
<Item key={index} index={index+20} data={item} />
30-
))}
26+
{loading ? (
27+
[...Array(12).keys()].map((_, i) => <ItemSkeleton key={i} />)
28+
) : JewelleryProducts.length > 0 ? (
29+
JewelleryProducts.slice(0, 100).map((item, index) => (
30+
<Item
31+
key={index}
32+
index={index + 20}
33+
data={item}
34+
reference={item.productRef}
35+
name={item.merchant?.name}
36+
/>
37+
))
38+
) : (
39+
<div className="text-white">No Jewellery's Products Found</div>
40+
)}
3141
</div>
3242

33-
<Footer/>
43+
<Footer />
3444
</div>
3545
);
3646
}

src/pages/Men/Men.jsx

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,43 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect } from "react";
22
import Footer from "../../components/Footer/Footer";
33
import Item from "../../components/Item";
4+
import { useDispatch, useSelector } from "react-redux";
5+
import { fetchProduct } from "../../store/feature/productSlice";
6+
import ItemSkeleton from "../../components/ItemSkeleton";
47

58
function Men() {
6-
const [product, setProduct] = useState([]);
9+
const dispatch = useDispatch();
10+
const { status, items: product } = useSelector((state) => state.product);
11+
const loading = !status || status === "loading" || status === "idle";
712

813
useEffect(() => {
9-
fetch("https://fakestoreapi.com/products/category/men's clothing")
10-
.then((res) => res.json())
11-
.then((data) => {
12-
setProduct(data);
13-
});
14-
}, []);
14+
if (!status || status === "idle" || status === "error") {
15+
dispatch(fetchProduct({}));
16+
}
17+
}, [dispatch, status]);
18+
19+
const menProducts = product.filter((item) => item.category === "Men");
1520

1621
return (
17-
<div className="bg-secondary flex flex-col gap-[50px]">
22+
<div className="bg-secondary flex flex-col pt-[50px] gap-[50px]">
23+
<div className="text-white text-2xl text-center font-bold">Men's Products</div>
24+
1825
<div className="flex flex-wrap gap-[20px] justify-center">
19-
{product.length > 0 &&
20-
product
21-
.slice(0, 100)
22-
.map((item, index) => (
23-
<Item key={index} index={index + 20} data={item} />
24-
))}
26+
{loading ? (
27+
[...Array(12).keys()].map((_, i) => <ItemSkeleton key={i} />)
28+
) : menProducts.length > 0 ? (
29+
menProducts.slice(0, 100).map((item, index) => (
30+
<Item
31+
key={index}
32+
index={index + 20}
33+
data={item}
34+
reference={item.productRef}
35+
name={item.merchant?.name}
36+
/>
37+
))
38+
) : (
39+
<div className="text-white">No Men's Products Found</div>
40+
)}
2541
</div>
2642

2743
<Footer />

src/pages/Women/Women.jsx

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,43 @@
1-
import { useEffect, useState } from "react";
1+
import { useEffect } from "react";
22
import Footer from "../../components/Footer/Footer";
33
import Item from "../../components/Item";
4+
import { useDispatch, useSelector } from "react-redux";
5+
import { fetchProduct } from "../../store/feature/productSlice";
6+
import ItemSkeleton from "../../components/ItemSkeleton";
47

58
function Women() {
6-
const [product, setProduct] = useState([]);
9+
const dispatch = useDispatch();
10+
const { status, items: product } = useSelector((state) => state.product);
11+
const loading = !status || status === "loading" || status === "idle";
712

813
useEffect(() => {
9-
fetch("https://fakestoreapi.com/products/category/women's clothing")
10-
.then((res) => res.json())
11-
.then((data) => {
12-
setProduct(data);
13-
});
14-
}, []);
14+
if (!status || status === "idle" || status === "error") {
15+
dispatch(fetchProduct({}));
16+
}
17+
}, [dispatch, status]);
18+
19+
const WomenProducts = product.filter((item) => item.category === "Women");
1520

1621
return (
17-
<div className="bg-primary flex flex-col gap-[50px] ">
22+
<div className="bg-secondary flex flex-col pt-[50px] gap-[50px]">
23+
<div className="text-white text-2xl text-center font-bold">Women's Products</div>
24+
1825
<div className="flex flex-wrap gap-[20px] justify-center">
19-
{product.length > 0 &&
20-
product
21-
.slice(0, 10)
22-
.map((item, index) => (
23-
<Item key={index} index={index + 20} data={item} />
24-
))}
26+
{loading ? (
27+
[...Array(12).keys()].map((_, i) => <ItemSkeleton key={i} />)
28+
) : WomenProducts.length > 0 ? (
29+
WomenProducts.slice(0, 100).map((item, index) => (
30+
<Item
31+
key={index}
32+
index={index + 20}
33+
data={item}
34+
reference={item.productRef}
35+
name={item.merchant?.name}
36+
/>
37+
))
38+
) : (
39+
<div className="text-white">No Women's Products Found</div>
40+
)}
2541
</div>
2642

2743
<Footer />

0 commit comments

Comments
 (0)