Files
nobat724_front/app/payment/[uuid]/page.js
T

239 lines
9.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useEffect, useState } from "react";
import { useParams, useRouter } from "next/navigation";
import { request } from "@/services/response";
import Cookies from "js-cookie";
import Layout from "@/components/layout";
export default function PaymentDetailsPage() {
const params = useParams();
const router = useRouter();
const [payment, setPayment] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [paying, setPaying] = useState(false);
const handleRetryPayment = async () => {
if (!payment?.appointment_uuid) return;
setPaying(true);
try {
const res = await request.postAppointmentPayment({
appointment_uuid: payment.appointment_uuid,
gateway: payment.gateway || "mellat",
frontend_address: `${window.location.origin}/payment/result`,
});
const redirectUrl = res?.data?.redirect_url;
if (redirectUrl) {
window.location.href = redirectUrl;
} else {
setPaying(false);
}
} catch {
setPaying(false);
}
};
useEffect(() => {
// بررسی لاگین بودن کاربر
const userInfo = Cookies.get("userInfo");
if (!userInfo) {
router.push("/login");
return;
}
const fetchPaymentDetails = async () => {
try {
setLoading(true);
const response = await request.getPayment(params.uuid);
setPayment(response?.data?.data ?? null);
} catch (err) {
setError("خطا در دریافت اطلاعات پرداخت");
console.error("Payment fetch error:", err);
} finally {
setLoading(false);
}
};
if (params.uuid) {
fetchPaymentDetails();
}
}, [params.uuid, router]);
const getStatusLabel = (status) => {
const statusMap = {
pending: "در انتظار پرداخت",
success: "پرداخت موفق",
failed: "پرداخت ناموفق",
refunded: "مسترد شده",
};
return statusMap[status] || status;
};
const getStatusColor = (status) => {
const colorMap = {
pending: "text-yellow-600 bg-yellow-50",
success: "text-green-600 bg-green-50",
failed: "text-red-600 bg-red-50",
refunded: "text-gray-600 bg-gray-50",
};
return colorMap[status] || "text-gray-600 bg-gray-50";
};
const getPaymentMethodLabel = (method) => {
const methodMap = {
mellat: "بانک ملت",
sep: "سامان (سپ)",
mock: "درگاه آزمایشی",
};
return methodMap[method] || method;
};
const formatDate = (timestamp) => {
const date = new Date(parseInt(timestamp) * 1000);
return new Intl.DateTimeFormat("fa-IR", {
year: "numeric",
month: "long",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
}).format(date);
};
const formatAmount = (rials) => {
return new Intl.NumberFormat("fa-IR").format(parseInt(rials));
};
if (loading) {
return (
<Layout>
<div className="flex items-center justify-center min-h-screen">
<div className="flex flex-col items-center gap-4">
<div className="w-12 h-12 border-4 border-[#5559CE] border-t-transparent rounded-full animate-spin"></div>
<p className="text-[#3B3B3B] text-[16px]">در حال بارگذاری...</p>
</div>
</div>
</Layout>
);
}
if (error) {
return (
<Layout>
<div className="flex items-center justify-center min-h-screen">
<div className="bg-red-50 border border-red-200 rounded-lg p-6 max-w-md">
<p className="text-red-600 text-center">{error}</p>
</div>
</div>
</Layout>
);
}
if (!payment) {
return null;
}
return (
<Layout>
<div className="container mx-auto px-4 py-8 max-w-4xl mt-20 md:mt-24">
<div className="bg-white rounded-lg shadow-md border border-gray-200 p-6 md:p-8">
<h1 className="text-2xl md:text-3xl font-bold text-[#3B3B3B] mb-6">
جزئیات پرداخت
</h1>
<div className="space-y-4">
{/* وضعیت پرداخت */}
<div className="flex justify-between items-center py-3 border-b border-gray-100">
<span className="text-[#616161] font-medium">وضعیت:</span>
<span
className={`px-4 py-2 rounded-full font-bold ${getStatusColor(
payment.status
)}`}
>
{getStatusLabel(payment.status)}
</span>
</div>
{/* مبلغ */}
<div className="flex justify-between items-center py-3 border-b border-gray-100">
<span className="text-[#616161] font-medium">مبلغ:</span>
<span className="text-[#3B3B3B] font-bold text-lg">
{formatAmount(payment.amount_rials)} ریال
</span>
</div>
{/* روش پرداخت */}
<div className="flex justify-between items-center py-3 border-b border-gray-100">
<span className="text-[#616161] font-medium">روش پرداخت:</span>
<span className="text-[#3B3B3B] font-bold">
{getPaymentMethodLabel(payment.gateway)}
</span>
</div>
{/* شناسه پرداخت */}
<div className="flex justify-between items-center py-3 border-b border-gray-100">
<span className="text-[#616161] font-medium">شناسه پرداخت:</span>
<span className="text-[#3B3B3B] font-mono text-sm">
{payment.uuid}
</span>
</div>
{/* شماره مرجع */}
{payment.reference_id && (
<div className="flex justify-between items-center py-3 border-b border-gray-100">
<span className="text-[#616161] font-medium">شماره مرجع:</span>
<span className="text-[#3B3B3B] font-bold">
{payment.reference_id}
</span>
</div>
)}
{/* تاریخ ایجاد */}
<div className="flex justify-between items-center py-3 border-b border-gray-100">
<span className="text-[#616161] font-medium">تاریخ ایجاد:</span>
<span className="text-[#3B3B3B]">
{formatDate(payment.created_at)}
</span>
</div>
{/* نوع سرویس */}
<div className="flex justify-between items-center py-3">
<span className="text-[#616161] font-medium">نوع سرویس:</span>
<span className="text-[#3B3B3B] font-bold">
{payment.type === "appointment" ? "رزرو نوبت" : payment.type}
</span>
</div>
</div>
{/* دکمه‌ها */}
<div className="mt-8 flex gap-4">
{payment.status === "pending" ? (
<>
<button
onClick={handleRetryPayment}
disabled={paying || !payment.appointment_uuid}
className="flex-1 bg-[#5559CE] hover:bg-[#4448b3] disabled:opacity-60 text-white font-bold py-3 px-6 rounded-lg transition-colors"
>
{paying ? "در حال انتقال به درگاه..." : "پرداخت"}
</button>
<button
onClick={() => window.location.reload()}
className="flex-1 bg-gray-200 hover:bg-gray-300 text-[#3B3B3B] font-bold py-3 px-6 rounded-lg transition-colors"
>
بروزرسانی وضعیت
</button>
</>
) : null}
<button
onClick={() => router.push("/dashboard?sidebar=2")}
className="flex-1 bg-[#5559CE] hover:bg-[#4448b3] text-white font-bold py-3 px-6 rounded-lg transition-colors"
>
بازگشت به تراکنشها
</button>
</div>
</div>
</div>
</Layout>
);
}