259 lines
9.7 KiB
JavaScript
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>
|
|
);
|
|
};
|