Comments, appointments adjustments, fixed some issues
This commit is contained in:
@@ -13,8 +13,10 @@ import {
|
||||
} from "@stripe/react-stripe-js";
|
||||
import { apiCompleteCheckout } from "@/lib/cartApi";
|
||||
|
||||
//Initializes Stripe with the publishable key
|
||||
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY || "");
|
||||
|
||||
//Stripe payment form shown after the user clicks checkout
|
||||
function PaymentForm({ clientSecret, totalAmount, onSuccess, onCancel }) {
|
||||
const stripe = useStripe();
|
||||
const elements = useElements();
|
||||
@@ -22,6 +24,7 @@ function PaymentForm({ clientSecret, totalAmount, onSuccess, onCancel }) {
|
||||
const [paying, setPaying] = useState(false);
|
||||
const [payError, setPayError] = useState(null);
|
||||
|
||||
//Confirms the payment with Stripe, then tells the backend to complete the order
|
||||
async function handlePay(e) {
|
||||
e.preventDefault();
|
||||
if (!stripe || !elements) return;
|
||||
@@ -57,9 +60,6 @@ function PaymentForm({ clientSecret, totalAmount, onSuccess, onCancel }) {
|
||||
<p className="text-[0.95rem] text-[#555] m-0">
|
||||
Total to pay: <strong>${parseFloat(totalAmount).toFixed(2)}</strong>
|
||||
</p>
|
||||
<div className="bg-[#fffbeb] border border-[#fde68a] rounded-lg px-4 py-3 text-[0.82rem] text-[#854d0e] flex flex-col gap-1">
|
||||
<div><strong>Demo mode</strong> — no real charge. Use test card: <span className="font-mono font-bold">4242 4242 4242 4242</span> · any future date · any 3-digit CVC</div>
|
||||
</div>
|
||||
<PaymentElement />
|
||||
{payError && <p className="bg-[#fff0f0] border border-[#f5c6c6] text-[#c0392b] rounded-lg px-4 py-3 text-[0.9rem] m-0">{payError}</p>}
|
||||
<div className="flex gap-3 mt-2">
|
||||
@@ -79,6 +79,7 @@ function PaymentForm({ clientSecret, totalAmount, onSuccess, onCancel }) {
|
||||
);
|
||||
}
|
||||
|
||||
//Cart page - shows items, coupons, loyalty points, order summary, and checkout
|
||||
export default function CartPage() {
|
||||
const { user, loading: authLoading, refreshUser } = useAuth();
|
||||
const {
|
||||
@@ -114,12 +115,14 @@ export default function CartPage() {
|
||||
|
||||
const [localQuantities, setLocalQuantities] = useState({});
|
||||
|
||||
//Redirect unauthenticated users to login
|
||||
useEffect(() => {
|
||||
if (!authLoading && !user) {
|
||||
router.push("/login");
|
||||
}
|
||||
}, [authLoading, user, router]);
|
||||
|
||||
//Sync local quantity inputs whenever the cart updates from the server
|
||||
useEffect(() => {
|
||||
if (cart?.items) {
|
||||
const map = {};
|
||||
@@ -129,12 +132,14 @@ export default function CartPage() {
|
||||
setOptimisticPointsApplied(null);
|
||||
}, [cart]);
|
||||
|
||||
//Cancel any leftover pending checkout if the page loads without a client secret
|
||||
useEffect(() => {
|
||||
if (cart?.checkoutPending && !clientSecret) {
|
||||
cancelCheckout().catch(() => {});
|
||||
}
|
||||
}, [cart?.checkoutPending, clientSecret, cancelCheckout]);
|
||||
|
||||
//Updates item quantity and rolls back the change if the request fails
|
||||
async function handleQuantityChange(cartItemId, newQty) {
|
||||
if (newQty < 1) return;
|
||||
setLocalQuantities((prev) => ({ ...prev, [cartItemId]: newQty }));
|
||||
@@ -158,6 +163,7 @@ export default function CartPage() {
|
||||
catch {}
|
||||
}
|
||||
|
||||
//Applies the typed coupon code and shows the discount type and amount
|
||||
async function handleApplyCoupon() {
|
||||
if (!couponInput.trim()) return;
|
||||
setCouponLoading(true);
|
||||
@@ -212,6 +218,8 @@ export default function CartPage() {
|
||||
}
|
||||
}
|
||||
|
||||
//Starts checkout
|
||||
//Either gets a Stripe client secret for payment or marks the order complete directly
|
||||
async function handleCheckout() {
|
||||
if (!cart?.items?.length) return;
|
||||
setCheckoutLoading(true);
|
||||
@@ -497,7 +505,7 @@ export default function CartPage() {
|
||||
)}
|
||||
|
||||
{clientSecret && (
|
||||
<Elements stripe={stripePromise} options={{ clientSecret }}>
|
||||
<Elements stripe={stripePromise} options={{ clientSecret, wallets: { link: "never" } }}>
|
||||
<PaymentForm
|
||||
clientSecret={clientSecret}
|
||||
totalAmount={checkoutTotal ?? cart.totalAmount}
|
||||
|
||||
Reference in New Issue
Block a user