Can we add dropdown view (image with text) on clicking on checkbox in React.js?

91 Views Asked by At

I'm working on a project and i want to add some cool feature on shopping basket/cart. Like after adding something in shopping basket i want to add something more in shopping basket itself by clicking on checkbox button and it will expand more items and by click on add button the item will add directly on the same shopping basket. And the cart value will update dynamically.

I've added some screenshots for what i'm actually want shopping basket/cart - 1 and then updated shopping basket by adding some dropdown items - 2 and after all the payment section updated payment page - 3

That's all. I know for this there may be a lot of things to do. So if any one can give me some solutions or suggestions or references like any existing projects or works - all these things will help me a lot. Kindly guide me.

I'm adding my shopping basket and payment code what i've done yet.

Booking.js

import React from 'react';
import "./Booking.css";
import BookingProduct from '../bookingproduct/BookingProduct';
import Subtotal from '../subtotal/Subtotal';
import { useStateValue } from '../../StateProvider';
import { offer } from '../../assets';


const Booking = () => {

    const [{ basket, user }, dispatch] = useStateValue();


  return (
    <div className='booking'>
        <div className="booking__left">
            <img
                className="booking__ad"
                src={ offer }
                alt=""
            />

            <div>
                <h4 style={{marginTop: 5, padding: 10}}>
                    {/* {!user ? 'Hello,' : 'Welcome,'}  */}
                    Hello, 
                    
                        {!user ? <span style={{color: 'red', fontSize: 18}}> You've not Signed In yet !</span>  : <span style={{color: 'green', fontSize: 18}}> {user?.email}</span>}
                    
                </h4>
                <h3 className='booking__title'>
                    Your Shopping Basket
                </h3>

                {/* To show selected products on Booking page   */}
                {basket.map(item => (
                    <BookingProduct
                        id={item.id}
                        title={item.title}
                        image={item.image}
                        info={item.info}
                        price={item.price}
                        stock={item.stock}
                        nostock={item.nostock}
                        rating={item.rating}
                    />
                ))}
                
            </div>
        </div>

        <div className="booking__right">
            <Subtotal/>
        </div>
    </div>
  )
}

export default Booking

Subtotal.js

import React from 'react';
import './Subtotal.css';
import CurrencyFormat from 'react-currency-format';
import { useStateValue } from '../../StateProvider';
import { getBasketTotal } from '../../reducer';
import { useNavigate } from 'react-router-dom';


const Subtotal = () => {

    const navigate = useNavigate();

    const [{ basket }, dispatch] = useStateValue();

  return (
    <div className='subtotal__title'>
        <h1>BOX OFFICE</h1>
        <div className='subtotal'>
        <CurrencyFormat
            renderText={(value) => (
                <>
                    <p>
                        Subtotal ({ basket?.length } items): <strong>{value}</strong>
                    </p>
                    <small className='subtotal__gift'>
                        <input type="checkbox"/>
                        Add Food and Beverage
                    </small>
                    <p className='subtotal__food'>
                        ▶︎ Order for Food and Beverage will be deliver on same booked theatre.
                    </p>
                    
                </>
            )}
            decimalScale={2}
            value={getBasketTotal(basket)}
            displayType={"text"}
            thousandSeparator={true}
            prefix={"₹ "}
        />

        
    </div>
    {/* Checkout Button  */}
    <button onClick={e => navigate('/payment')}>
            Book Now
        </button>
    </div>
  )
}

export default Subtotal

BookingProduct.js

import React from 'react';
import './BookingProduct.css';
import { useStateValue } from '../../StateProvider';

const BookingProduct = ({ id, image, title, price, rating, hideButton, info, stock, nostock }) => {

    const [{ basket }, dispatch] = useStateValue();


    const removeFromBasket = () => {
        // Remove the item from basket
        dispatch({
            type: 'REMOVE_FROM_BASKET',
            id: id,
        })
    }


  return (
    <div className='bookingProduct'>
        <img
            className='bookingProduct__image'
            src={image}
            alt=""
        />

        <div className="bookingProduct__info">
            <p className="bookingProduct__title">
                {title}
            </p>

            <p style={{fontSize: 10}}>
                {info}
            </p>

            <p className="bookingProduct__price">
                <small style={{fontWeight: 'bold', fontSize: '15px'}}>₹&nbsp;</small>
                <strong style={{fontSize: 14 ,fontWeight: 100}}>{price}</strong>
                <p className="bookingProduct__stock">
                    {/* &nbsp;{stock}&nbsp; */}
                    <small style={{color: "green"}}>&nbsp;{stock}</small>
                    <small style={{color: "darkred"}}>{nostock}&nbsp;</small>
                </p>
            </p>

            <div className="bookingProduct__rating">
                {Array(rating).fill().map((_, i) => (
                    <p></p>
                ))}
            </div>


            {!hideButton && (
                <button onClick={removeFromBasket}>
                    Remove from Box Office
                </button>
            )}
            
        </div>
    </div>
  )
}

export default BookingProduct

Payment.js

import React, { useEffect, useState } from 'react';
import { CardElement, useElements, useStripe } from '@stripe/react-stripe-js';
import { Link, useNavigate } from 'react-router-dom';
import BookingProduct from '../bookingproduct/BookingProduct';
import './Payment.css';
import { useStateValue } from '../../StateProvider';
import { getBasketTotal } from '../../reducer';
import CurrencyFormat from 'react-currency-format';
import axios from '../../axios';
import { db } from '../../firebase';


const Payment = () => {

    const [{ basket, user }, dispatch] = useStateValue();

    const navigate = useNavigate();

    // const stripe = loadStripe('secret_key');
    const stripe = useStripe();
    const elements = useElements();

    const [succeeded, setSucceeded] = useState(false);
    const [processing, setProcessing] = useState("");
    const [error, setError] = useState(null);
    const [disabled, setDisabled] = useState(true);
    const [clientSecret, setClientSecret] = useState(true);

    useEffect(() => {
        
        // generate the special stripe secret which allows us to charge a customer
        const getClientSecret = async () => {
            const response = await axios({
                method: 'post',
                // Stripe expects the total in a currencies subunits => Rupees to Paisa
                url: `/payments/create?total=${getBasketTotal(basket) * 100}`
            });
            setClientSecret(response.data.clientSecret)
        }

        getClientSecret();
    }, [basket])

    console.log('THE SECRET IS >>>', clientSecret)
    console.log('', user)

    const handleSubmit = async (event) => {
        // Do all stripe stuff...
        event.preventDefault();
        setProcessing(true);

        const payload = await stripe.confirmCardPayment(clientSecret, {
            payment_method: {
                card: elements.getElement(CardElement)
            }
        }).then(({ paymentIntent }) => {
            // paymentIntent = payment confirmation
            console.log({ user, basket, paymentIntent })

            // adding orders on order page with user details
            db
                .collection('users')
                .doc(user?.uid)
                .collection('orders')
                .doc(paymentIntent.id)
                .set({
                    basket: basket,
                    amount: paymentIntent.amount,
                    created: paymentIntent.created
                })
                

            setSucceeded(true);
            setError(null);
            setProcessing(false);

            dispatch({
                type: 'EMPTY_BASKET'
            })

            // redirect the page and never back to payment page again since the payment is done 
            navigate('/orders', { replace: true })
        })
    }

    const handleChange = event => {
        // card element work
        // listen for changes in the CardElement
        // and display any errors as the customer types their card details
        setDisabled(event.empty);
        setError(event.error ? event.error.message : "");
    }

  return (
    <div className='payment'>
        <div className="payment__container">

            {/* Number of items in cart / basket */}
            <h1>
                Box Office Booking  (
                    <Link to='/booking' style={{fontSize: 25, verticalAlign: 'middle'}}>
                        {basket?.length} tickets
                    </Link>
                )
            </h1>

            <div className="payment__section">
                <div className="payment__title">
                    <h4>User</h4>
                </div>
                <div className="payment__address">
                    <p>{!user ? <span style={{color: 'red'}}>Please Sign In before making a booking !</span>  : <span style={{color: 'green'}}> {user?.email}</span>}</p>
                    
                    <p></p>
                </div>
            </div>

            {/* Payment Section => Delivery Address */}
            <div className="payment__section">
                <div className="payment__title">
                    <h4>Nearest Theatre</h4>
                </div>
                <div className="payment__address">
                    <p>2023 JavaScript Road</p>
                    <p>Developers Colony, Stack World</p>
                    <p></p>
                </div>
            </div>

            {/* Payment Section => Review Items */}
            <div className="payment__section">
                <div className="payment__title">
                    <h4>Review Tickets</h4>
                </div>
                <div className="payment__items">
                    {/* all the selected products */}
                    {basket.map(item => (
                    <BookingProduct
                        id={item.id}
                        title={item.title}
                        image={item.image}
                        info={item.info}
                        price={item.price}
                        stock={item.stock}
                        nostock={item.nostock}
                        rating={item.rating}
                    />
                ))}
                </div>
            </div>

            {/* Payment Section => Payment Method */}
            <div className="payment__section">
                <div className="payment__title">
                    <h4>Payment Method</h4>
                </div>
                <div className="payment__details">
                    <p className='payment__card'>Card Details</p>
                    {/* Stripe Work for Payment */}
                    
                    <form onSubmit={handleSubmit}>
                        <CardElement onChange={handleChange}/>

                        <div className="payment__priceContainer">
                            <CurrencyFormat
                                renderText={(value) => (
                                    <h4>
                                        Booking Total: {value}
                                    </h4>
                                )}
                                decimalScale={2}
                                value={getBasketTotal(basket)}
                                displayType={"text"}
                                thousandSeparator={true}
                                prefix={"₹ "}
                            />

                            <button disabled={processing || disabled || succeeded}>
                                <span>
                                    {processing ? <p style={{color: 'green'}}>Processing</p> : <span style={{color: ''}}>Book Now</span>}
                                </span>
                            </button>
                        </div>

                        {/* Errors */}
                        {error && <div>{error}</div>}
                    </form>
                </div>
            </div>

        </div>
    </div>
  )
}

export default Payment

That's all.... if anything need kindly let me know. Thank You.

0

There are 0 best solutions below