'Unable to get back the Order Details from Firebase 9
I am trying to make an Amazon Clone. I am at the last stage of Displaying the final order after payment confirmation from Stripe. Everything is working perfectly except that I am unable to get the order details back from firebase. I will be grateful for any help. thank You.
I have added the payment.js and order.js file. Also I have attached the image of the firebase structure. The structure looks like this db-- "Users"-- user?.uid--"orders". And I want to sort the order by date.
///This is my Orders.js file
import React, { useState, useEffect } from "react";
import { db } from "./firebase";
import "./Orders.css";
import { useStateValue } from "./StateProvider";
import Order from "./Order";
import {
getDoc,
onSnapshot,
collection,
getDocs,
doc,
addDoc,
setDoc,
updateDoc,
serverTimestamp,
} from "firebase/firestore";
import { query, orderBy, limit } from "firebase/firestore";
function Orders() {
const [{ basket, user }, dispatch] = useStateValue();
const [orders, setOrders] = useState([]);
useEffect(() => {
if (user) {
async function fetchData() {
const q = query(
collection(db, "Users", user?.uid, "orders"),
orderBy("createdAt", "desc")
);
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
setOrders({ ...doc.data(), id: doc.id });
});
}
} else {
setOrders([]);
console.log(setOrders);
}
}, [user]);
return (
<div className="orders">
<h1>Your Orders is Here</h1>
<div className="orders__order">
{orders?.map((order) => (
<Order order={order} />
))}
</div>
</div>
);
}
export default Orders;
///This is payment.js where I am pushing the order details to the firebase database. I am successful in updating the database
import React, { useState, useEffect } from "react";
import "./Payment.css";
import { useStateValue } from "./StateProvider";
import CheckoutProduct from "./CheckoutProduct";
import { Link, useNavigate } from "react-router-dom";
import { CardElement, useStripe, useElements } from "@stripe/react-stripe-js";
import CurrencyFormat from "react-currency-format";
import { getBasketTotal } from "./reducer";
import axios from "./axios";
// import { db } from "./firebase";
import {
getFirestore,
doc,
addDoc,
getDoc,
getDocs,
setDoc,
updateDoc,
} from "firebase/firestore";
import { db, collection, auth, firebaseApp } from "./firebase";
function Payment() {
const [{ basket, user }, dispatch] = useStateValue();
const history = useNavigate();
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
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 the fancy stripe stuff...
event.preventDefault();
setProcessing(true);
const payload = await stripe
.confirmCardPayment(clientSecret, {
payment_method: {
card: elements.getElement(CardElement),
},
})
.then(async ({ paymentIntent }) => {
// paymentIntent = payment confirmation
const colRef = doc(db, "Users", user?.uid, "orders", paymentIntent.id);
const gameSnap = await getDoc(colRef);
const game = gameSnap.data();
setDoc(
colRef,
{
basket: basket,
amount: paymentIntent.amount,
created: paymentIntent.created,
},
{ merge: true }
);
setSucceeded(true);
setError(null);
setProcessing(false);
dispatch({
type: "EMPTY_BASKET",
});
history("/orders", { replace: true });
});
};
const handleChange = (event) => {
// 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">
<h1>
Checkout (<Link to="/checkout">{basket?.length} items</Link>)
</h1>
{/* Payment section - delivery address */}
<div className="payment__section">
<div className="payment__title">
<h3>Delivery Address</h3>
</div>
<div className="payment__address">
<p>{user?.email}</p>
<p>123 React Lane</p>
<p>Los Angeles, CA</p>
</div>
</div>
{/* Payment section - Review Items */}
<div className="payment__section">
<div className="payment__title">
<h3>Review items and delivery</h3>
</div>
<div className="payment__items">
{basket.map((item) => (
<CheckoutProduct
id={item.id}
title={item.title}
image={item.image}
price={item.price}
rating={item.rating}
/>
))}
</div>
</div>
{/* Payment section - Payment method */}
<div className="payment__section">
<div className="payment__title">
<h3>Payment Method</h3>
</div>
<div className="payment__details">
{/* Stripe magic will go */}
<form onSubmit={handleSubmit}>
<CardElement onChange={handleChange} />
<div className="payment__priceContainer">
<CurrencyFormat
renderText={(value) => <h3>Order Total: {value}</h3>}
decimalScale={2}
value={getBasketTotal(basket)}
displayType={"text"}
thousandSeparator={true}
prefix={"$"}
/>
<button disabled={processing || disabled || succeeded}>
<span>{processing ? <p>Processing</p> : "Buy Now"}</span>
</button>
</div>
{/* Errors */}
{error && <div>{error}</div>}
</form>
</div>
</div>
</div>
</div>
);
}
export default Payment;
// This is my order.js where I am trying to use the data pulled from firebase.
import React from "react";
import "./Order.css";
import moment from "moment";
import CheckoutProduct from "./CheckoutProduct";
import CurrencyFormat from "react-currency-format";
function Order({ order }) {
return (
<div className="order">
<h2>Order </h2>
<p>{moment.unix(order.data.created).format("MMMM Do YYYY, h:mma")}</p>
<p className="order__id">
<small>{order.id}</small>
</p>
{order.data.basket?.map((item) => (
<CheckoutProduct
id={item.id}
title={item.title}
image={item.image}
price={item.price}
rating={item.rating}
hideButton
/>
))}
<CurrencyFormat
renderText={(value) => (
<h3 className="order__total">Order Total: {value}</h3>
)}
decimalScale={2}
value={order.data.amount / 100}
displayType={"text"}
thousandSeparator={true}
prefix={"$"}
/>
</div>
);
}
export default Order;

Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
