I have 4 categories anmial
, treatment
, dailyEssentials
and medical-care
On the left side there are 3 cards for treatment
, dailyEssentials
and medical-care
and one drop-down to select by animals
.
the product gets updated perfectly for the Animal
and the treatment
category but dailyEssentials
and medical-care
are not giving required products as a output instead of that it’s shows all the products.
URL – http://localhost:3000/search/essential/6451eafc000f972917fe38fe
6451eafc000f972917fe38fe
is dailyessential category id .
I have a question that the treatment
card is very similar to dailyEssentials
and medical-care
In my case treatment
is working fine then why not dailyEssentials
and medical-care
.
This is the backend
exports.showAllProducts = catchAsyncError(async (req, res, next) => {
try {
// enable search
const keyword = req.query.keyword
? {
name: {
$regex: req.query.keyword,
$options: 'i',
},
}
: {};
// enable filter by animal
const animalId = req.query.animal;
const animalFilter = animalId ? { animal: animalId } : {};
// enable filter by treatment
const treatmentId = req.query.treatment;
const treatmentFilter = treatmentId ? { treatment: treatmentId } : {};
//enable filter by essentials
const essentialId = req.query.dailyEssential;
const essentialFilter = essentialId ? {dailyEssential: essentialId}: {};
//enable filter by medical care
const medicalCareId = req.query.medicalCare;
const medicalCareFilter = medicalCareId ? {medicalCare: medicalCareId}:{};
// enable pagination
const pageSize = 4;
const page = Number(req.query.pageNumber) || 1;
// construct the filter based on the keyword and any additional filters
const filter = {
...keyword,
...animalFilter,
...treatmentFilter,
...essentialFilter,
...medicalCareFilter,
};
const count = await Product.find(filter).countDocuments();
const products = await Product.find(filter)
.skip(pageSize * (page - 1))
.limit(pageSize);
res.status(200).json({
success: true,
count,
products,
page,
pages: Math.ceil(count / pageSize),
});
} catch (error) {
next(error);
}
});
ESSENTIAL_ACTION
import { DAILY_ESSENTIALS_TYPE_LOAD_FAIL, DAILY_ESSENTIALS_TYPE_LOAD_REQUEST, DAILY_ESSENTIALS_TYPE_LOAD_RESET, DAILY_ESSENTIALS_TYPE_LOAD_SUCCESS } from "../../constants/categories/dailyEssentialsConstants";
import axios from 'axios'
export const dailyEssentialsTypeLoadAction = () => async (dispatch) => {
dispatch({ type: DAILY_ESSENTIALS_TYPE_LOAD_REQUEST });
try {
const { data } = await axios.get('/api/v1/essential');
dispatch({
type: DAILY_ESSENTIALS_TYPE_LOAD_SUCCESS,
payload: data
});
} catch (error) {
dispatch({
type: DAILY_ESSENTIALS_TYPE_LOAD_FAIL,
payload: error.response.data.error
});
}
}
ESSENTIAL REDUCER
import { DAILY_ESSENTIALS_TYPE_LOAD_FAIL, DAILY_ESSENTIALS_TYPE_LOAD_REQUEST, DAILY_ESSENTIALS_TYPE_LOAD_RESET, DAILY_ESSENTIALS_TYPE_LOAD_SUCCESS } from "../../constants/categories/dailyEssentialsConstants";
export const loadDailyEssentialTypeReducer = (state = {dailyEssentialType:[] },action)=>{
switch (action.type){
case DAILY_ESSENTIALS_TYPE_LOAD_REQUEST:
return { loading : true}
case DAILY_ESSENTIALS_TYPE_LOAD_SUCCESS:
return {
loading: false,
dailyEssentialType: action.payload.essentialT
}
case DAILY_ESSENTIALS_TYPE_LOAD_FAIL:
return {
loading: false,
error: action.payload
}
case DAILY_ESSENTIALS_TYPE_LOAD_RESET:
return {}
default:
return state;
}
}
import React, { useEffect, useState } from 'react';
import './product.css';
import { Box, Card, CardContent, Stack, Typography } from '@mui/material';
import ProductCard from './ProductCard';
import { useDispatch, useSelector } from 'react-redux';
import { getProduct } from '../../actions/productAction';
import { Link, useParams } from 'react-router-dom';
import Pagination from '@mui/material/Pagination';
import Loader from '../layout/Loader/Loader';
import SelectComponent from './SelectComponent';
import { animalTypeLoadAction } from '../../actions/categories/animalTypeAction';
import { treatmentTypeLoadAction } from '../../actions/categories/treatmentTypeAction';
import { dailyEssentialsTypeLoadAction } from '../../actions/categories/dailyEssentialTypeAction';
import { medicalCareTypeLoadAction } from '../../actions/categories/medicalCareTypeAction';
const dispatch = useDispatch();
const {error,loading,products,pages} = useSelector(state=>state.products)
const { keyword,treatment,essential,medical} = useParams()
const { treatmentType } = useSelector(state => state.treatmentTypeAll)
const { dailyEssentialType } = useSelector(state => enter image description herestate.dailyEssentialTypeAll)
const { MedicalCareType } = useSelector(state => state.medicalCareTypeAll)
const [page, setPage ] = useState(1);
const [animal, setAnimal ] = useState();
useEffect(()=>{
dispatch(getProduct(page,keyword,animal,treatment,essential,medical))
},[dispatch,page,keyword,animal,treatment,essential,medical])
useEffect(()=>{
dispatch(animalTypeLoadAction())
dispatch(treatmentTypeLoadAction())
dispatch(dailyEssentialsTypeLoadAction())
dispatch(medicalCareTypeLoadAction())
},[])
const handleChangeCategory=(e)=>{
setAnimal(e.target.value)
}
return (
<div>
{
loading ? <Loader /> : <>
<Box sx={{ bgcolor: '#fff', minHeight: '100vh' }}>
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={{ xs: 1, sm: 2, md: 4 }}>
<Box sx={{ flex: 2, p: 2 }}>
<Card sx={{ minWidth: 170, mb: 3, mt: 3, p: 2 }}>
<Box sx={{ pb: 2 }}>
<Typography component="h4" sx={{ color: '#217c04', fontWeight: 700, fontFamily: 'Inter' }}>
SORT AS PER YOUR PREFERENCE
</Typography>
</Box>
<SelectComponent handleChangeCategory={handleChangeCategory} animal={animal} />
</Card>
{/* treatment category card*/}
<Card sx={{ minWidth: 150, mb: 3,mt:2, p: 2 }}>
<Box sx={{ pb: 2 }}>
<Typography component="h4" sx={{ color: '#217c04', fontWeight: 600 }}>
SORT BY TREATMENT
</Typography>
{
treatmentType && treatmentType.map((treatment) => (
<Link className='link' to={`/search/treatment/${treatment._id.toString()}`} key={treatment._id}>
<Card sx={{ minWidth: 150, mb: 1,mt:1, p: 1}}>
<CardContent>
<Typography variant="h6" color="text.primary">
{treatment.TreatmentTypeName}
</Typography>
</CardContent>
</Card>
</Link>
))
}
</Box>
</Card>
{/* daily-Essential-Card */}
<Card sx={{ minWidth: 150, mb: 3,mt:2, p: 2 }}>
<Box sx={{ pb: 2 }}>
<Typography component="h4" sx={{ color: '#217c04', fontWeight: 600 }}>
OUR DAILY ESSENTIALS
</Typography>
{
dailyEssentialType && dailyEssentialType.map((essential) => (
<Link className='link' to={`/search/essential/${essential._id.toString()}`} key={essential._id}>
<Card sx={{ minWidth: 150, mb: 1,mt:1, p: 1}}>
<CardContent>
<Typography variant="h6" color="text.primary">
{essential.essentialName}
</Typography>
</CardContent>
</Card>
</Link>
))
}
</Box>
</Card>
{/* medical-care-card */}
<Card sx={{ minWidth: 150, mb: 3,mt:2, p: 2 }}>
<Box sx={{ pb: 2 }}>
<Typography component="h4" sx={{ color: '#217c04', fontWeight: 600 }}>
SORT BY Medical
</Typography>
{
MedicalCareType && MedicalCareType.map((medical) => (
<Link className='link' to={`/search/medical/${medical._id.toString()}`} key={medical._id}>
<Card sx={{ minWidth: 150, mb: 1,mt:1, p: 1}}>
<CardContent>
<Typography variant="h6" color="text.primary">
{medical.medicalCareName}
</Typography>
</CardContent>
</Card>
</Link>
))
}
</Box>
</Card>
</Box>
{/* main card */}
{
products && products.length === 0 ? <>
<Box
sx={{
minHeight: '350px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
}}>
<h2>No result found!</h2>
</Box>
</> :
<>
<div className='product-main-container' style={{ display: 'flex', flexDirection: 'column' }}>
<Box sx={{ flex: 6, p: 1,mt:4 }}>
<Box sx={{ minHeight: '350px', display: 'flex', justifyContent: 'center', alignItems: 'center',flexDirection: 'column' }}>
{products.map((product) => (
<ProductCard key={product._id} product={product} />
))}
</Box>
<Stack spacing={2} >
<Pagination variant='outlined' className='pagination' page={page} count={pages === 0 ? 1 : pages} onChange={(event, value) => setPage(value)} />
</Stack>
</Box>
</div>
</>
}
</Stack>
</Box>
</>
}
</div>
);
};
export default Product;
import './App.css';
import Home from './components/Home/Home';
import Navbar from './components/Navbar/Navbar';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css'
import '../node_modules/bootstrap/dist/js/bootstrap.bundle'
import {BrowserRouter as Router, Route, Routes} from 'react-router-dom';
import Login from './components/user/Login';
import Product from './components/product/Product';
function App() {
return (
<>
<Router>
<Navbar />
<Routes>
<Route path='/' element={<Home />} />
<Route path='/login' element={<Login />} />
<Route path='/products' element={<Product />} />
{/* product categories routes */}
<Route path='/search/treatment/:treatment' element={<Product />} />
<Route path='/search/essential/:essential' element={<Product />} />
<Route path='/search/medical/:medical' element={<Product />} />
</Routes>
</Router>
</>
);
}
export default App;
productAction.js
import axios from 'axios';
import {
ALL_PRODUCT_REQUEST,
ALL_PRODUCT_SUCCESS,
ALL_PRODUCT_FAIL,
CLEAR_ERRORS
} from "../constants/productConstants"
export const getProduct = (pageNumber,keyword='',animal='',treatment='',essential='',medical='') => async (dispatch)=>
{
try{
dispatch({type:ALL_PRODUCT_REQUEST})
//let link = `/api/v1/products`;
let link = `/api/v1/products/?pageNumber=${pageNumber}&keyword=${keyword}&animal=${animal}&treatment=${treatment}&essential=${essential}&medical=${medical}`;
const {data} = await axios.get(link)
dispatch({
type:ALL_PRODUCT_SUCCESS,
payload:data,
})
}
catch(error){
dispatch({
type: ALL_PRODUCT_FAIL,
payload:error.response.data.message,
})
}
}
2
Answers
So It was my mistake the error was in ProductAction.js
the link would be
/api/v1/products/?pageNumber=${pageNumber}&keyword=${keyword}&animal=${animal}&treatment=${treatment}&dailyEssential=${dailyEssential}
Instead of
essentials
I should have usedailyEssential
medical
I should have usemedicalCare
You should conditionally select which action to dispatch to call the correct/expected backend API. Giving each route a "category" prop to pass to
Product
will make selecting the correct endpoint easier.Example:
From here each action should fetch its expected data from its respective API and update the appropriate state, either the
products
state or its own state that would also need to be selected in theProduct
component to be rendered.