155 lines
5.0 KiB
JavaScript
155 lines
5.0 KiB
JavaScript
import { useParams, Link, useNavigate } from "react-router-dom";
|
|
import {
|
|
useGetCouponByIdQuery,
|
|
useToggleCouponStatusMutation,
|
|
} from "../../features/coupons/couponAPI";
|
|
import { ArrowLeft, Percent, Calendar, Activity } from "lucide-react";
|
|
import { formatDate } from "../../utils/formatDate";
|
|
|
|
/* ---------- Status Badge ---------- */
|
|
const StatusBadge = ({ isActive }) => (
|
|
<span
|
|
className={`px-3 py-1 rounded-full text-xs font-semibold
|
|
${isActive ? "bg-green-100 text-green-700" : "bg-red-100 text-red-700"}`}
|
|
>
|
|
{isActive ? "ACTIVE" : "INACTIVE"}
|
|
</span>
|
|
);
|
|
|
|
/* ---------- Main Component ---------- */
|
|
const CouponDetails = () => {
|
|
const { id } = useParams();
|
|
const navigate = useNavigate();
|
|
|
|
const {
|
|
data: coupon,
|
|
isLoading,
|
|
isError,
|
|
} = useGetCouponByIdQuery(id, { skip: !id });
|
|
|
|
const [toggleCouponStatus, { isLoading: toggling }] =
|
|
useToggleCouponStatusMutation();
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="flex justify-center items-center h-64 text-gray-600">
|
|
Loading coupon details...
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (isError || !coupon) {
|
|
return (
|
|
<div className="text-center py-10 text-red-500">
|
|
Failed to load coupon details
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="max-w-7xl mx-auto p-6 space-y-6">
|
|
{/* Back Button */}
|
|
<div className="flex items-center gap-2 text-blue-600 hover:text-blue-800">
|
|
<ArrowLeft size={18} />
|
|
<button onClick={() => navigate(-1)} className="font-medium">
|
|
Back to Coupons
|
|
</button>
|
|
</div>
|
|
|
|
{/* Header Card */}
|
|
<div className="bg-white shadow-lg rounded-2xl p-6 flex flex-col md:flex-row justify-between items-start md:items-center gap-6">
|
|
<div>
|
|
<h2 className="text-2xl font-bold text-gray-800">{coupon.code}</h2>
|
|
<p className="text-gray-500">{coupon.description}</p>
|
|
<div className="mt-2">
|
|
<StatusBadge isActive={coupon.isActive} />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="text-right space-y-2">
|
|
<p className="text-2xl font-extrabold text-green-600">
|
|
{coupon.type === "PERCENTAGE"
|
|
? `${coupon.value}% OFF`
|
|
: `₹${coupon.value} OFF`}
|
|
</p>
|
|
|
|
<button
|
|
onClick={() => toggleCouponStatus(coupon.id)}
|
|
disabled={toggling}
|
|
className={`px-4 py-2 rounded-lg text-sm font-semibold transition
|
|
${
|
|
coupon.isActive
|
|
? "bg-red-100 text-red-700 hover:bg-red-200"
|
|
: "bg-green-100 text-green-700 hover:bg-green-200"
|
|
}`}
|
|
>
|
|
{coupon.isActive ? "Deactivate Coupon" : "Activate Coupon"}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Info Cards */}
|
|
<div className="grid md:grid-cols-3 gap-6">
|
|
{/* Discount */}
|
|
<div className="bg-gradient-to-r from-purple-50 to-purple-100 p-6 rounded-2xl shadow hover:shadow-lg transition">
|
|
<h3 className="text-gray-700 font-semibold mb-2 flex items-center gap-2">
|
|
<Percent size={16} /> Discount
|
|
</h3>
|
|
<p className="text-xl font-bold text-purple-700">
|
|
{coupon.type === "PERCENTAGE"
|
|
? `${coupon.value}%`
|
|
: `₹${coupon.value}`}
|
|
</p>
|
|
<p className="text-gray-600 text-sm">
|
|
Min Order: ₹{coupon.minOrderAmount}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Validity */}
|
|
<div className="bg-gradient-to-r from-blue-50 to-blue-100 p-6 rounded-2xl shadow hover:shadow-lg transition">
|
|
<h3 className="text-gray-700 font-semibold mb-2 flex items-center gap-2">
|
|
<Calendar size={16} /> Validity
|
|
</h3>
|
|
<p className="text-gray-800 text-sm">
|
|
From: {formatDate(coupon.validFrom)}
|
|
</p>
|
|
<p className="text-gray-800 text-sm">
|
|
Till: {formatDate(coupon.validUntil)}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Usage */}
|
|
<div className="bg-gradient-to-r from-green-50 to-green-100 p-6 rounded-2xl shadow hover:shadow-lg transition">
|
|
<h3 className="text-gray-700 font-semibold mb-2 flex items-center gap-2">
|
|
<Activity size={16} /> Usage
|
|
</h3>
|
|
<p className="text-xl font-bold text-green-700">
|
|
{coupon.usedCount}/{coupon.maxUses}
|
|
</p>
|
|
<p className="text-gray-600 text-sm">
|
|
Remaining: {coupon.remainingUses}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Extra Info */}
|
|
<div className="bg-white shadow-lg rounded-2xl p-6 text-sm text-gray-600 grid md:grid-cols-2 gap-4">
|
|
<div>
|
|
<b>Created At:</b> {formatDate(coupon.createdAt)}
|
|
</div>
|
|
<div>
|
|
<b>Last Updated:</b> {formatDate(coupon.updatedAt)}
|
|
</div>
|
|
<div>
|
|
<b>Expired:</b> {coupon.isExpired ? "Yes ❌" : "No ✅"}
|
|
</div>
|
|
<div>
|
|
<b>Not Started:</b> {coupon.isNotStarted ? "Yes ⏳" : "No"}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default CouponDetails;
|