0
0 Comments

//here is my server.js code 
 import express from 'express';
import data from './data.js';
 const app = express();
 //test api
app.get('/api/products', (req , res)=>{
    res.send(data.products);
})
 app.get('/api/products/slug/:slug', (req , res)=>{
    const product = data.products.find((x)=> x.slug === req.params.slug)
    if(product){
        res.send(product)
    }else{
        res.status(404).send({message:'product not found'});
    }
    res.send(data.products);
})
app.get('/api/products/:id', (req , res)=>{
    const product = data.products.find((x)=> x._id === req.params._id)
    if(product){
        res.send(product)
    }else{
        res.status(404).send({message:'product not found'});
    }
    res.send(data.products);
})
 const port = process.env.PORT || 5000;
 app.listen(port, () => {
    console.log(`server is running on ${port}`)
});
  here is my productscreen.js code//
 import axios from "axios";
import React from "react";
import { useContext , useEffect, useReducer } from "react";
 import { useParams } from "react-router-dom";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import Rating from "../components/Rating";
import ListGroup from 'react-bootstrap/ListGroup'
import Card from 'react-bootstrap/Card'
import Badge from 'react-bootstrap/Badge'
import Button from "react-bootstrap/esm/Button";
import {Helmet} from 'react-helmet-async'
import LoadingBox from "../components/LoadingBox";
import MessageBox from "../components/MessageBox";
import getError from "../Error";
import { Store } from "../Store";
  const ProductScreen = () => {
const reducer = (state, action) => {
  switch (action.type) {
      case "FETCH_REQUEST":
        return { ...state, loading: true };
      case "FETCH_SUCCESS":
        return { ...state, product: action.payload, loading: false };
      case "FETCH_FAIL":
        return { ...state, loading: false, error: action.payload };
      default:
        return state;
    }
  };
  const params = useParams();
  const { slug } = params;
  const [{ loading, error, product }, dispatch] = useReducer(reducer, {
    product: [],
    loading: true,
    error: "",
  });
  // const [products, setProducts] = useState([]);
  useEffect(() => {
    const fetchData = async () => {
      dispatch({ type: "FETCH_REQUEST" });
      try {
        const result = await axios.get(`/api/products/slug/${slug}`);
        dispatch({ type: "FETCH_SUCCESS", payload: result.data });
      } catch (err) {
        dispatch({ type: "FETCH_FAIL", payload: getError(err) });
      }
       // setProducts(result.data)
    };
    fetchData();
  }, [slug]);
   const {state, dispatch: ctxDispatch} = useContext(Store);
  const {cart} = state;
  const addToCart = async () =>{
    const existItem = cart.cartItems.find(x => x._id === product._id)
    const quantity = existItem ? existItem.quantity + 1 : 1;
    const { data } = await axios.get(`/api/products/${product._id}`); 
    if(data.countInStock < quantity) {
      window.alert('sorry, product is out of stock');
      return;
    } 
      ctxDispatch({
        type:'CART_ADD_ITEM',
        payload: {...product, quantity:1},
      })
  }
   return loading ? (
    <LoadingBox />
   ):error ? (
     <MessageBox variant="danger">{error}</MessageBox>
   ): (
    <div>
      <Row>
        <Col md={6}>
          <img
            className="img-large"
            src={product.image}
            alt={product.name}
          ></img>
        </Col>
        <Col md={3}>
          <ListGroup variant="flush">
            <ListGroup.Item>
              <Helmet>
                <title>{product.name}</title>
              </Helmet>
              <h1>{product.name}</h1>
            </ListGroup.Item>
            <ListGroup.Item>
              <Rating
                Rating={product.rating}
                numReviews={product.numReviews}
              ></Rating>
            </ListGroup.Item>
            <ListGroup.Item>price : ${product.price}</ListGroup.Item>
            <ListGroup.Item> Description: <p>{product.description}</p></ListGroup.Item>
          </ListGroup>
        </Col>
        <Col md={3}>
          <Card>
            <Card.Body>
              <ListGroup variant="flush">
                <ListGroup.Item>
                  <Row>
                    <Col>Prices:</Col>
                    <Col>{product.price}</Col>
                  </Row>
                </ListGroup.Item>
                <ListGroup.Item>
                  <Row>
                    <Col>Status:</Col>
                    <Col>{product.countInStock>0?
                    <Badge bg = "success">In stock</Badge>:
                    <Badge bg = "danger">Unavailiable</Badge>}</Col>
                  </Row>
                </ListGroup.Item>
                 {product.countInStock > 0 && (
                  <ListGroup.Item>
                    <div className="d-grid">
                    <Button onClick={addToCart} variant = "primary">Add to Cart</Button>
                    </div>
                  </ListGroup.Item>
                )}
              </ListGroup>
            </Card.Body>
          </Card>
        </Col>
      </Row>
    </div>
  );
};
 export default ProductScreen;
  // here is my store.js code
 import { createContext, useReducer } from "react";
 // Implement add to cart and store using context
export const Store = createContext ();
 const initialState = {
     cart:{
        cartItems:[],
    },
};
function reducer(state, action) {
    switch (action.type){
        case 'CART_ADD_ITEM':
            //add to cart
            const newItem = action.payload;
            const existItem = state.cart.cartItems.find(
                (item) => item._id === newItem._id
            );
            const cartItems = existItem
            ? state.cart.cartItems.map((item) => 
            item._id === existItem._id ? newItem : item 
            )
            : [...state.cart.cartItems, newItem];
            return { ...state, cart: {...state.cart, cartItems }};
        default:
    return state;
    };
     }
 export function StoreProvider(props) {
 const [state, dispatch] = useReducer(reducer, initialState);
 const value = {state, dispatch};
 return <Store.Provider value={value}>{props.children}</Store.Provider>
}
 //here is my app.js code
 import React from 'react'
import {BrowserRouter ,Route , Routes} from 'react-router-dom'
import HomeScreen from './screens/HomeScreen'
import ProductScreen from './screens/ProductScreen'
import Navbar from 'react-bootstrap/Navbar';
import Nav from 'react-bootstrap/Nav';
import Badge from 'react-bootstrap/Badge';
import {LinkContainer} from 'react-router-bootstrap';
import Container from 'react-bootstrap/Container';
import { Link } from 'react-router-dom';
import { useContext } from 'react';
import { Store } from './Store'
 const App = () => {
  const {state} = useContext(Store);
  const {cart} = state;
  return (
    <BrowserRouter>
    <div className='d-flex flex-column site-container'>
      <header>
        <Navbar bg = "dark" variant="dark">
          <Container>
            <LinkContainer to="/">
            <Navbar.Brand>MOJO-Shoping</Navbar.Brand>
            </LinkContainer>
            <Nav className="me-auto">
              <Link to="/cart" className='nav-link'>
                Cart 
                {cart.cartItems.length > 0 && (
                  <Badge pill bg = "danger">
                    {cart.cartItems.reduce((a , c) => a + c.quantity , 0)}
                  </Badge>
                )}
              </Link>
            </Nav>
          </Container>
        </Navbar>
      </header>
             <main>
        <Container className='mt-4'>
        <Routes>
          <Route path='/product/:slug' element = {<ProductScreen />} />
          <Route path='/' element={<HomeScreen />} />
        </Routes>
        </Container>
      </main>
      <footer>
        <div className='text-center'>All rights reserved</div>
      </footer>
    </div>
    </BrowserRouter>
  )
}
 export default App

Bassir Changed status to publish October 11, 2022