//this is Cartscreen.jsx file

import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
//useDispatch for request and useSelector for data retrive
import { Row, Col, Form, Button, Card, Image, ListGroup, ListGroupItem } from 'react-bootstrap'
import { addToCart, removeFromCart } from '../actions/cartAction'
import { useNavigate, useParams, useLocation } from 'react-router-dom'
import Message from '../components/shared/Message'

const CartScreen = () => {
    const params = useParams()
    const location = useLocation()
    const navigate = useNavigate()
    const productId = params.id
    const qty = location.search ? Number(location.search.split('=')[1]) : 1
    const dispatch = useDispatch()

    useEffect(() => {
        //checking product is coming or not
        if (productId) {
            dispatch(addToCart(productId, qty))//both value will remain in redux
        }
    }, [dispatch, productId, qty])//these passed as dependencies as array

    const cart = useSelector(state => state.cart)
    const { cartItems } = cart;

    const removeFromCartHandler = (id) => {
        dispatch(removeFromCart(id))
    }

    const checkOut = () => {
        //navigate("/login", { state: { redirect: "shipping" } });
        navigate("/login?redirect=shipping");
    }

    return (
        <>
            <Row>
                <Col md={8}>
                    <h1>Shopping Cart</h1>
                    {cartItems.length === 0 ? (
                        <Message>
                            Your Cart is Empty !<Link to="/">Go Back</Link>
                        </Message>
                    ) : (
                        <ListGroup variant="flush">
                            {cartItems.map((item) => (
                                <ListGroupItem key={item.product}>
                                    <Row>
                                        <Col md={2}>
                                            <Image src={item.image} alt={item.name} fluid rounded />
                                        </Col>
                                        <Col md={3}>
                                            <Link to={`/product/${item.product}`}>{item.name}</Link>
                                        </Col>
                                        <Col md={2}>${item.price}</Col>
                                        <Col md={2}>
                                            <Form.Control
                                                as="select"
                                                value={item.qty}
                                                onChange={(e) =>
                                                    dispatch(
                                                        addToCart(item.product, Number(e.target.value))
                                                    )
                                                }
                                            >
                                                {[...Array(item.countInStock).keys()].map((x) => (
                                                    <option key={x + 1} value={x + 1}>
                                                        {x + 1}
                                                    </option>
                                                ))}
                                            </Form.Control>
                                            <Button
                                                type="button"
                                                variant="light"
                                                onClick={() => removeFromCartHandler(item.product)}
                                            >
                                                <i
                                                    className="fa fa-trash text-danger"
                                                    aria-hidden="true"
                                                ></i>
                                            </Button>
                                        </Col>
                                    </Row>
                                </ListGroupItem>
                            ))}
                        </ListGroup>
                    )}
                </Col>
                <Col md={4}>
                    <Card>
                        <ListGroup variant="flush">
                            <ListGroupItem>
                                <h2>
                                    subtotal ({cartItems.reduce((acc, item) => acc + item.qty, 0)}
                                    ) items
                                </h2>
                                $
                                {cartItems
                                    .reduce((acc, item) => acc + item.qty * item.price, 0)
                                    .toFixed(2)}
                            </ListGroupItem>
                            <Button
                                type="button"
                                className="btn-block"
                                disabled={cartItems.length === 0}
                                onClick={checkOut}
                            >
                                Proceed to checkOut
                            </Button>
                        </ListGroup>
                    </Card>
                </Col>
            </Row>
        </>
    )
}

export default CartScreen

//this is ShippingScreen.jsx file

import React, { useState } from 'react';
import { Form, useNavigate } from 'react-router-dom';
import { Button } from 'react-bootstrap';
import { useSelector, useDispatch } from 'react-redux';
import { saveShippingAddress } from '../actions/cartAction';
import FormContainer from './../components/shared/FormContainer';

const ShippingScreen = () => {
    const navigate = useNavigate()
    const dispatch = useDispatch()
    const cart = useSelector(state => state.cart)
    const { shippingAddress } = cart
    const [address, setAddress] = useState(shippingAddress?.address || '')
    const [city, setCity] = useState(shippingAddress?.city || '')
    const [postal, setPostal] = useState(shippingAddress?.postal || '')
    const [country, setCountry] = useState(shippingAddress?.country || '')

    const submitHandler = (e) => {
        e.preventDefault()
        //dispatch
        dispatch(saveShippingAddress({ address, city, postal, country }))
        navigate('/payment')
    }

    return (
        <div>
            <FormContainer>
                <Form onSubmit={submitHandler}>
                    <Form.Group controlId='address'>
                        <Form.Label>Address</Form.Label>
                        <Form.Control type='text'
                            placeholder='Enter Address'
                            value={address}
                            onChange={e => setAddress(e.target.value)}>
                        </Form.Control>
                    </Form.Group>
                    <Form.Group controlId='city'>
                        <Form.Control type='text'
                            placeholder='City'
                            value={city}
                            onChange={e => setCity(e.target.value)}>
                        </Form.Control>
                    </Form.Group>
                    <Form.Group controlId='postal'>
                        <Form.Control type='text'
                            placeholder='Postal Code'
                            value={postal}
                            onChange={e => setPostal(e.target.value)}>
                        </Form.Control>
                    </Form.Group>
                    <Form.Group controlId='country'>
                        <Form.Control type='text'
                            placeholder='Country'
                            value={country}
                            onChange={e => setCountry(e.target.value)}>
                        </Form.Control>
                    </Form.Group>
                    <Button type='submit' variant='primary'>Continue</Button>
                </Form>
            </FormContainer>
        </div>
    )
}

export default ShippingScreen

below cartAction.js file

import axios from 'axios'
import {
    CART_ADD_ITEM,
    CART_REMOVE_ITEM,
    CART_SAVE_SHIPPING_ADDRESS} from '../constants/CartConstant'

export const addToCart =(id,qty)=>async(dispatch,getstate)=>{
    const {data} = await axios.get(`/api/products/${id}`)
    dispatch({
        type:CART_ADD_ITEM,
        payload:{
            product:data._id,
            name:data.name,
            image:data.image,
            price:data.price,
            countInStock:data.countInStock,
            qty,
        },
    });
    localStorage.setItem('cartItems',JSON.stringify(getstate().cart.cartItems))
};
//we use getstate because we have items in local storage
export const removeFromCart = (id)=>(dispatch,getState) =>{
    dispatch({
        type:CART_REMOVE_ITEM,
        payload:id
    })
    localStorage.setItem('cartItems',JSON.stringify(getState().cart.cartItems))
};

export const saveShippingAddress = (data)=>(dispatch)=>{
    dispatch({type:CART_SAVE_SHIPPING_ADDRESS,payload:data,});
    localStorage.setItem('shippingAddress',JSON.stringify(data))
};

i am trying to go to shipping.jsx file but after clicking on checkout button which present in cartScreen.jsx file it redirect me to home page '/'
Things i have tried
\> try different way to adjust the link which send to shipping page

\>different way to use hooks
\>checked if routes are correct or not but incase if u ask

<Route path="/shipping" element={<ShippingScreen/>}></Route>
0

There are 0 best solutions below