|
| 1 | +So now we want to be able to handle the user's cart and submitting our order. Let's go add what we need to Order.jsx |
| 2 | + |
| 3 | +```javascript |
| 4 | +// add import |
| 5 | +import Cart from "./Cart"; |
| 6 | + |
| 7 | +// add another hook |
| 8 | +const [cart, setCart] = useState([]); |
| 9 | + |
| 10 | +// replace <form> |
| 11 | +<form |
| 12 | + onSubmit={(e) => { |
| 13 | + e.preventDefault(); |
| 14 | + setCart([...cart, { pizza: selectedPizza, size: pizzaSize, price }]); |
| 15 | + }} |
| 16 | +> |
| 17 | + […] |
| 18 | +</form>; |
| 19 | + |
| 20 | +// just inside the last closing div |
| 21 | +{ |
| 22 | + loading ? <h2>LOADING …</h2> : <Cart cart={cart} />; |
| 23 | +} |
| 24 | +``` |
| 25 | + |
| 26 | +So now we're using an onSubmit to handle the adding to cart. Awesome! Then we're passing that into Cart to have a nice display. |
| 27 | + |
| 28 | +Let's make the cart. Make a file called Cart.jsx and add |
| 29 | + |
| 30 | +```javascript |
| 31 | +const intl = new Intl.NumberFormat("en-US", { |
| 32 | + style: "currency", |
| 33 | + currency: "USD", // feel free to change to your local currency |
| 34 | +}); |
| 35 | + |
| 36 | +export default function Cart({ cart, checkout }) { |
| 37 | + let total = 0; |
| 38 | + for (let i = 0; i < cart.length; i++) { |
| 39 | + const current = cart[i]; |
| 40 | + total += current.pizza.sizes[current.size]; |
| 41 | + } |
| 42 | + return ( |
| 43 | + <div className="cart"> |
| 44 | + <h2>Cart</h2> |
| 45 | + <ul> |
| 46 | + {cart.map((item) => ( |
| 47 | + <li> |
| 48 | + <span className="size">{item.size}</span> – |
| 49 | + <span className="type">{item.pizza.name}</span> – |
| 50 | + <span className="price">{item.price}</span> |
| 51 | + </li> |
| 52 | + ))} |
| 53 | + </ul> |
| 54 | + <p>Total: {intl.format(total)}</p> |
| 55 | + <button onClick={checkout}>Checkout</button> |
| 56 | + </div> |
| 57 | + ); |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +Now we have a nice shopping cart experience. So how do actually checkout on the server? Let's do that! We probably want to do it as the Order level. It already has the Cart and we can just leave the Cart as a dumb display component. We can just pass a function to call into the Cart component and call it and run the function at the Order level. |
| 62 | + |
| 63 | +```javascript |
| 64 | +// inside the render body |
| 65 | +async function checkout() { |
| 66 | + setLoading(true); |
| 67 | + |
| 68 | + await fetch("/api/order", { |
| 69 | + method: "POST", |
| 70 | + headers: { |
| 71 | + "Content-Type": "application/json", |
| 72 | + }, |
| 73 | + body: JSON.stringify({ |
| 74 | + cart, |
| 75 | + }), |
| 76 | + }); |
| 77 | + |
| 78 | + setCart([]); |
| 79 | + setLoading(false); |
| 80 | +} |
| 81 | + |
| 82 | +// replace Cart |
| 83 | +<Cart checkout={checkout} cart={cart} />; |
| 84 | +``` |
| 85 | + |
| 86 | +Now we can pass that checkout function in and whenever someone clicks inside the form, it will run the checkout function from the Order components. We're doing a simple loading animation, doing a fetch, and then clearing the status once we're all done. Not too bad! |
0 commit comments