Basdat/web/js/components/ClaimCard.js
2025-12-20 00:01:08 +07:00

259 lines
9.7 KiB
JavaScript

const ClaimCard = ({
claim,
onViewDetails,
onVerify,
onReopen,
onCancelApproval,
onUserRespond,
isOwnerView = false,
currentUserId,
}) => {
const getStatusClass = (status) => {
switch (status) {
case "approved":
case "verified":
return "bg-green-600 text-white border-green-500";
case "rejected":
return "bg-red-600 text-white border-red-500";
case "waiting_owner":
return "bg-yellow-600 text-white border-yellow-500";
default:
return "bg-slate-700 text-slate-300 border-slate-600";
}
};
const getStatusText = (status) => {
if (status === "waiting_owner") {
// Jika yang login adalah pemilik barang yang hilang
if (
claim.lost_item_user_id &&
currentUserId === claim.lost_item_user_id
) {
return "🔔 MENUNGGU ANDA";
}
// Jika yang login adalah penemu yang mengajukan klaim
if (claim.user_id && currentUserId === claim.user_id) {
return "⏳ MENUNGGU OWNER"; // Updated: Sesuai permintaan
}
return onUserRespond ? "🔔 MENUNGGU PEMILIK" : "⏳ MENUNGGU OWNER";
}
return status.toUpperCase();
};
const ActorBadge = ({ label, name, icon, color }) => (
<div
className={`flex items-center gap-1 text-xs ${color} bg-slate-950/30 px-2 py-1 rounded border border-slate-700`}
>
<span>{icon}</span>
<span className="opacity-70">{label}:</span>
<span className="font-semibold">{name}</span>
</div>
);
return (
<div className="bg-gradient-to-br from-slate-800 to-slate-900 border-2 border-slate-700 rounded-xl p-6 hover:shadow-2xl hover:shadow-blue-500/20 hover:border-blue-500 transition-all group flex flex-col h-full">
<div className="flex justify-between items-start mb-4 border-b border-slate-700 pb-3">
<div>
<h3 className="text-lg font-bold text-white group-hover:text-blue-400 transition">
{claim.item_name}
</h3>
<p className="text-xs text-slate-400 mt-1">
Pengklaim:{" "}
<span className="text-white font-medium">{claim.user_name}</span> {" "}
{claim.contact}
</p>
</div>
<div className="text-right">
<span
className={`px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider border ${getStatusClass(
claim.status
)}`}
>
{getStatusText(claim.status)}
</span>
{claim.match_percentage && (
<div
className={`text-xs font-bold mt-2 ${
claim.match_percentage >= 70
? "text-green-400"
: "text-yellow-400"
}`}
>
Match: {claim.match_percentage}%
</div>
)}
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4 flex-grow">
<div className="bg-slate-950/50 p-3 rounded-lg border border-slate-600 relative overflow-hidden">
<div className="absolute top-0 left-0 w-1 h-full bg-yellow-500"></div>
<p className="text-xs text-slate-500 mb-1 font-bold uppercase">
Ciri Rahasia (Dari Penemu)
</p>
<p className="text-sm text-slate-300 italic">
"{claim.item_secret_details || "Tidak ada data"}"
</p>
</div>
<div className="bg-slate-950/50 p-3 rounded-lg border border-slate-600 relative overflow-hidden">
<div className="absolute top-0 left-0 w-1 h-full bg-blue-500"></div>
<p className="text-xs text-slate-500 mb-1 font-bold uppercase">
Deskripsi Pengklaim
</p>
<p className="text-sm text-slate-300">"{claim.description}"</p>
</div>
</div>
{claim.status === "waiting_owner" &&
claim.lost_item_user_id &&
currentUserId === claim.lost_item_user_id && (
<div className="bg-blue-500/20 border border-blue-500/50 p-3 rounded-lg mb-4 text-center">
<p className="text-sm text-blue-200 font-semibold">
🔔 Seseorang menemukan barang ini dan mencocokkannya dengan Anda.
</p>
<p className="text-xs text-blue-300 mt-1">
Apakah benar ini barang Anda?
</p>
</div>
)}
{claim.status === "waiting_owner" &&
claim.user_id &&
currentUserId === claim.user_id && (
<div className="bg-yellow-500/20 border border-yellow-500/50 p-3 rounded-lg mb-4 text-center">
<p className="text-sm text-yellow-200 font-semibold">
Menunggu keputusan dari pemilik barang
</p>
<p className="text-xs text-yellow-300 mt-1">
Pemilik sedang memverifikasi apakah ini barang mereka
</p>
</div>
)}
<div className="space-y-2 mb-4 pt-3 border-t border-slate-700 border-dashed">
<div className="flex justify-between items-center">
<ActorBadge
label="Penemu"
name={claim.reporter_name || "Anonim"}
icon="📦"
color="text-slate-300"
/>
<span className="text-[10px] text-slate-500">
Ditemukan: {Helpers.formatDate(claim.created_at)}
</span>
</div>
{claim.verifier_name && (
<div className="flex justify-between items-center">
<ActorBadge
label={
claim.status === "rejected"
? "Ditolak Oleh"
: "Diverifikasi Oleh"
}
name={claim.verifier_name}
icon={claim.status === "rejected" ? "❌" : "✅"}
color={
claim.status === "rejected" ? "text-red-300" : "text-green-300"
}
/>
<span className="text-[10px] text-slate-500">
{Helpers.formatDateTime(claim.verified_at)}
</span>
</div>
)}
{claim.case_closed_by_name && (
<div className="flex justify-between items-center bg-purple-500/10 p-1 rounded mt-1">
<ActorBadge
label="Closed By"
name={claim.case_closed_by_name}
icon="🔒"
color="text-purple-300"
/>
<div className="text-right">
<span className="block text-[10px] text-purple-300/70 font-bold">
BA: {claim.berita_acara_no}
</span>
<span className="block text-[10px] text-purple-300/50">
{Helpers.formatDateTime(claim.case_closed_at)}
</span>
</div>
</div>
)}
</div>
<div className="flex items-center justify-end gap-2 mt-auto pt-2 border-t border-slate-700">
{onViewDetails && (
<button
onClick={onViewDetails}
className="px-3 py-2 bg-slate-700 hover:bg-slate-600 text-white text-sm rounded transition"
>
📋 Detail
</button>
)}
{claim.status === "waiting_owner" &&
claim.lost_item_user_id &&
currentUserId === claim.lost_item_user_id &&
onUserRespond && (
<div className="flex gap-2 w-full">
<button
onClick={() => onUserRespond(claim.id, "reject")}
className="flex-1 px-4 py-2 border border-red-500 text-red-400 hover:bg-red-500/10 rounded transition"
>
Bukan Punya Saya
</button>
<button
onClick={() => onUserRespond(claim.id, "approve")}
className="flex-1 px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded transition shadow-lg"
>
Ya, Benar
</button>
</div>
)}
{claim.status === "pending" && onVerify && (
<button
onClick={() => onVerify(claim)}
className="flex-1 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white text-sm rounded transition shadow-lg flex justify-center items-center gap-2"
>
<span>🔍</span> Verifikasi
</button>
)}
{claim.status === "approved" && !claim.berita_acara_no && (
<>
{onCancelApproval && (
<button
onClick={() => {
if (confirm("Yakin ingin membatalkan status Approved?"))
onCancelApproval(claim.id);
}}
className="px-3 py-2 border border-red-500 text-red-400 hover:bg-red-500/10 text-sm rounded transition"
title="Batalkan Approval"
>
🚫 Batal
</button>
)}
{onVerify && (
<button
onClick={() => onVerify(claim)}
className="flex-1 px-3 py-2 bg-green-600 hover:bg-green-700 text-white text-sm rounded transition shadow-lg flex justify-center items-center gap-2"
>
<span>🔒</span> Close Case
</button>
)}
</>
)}
{claim.status === "approved" && claim.berita_acara_no && onReopen && (
<button
onClick={() => onReopen(claim)}
className="flex-1 px-4 py-2 bg-yellow-600 hover:bg-yellow-700 text-white text-sm rounded transition shadow-lg flex justify-center items-center gap-2"
>
<span>🔄</span> Reopen Case
</button>
)}
</div>
</div>
);
};