156 lines
5.0 KiB
TypeScript
156 lines
5.0 KiB
TypeScript
'use client';
|
||
|
||
import React, { useEffect, useState } from "react";
|
||
import { useRouter, useSearchParams } from "next/navigation";
|
||
import axios from "axios";
|
||
import IconXCircle from "@/components/icon/icon-x-circle";
|
||
|
||
interface PaymentDetails {
|
||
email: string;
|
||
amount: number;
|
||
planId: string;
|
||
stripeSessionId: string;
|
||
status: string;
|
||
created_at: string;
|
||
}
|
||
|
||
const PaymentFailure: React.FC = () => {
|
||
const [payment, setPayment] = useState<any>(null);
|
||
const [loading, setLoading] = useState(true);
|
||
const [error, setError] = useState<string | null>(null);
|
||
|
||
const router = useRouter();
|
||
const searchParams = useSearchParams();
|
||
const sessionId = searchParams.get("session_id"); // Stripe sends session_id in query
|
||
|
||
useEffect(() => {
|
||
if (!sessionId) {
|
||
setError("No session_id provided");
|
||
setLoading(false);
|
||
return;
|
||
}
|
||
|
||
const fetchPaymentDetails = async () => {
|
||
try {
|
||
const res:any = await axios.get(
|
||
`https://ebay.backend.data4autos.com/api/payment/details`,
|
||
{ params: { session_id: sessionId } }
|
||
);
|
||
setPayment(res.data.payment);
|
||
} catch (err: any) {
|
||
console.error(err);
|
||
setError(err.response?.data?.error || "Failed to fetch payment details");
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
fetchPaymentDetails();
|
||
}, [sessionId]);
|
||
|
||
if (loading) {
|
||
return (
|
||
<div className="flex items-center justify-center min-h-[83vh] text-gray-500">
|
||
Loading payment details...
|
||
</div>
|
||
);
|
||
}
|
||
|
||
if (error) {
|
||
return (
|
||
<div className="flex items-center justify-center min-h-[83vh] text-red-500">
|
||
{error}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className="flex flex-col items-center justify-center min-h-[83vh] bg-gradient-to-br from-red-50 via-white to-red-100 px-4">
|
||
{/* ❌ Error Icon */}
|
||
<div className="animate-bounce mb-6">
|
||
<IconXCircle className="w-24 h-24 text-red-500 drop-shadow-md" />
|
||
</div>
|
||
|
||
{/* ❌ Title */}
|
||
<h1 className="text-3xl font-bold text-gray-800 mb-2 text-center">
|
||
Payment Failed ❌
|
||
</h1>
|
||
|
||
{/* ❌ Subtitle */}
|
||
<p className="text-gray-600 mb-6 text-center max-w-md">
|
||
Unfortunately, your payment could not be processed. Please try again or
|
||
contact support if the issue persists.
|
||
</p>
|
||
|
||
{/* ❌ Card with Payment Details */}
|
||
<div className="bg-white shadow-lg rounded-2xl p-6 w-full max-w-md border border-gray-100 transition-transform duration-300 hover:scale-[1.02] space-y-3">
|
||
<div className="flex justify-between items-start">
|
||
<span className="text-gray-500">Transaction ID:</span>
|
||
<span className="font-semibold text-gray-800 break-all max-w-[60%]">
|
||
{payment?.stripeSessionId}
|
||
</span>
|
||
</div>
|
||
|
||
<div className="flex justify-between items-start">
|
||
<span className="text-gray-500">Email:</span>
|
||
<span className="font-semibold text-gray-800 break-words max-w-[60%]">
|
||
{payment?.email}
|
||
</span>
|
||
</div>
|
||
|
||
<div className="flex justify-between items-start">
|
||
<span className="text-gray-500">Plan:</span>
|
||
<span className="font-semibold text-gray-800 break-words max-w-[60%]">
|
||
{payment?.planId}
|
||
</span>
|
||
</div>
|
||
|
||
<div className="flex justify-between items-start">
|
||
<span className="text-gray-500">Amount:</span>
|
||
<span className="font-semibold text-gray-800 break-words max-w-[60%]">
|
||
${payment?.amount / 100}
|
||
</span>
|
||
</div>
|
||
|
||
<div className="flex justify-between items-start">
|
||
<span className="text-gray-500">Payment Status:</span>
|
||
<span className="font-semibold text-red-600 break-words max-w-[60%]">
|
||
{payment?.status}
|
||
</span>
|
||
</div>
|
||
|
||
<div className="flex justify-between items-start">
|
||
<span className="text-gray-500">Date:</span>
|
||
<span className="font-semibold text-gray-800 break-words max-w-[60%]">
|
||
{new Date(payment?.created_at || "").toLocaleString()}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* ❌ Buttons */}
|
||
<div className="mt-8 flex flex-col sm:flex-row gap-4">
|
||
<button
|
||
onClick={() => router.push("/pricing")}
|
||
className="bg-red-500 hover:bg-red-600 text-white px-6 py-3 rounded-xl shadow-md font-medium transition-all duration-200 hover:shadow-lg"
|
||
>
|
||
Retry Payment
|
||
</button>
|
||
|
||
<button
|
||
onClick={() => router.push("/support")}
|
||
className="bg-gray-200 hover:bg-gray-300 text-gray-800 px-6 py-3 rounded-xl shadow-md font-medium transition-all duration-200 hover:shadow-lg"
|
||
>
|
||
Contact Support
|
||
</button>
|
||
</div>
|
||
|
||
{/* ❌ Footer Text */}
|
||
<p className="mt-6 text-sm text-gray-400 text-center">
|
||
Don’t worry — no amount has been deducted from your account.
|
||
</p>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default PaymentFailure;
|