我正在做一个项目,我想在购物篮/购物车上添加一些很酷的功能。就像在购物篮中添加一些东西后,我想通过单击复选框按钮在购物篮本身中添加更多东西,它会展开更多项目,然后单击添加按钮,该项目将直接添加到同一个购物篮中。并且购物车价值会动态更新。
就是这样。我知道为此可能有很多事情要做。因此,如果有人能像任何现有项目或作品一样给我一些解决方案或建议或参考——所有这些都会对我有很大帮助。请指导我。
我正在添加我的购物篮和付款代码我已经完成了。
预订.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
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'}}>₹ </small>
<strong style={{fontSize: 14 ,fontWeight: 100}}>{price}</strong>
<p className="bookingProduct__stock">
{/* {stock} */}
<small style={{color: "green"}}> {stock}</small>
<small style={{color: "darkred"}}>{nostock} </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
就是这样....如果有任何需要请告诉我。谢谢你。