const Button = ReactBootstrap.Button;
const Card = ReactBootstrap.Card;
const { CSSTransition, TransitionGroup } = ReactTransitionGroup;
const { useContext, useReducer, useEffect, createContext, useRef } = React
const GET_PRODUCTS = 'GET_PRODUCTS';
const FILTER_PRODUCTS = 'FILTER_PRODUCTS';
const CLEAR_FILTER = 'CLEAR_FILTER';
//context
const ShoppingCartContext = createContext();
//reducer
const ShoppingCartReducer = (state, action) => {
switch(action.type) {
case GET_PRODUCTS:
return {
...state,
products: action.payload
}
case FILTER_PRODUCTS:
return {
...state,
filtered: state.products.filter(product => {
const regex = new RegExp(`${action.payload}`, 'gi');
return product.name.match(regex) || product.category.match(regex);
})
};
case CLEAR_FILTER:
return {
...state,
filtered: null
}
default:
return state;
}
}
//state
const ShoppingCartState = props => {
const initState = {
products: [],
filtered: null
}
const [state, dispatch] = React.useReducer(ShoppingCartReducer, initState);
//Get products
const getProducts = () => {
dispatch({
type: GET_PRODUCTS,
payload: [{
id:1,
category: 'food',
name: 'noodles',
size:'large',
price:100
},{
id:2,
category: 'food2',
name: 'noodles',
size:'small',
price:50
},{
id:3,
category: 'food',
name: 'rice',
size:'large',
price:120
},{
id:4,
category: 'food',
name: 'rice',
size:'large',
price:120
}]
})
}
//filter products
const filterProducts = text => {
dispatch({type: FILTER_PRODUCTS, payload:text});
}
//clear filter
const clearFilter = text => {
dispatch({type: CLEAR_FILTER});
}
return (<ShoppingCartContext.Provider value = {{
products: state.products,
getProducts,
filterProducts,
clearFilter,
filtered: state.filtered,
}}>
{props.children}
</ShoppingCartContext.Provider>)
}
const Content = () => {
const shoppingCartContext = React.useContext(ShoppingCartContext);
React.useEffect( ()=>{
shoppingCartContext.getProducts();
}, []);
return (
<Menu/>
)
}
const Menu = () => {
const shoppingCartContext = React.useContext(ShoppingCartContext);
const { products, filtered } = shoppingCartContext
return (
<div className="container menu-container">
<div className="row">
{filtered !== null ? filtered.map(product => (
<TransitionGroup>
<CSSTransition key={product.id} timeout={500} classNames="item">
<MenuItem product = {product} />
</CSSTransition>
</TransitionGroup>
)):products.map(product => (
<TransitionGroup>
<CSSTransition key={product.id} timeout={500} classNames="item">
<MenuItem product = {product} />
</CSSTransition>
</TransitionGroup>
))}
</div>
</div>
)
}
const MenuItem = ({product}) => {
return (
<div className="col-md-4 col-xs-4">
<Card style={{ width: '18rem' }}>
<Card.Body>
<Card.Title>{product.name}</Card.Title>
<Card.Text>
<div>Category: {product.category}</div>
<div>Size: {product.size}</div>
<div>Prize: {product.price}</div>
</Card.Text>
<Button className="menu-btn" variant="primary" >Check</Button>
<Button className="menu-btn" variant="primary" >Add</Button>
</Card.Body>
</Card>
</div>
)
}
const ProductsFilter = () => {
const shoppingCartContext = useContext(ShoppingCartContext);
const text = useRef('');
const {filterProducts, clearFilter, filtered} = shoppingCartContext;
useEffect(() => {
if (filtered === null) {
text.current.value = '';
}
});
const onChange = e => {
if (text.current.value !== '') {
filterProducts(e.target.value);
} else {
clearFilter();
}
}
return (
<form>
<input ref={text} type="text" placeholder="Filter products..." onChange={onChange}/>
</form>
)
}
const app = (
<ShoppingCartState>
<ProductsFilter/>
<Content/>
</ShoppingCartState>
);
ReactDOM.render(app, document.getElementById("root"));
View Compiled