Api for orderplace is not found in redux

70 Views Asked by At

My /api/orders is not getting found. I had the same approach for users and products and they worked. I am following BradTraversy's Mern Ecommerce from scratch. This is his github repo but this is mostly outdated. https://github.com/bradtraversy/proshop_mern

This is my states

This is my actions file

import {
ORDER_CREATE_REQUEST,
ORDER_CREATE_SUCCESS,
ORDER_CREATE_FAIL,
} from '../constants/orderConstants'
import axios from 'axios'

export const createOrder = (order) => async (dispatch, getState) => {
try {
dispatch({
  type: ORDER_CREATE_REQUEST,
})

const {
  userLogin: { userInfo },
} = getState()

const config = {
  headers: {
    Content_Type: 'application/json',
    Authorization: `Bearer ${userInfo.token}`,
  },
}

const { data } = await axios.post('/api/products', order, config)

dispatch({
  type: ORDER_CREATE_SUCCESS,
  payload: data,
})

localStorage.setItem('userInfo', JSON.stringify(data))
} catch (error) {
dispatch({
  type: ORDER_CREATE_FAIL,
  payload: error.response?.data.message
    ? error.response.data.message
    : error.message,
})
}
}

This is the placeorderscreen

import React, { useEffect } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import {
Button,
Row,
Col,
ListGroup,
Image,
Card,
ListGroupItem,
} from 'react-bootstrap'
import { useDispatch, useSelector } from 'react-redux'
import Message from '../components/Message'
import CheckoutSteps from '../components/CheckoutSteps'
import { createOrder } from '../actions/orderActions.js'

const PlaceOrderScreen = () => {
const navigate = useNavigate()
const dispatch = useDispatch()
const cart = useSelector((state) => state.cart)
// to the end of prices
const addDecimals = (num) => {
return (Math.round(num * 100) / 100).toFixed(2)
}

//   calculate prices
cart.itemsPrice = addDecimals(
cart.cartItems.reduce((acc, item) => acc + item.price * item.qty, 0)
)
cart.shippingPrice = addDecimals(cart.itemsPrice > 100 ? 0 : 100)

cart.taxPrice = addDecimals(Number((0.07 * cart.itemsPrice).toFixed(2)))
cart.totalPrice = (
Number(cart.itemsPrice) +
Number(cart.shippingPrice) +
Number(cart.taxPrice)
).toFixed(2)

// get order from the state
const orderCreate = useSelector((state) => state.orderCreate)
const { order, success, error } = orderCreate
// undefined no order created
console.log(orderCreate.order)

useEffect(() => {
if (success) {
  navigate(`/order/${order._id}`)
}
// eslint-disable-next-line
}, [navigate, success])
// after click placeOrder button we would fire the create order which will take us to 
orderActions
const placeOrderHandler = () => {
dispatch(
  // it's going to pass it through the state and we need to grab it
  createOrder({
    orderItems: cart.cartItems,
    shippingAddress: cart.shippingAddress,
    paymentMethod: cart.paymentMethod,
    itemsPrice: cart.itemsPrice,
    shippingPrice: cart.shippingPrice,
    taxPrice: cart.taxPrice,
    totalPrice: cart.totalPrice,
  })
  )
  }

  return (
  <>
  <CheckoutSteps step1 step2 step3 step4 />
  <Row>
    <Col md={8}>
      <ListGroup variant='flush'>
        <ListGroupItem>
          <h2>Shipping</h2>
          <p>
            <strong>Address:</strong>
            {cart.shippingAddress.address}, {cart.shippingAddress.city}{' '}
            {cart.shippingAddress.postalCode},{' '}
            {cart.shippingAddress.country}
          </p>
        </ListGroupItem>

        <ListGroupItem>
          <h2>Payment Method</h2>
          {/* <p> */}
          <strong>Method:</strong>
          {cart.paymentMethod}
          {/* </p> */}
        </ListGroupItem>

        <ListGroupItem>
          <h2>Order Items</h2>
          {cart.cartItems.length === 0 ? (
            <Message>Your Cart is Empty</Message>
          ) : (
            <ListGroup variant='flush'>
              {cart.cartItems.map((item, index) => (
                <ListGroupItem key={index}>
                  <Row>
                    <Col md={1}>
                      <Image
                        src={item.image}
                        alt={item.name}
                        fluid
                        rounded
                      />
                    </Col>
                    <Col>
                      <Link to={`/product/${item.product}`}>
                        {item.name}
                      </Link>
                    </Col>
                    <Col md={4}>
                      {item.qty} x ${item.price} = ${item.qty * item.price}
                    </Col>
                  </Row>
                </ListGroupItem>
              ))}
            </ListGroup>
          )}
        </ListGroupItem>
      </ListGroup>
    </Col>
    <Col md={4}>
      <Card>
        <ListGroup variant='flush'>
          <ListGroupItem>
            <h2>Order Summary</h2>
          </ListGroupItem>

          <ListGroupItem>
            <Row>
              <Col>Items</Col>
              <Col>${cart.itemsPrice}</Col>
            </Row>
          </ListGroupItem>

          <ListGroupItem>
            <Row>
              <Col>Shipping</Col>
              <Col>${cart.shippingPrice}</Col>
            </Row>
          </ListGroupItem>

          <ListGroupItem>
            <Row>
              <Col>Tax</Col>
              <Col>${cart.taxPrice}</Col>
            </Row>
          </ListGroupItem>

          <ListGroupItem>
            <Row>
              <Col>Total</Col>
              <Col>${cart.totalPrice}</Col>
            </Row>
          </ListGroupItem>

          <ListGroupItem>
            {error && <Message variant='danger'>{error}</Message>}
          </ListGroupItem>

          <ListGroupItem className='d-grid gap-2'>
            <Button
              type='button'
              disabled={cart.cartItems.length === 0}
              onClick={placeOrderHandler}
            >
              Place Order
            </Button>
          </ListGroupItem>
        </ListGroup>
      </Card>
    </Col>
  </Row>
  </>
  )
  }

  export default PlaceOrderScreen

This is the store js

import {
configureStore,
combineReducers,
applyMiddleware,
} from '@reduxjs/toolkit'
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'

// Reducers import
import {
productListReducer,
productDetailsReducer,
} from './reducers/productReducers.js'
import { cartReducer } from './reducers/cartReducers.js'
import {
userLoginReducer,
userRegisterReducer,
userDetailsReducer,
userUpdateProfileReducer,
} from './reducers/userReducers'
import { orderCreateReducer } from './reducers/orderReducers'

const reducer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
cart: cartReducer,
userLogin: userLoginReducer,
userRegister: userRegisterReducer,
userDetails: userDetailsReducer,
userUpdateProfile: userUpdateProfileReducer,
orderCreate: orderCreateReducer,
})

// getting data from local storage
const cartItemsFromStorage = localStorage.getItem('cartItems')
? JSON.parse(localStorage.getItem('cartItems'))
: []

const userInfoFromStorage = localStorage.getItem('userInfo')
? JSON.parse(localStorage.getItem('userInfo'))
: null

const shippingAddressFromStorage = localStorage.getItem('shippingAddress')
? JSON.parse(localStorage.getItem('shippingAddress'))
: {}

//initial state
const initialState = {
cart: {
cartItems: cartItemsFromStorage,
shippingAddress: shippingAddressFromStorage,
},
userLogin: {
userInfo: userInfoFromStorage,
},
}

const middleware = [thunk]

const store = configureStore({
initialState,
reducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware(
  {
    serializableCheck: {
      immutableCheck: false,
      serializableCheck: false,
    },
  },
  composeWithDevTools(applyMiddleware(...middleware))
  ),
  })

  export default store
1

There are 1 best solutions below

0
Akhilesh Gowda M R On

In your code you're doing this in createOrder action.

const { data } = await axios.post('/api/products', order, config)

it should be

const { data } = await axios.post(`/api/orders`, order, config);

this instead. You need to post to /api/orders and not the products