189 lines
6.5 KiB
JavaScript
189 lines
6.5 KiB
JavaScript
// web/js/components/ItemCard.js
|
||
|
||
const ItemCard = ({
|
||
item,
|
||
onViewDetail,
|
||
onClaim,
|
||
onEdit,
|
||
onDelete,
|
||
onManualClaim,
|
||
currentUserId,
|
||
showActions = true,
|
||
isManager = false,
|
||
}) => {
|
||
const isOwnItem = currentUserId && item.reporter_id === currentUserId;
|
||
|
||
// ✅ FIX: Status logic yang lebih akurat
|
||
const isCaseClosed = item.status === "case_closed";
|
||
const isExpired = item.status === "expired";
|
||
const isVerified = item.status === "verified" || item.status === "completed";
|
||
const isPendingClaim = item.status === "pending_claim";
|
||
const isUnclaimed = item.status === "unclaimed";
|
||
|
||
// ✅ User hanya bisa claim jika unclaimed DAN bukan barang sendiri
|
||
const canClaim = isUnclaimed && !isOwnItem;
|
||
|
||
// ✅ Edit/Delete logic
|
||
let canEditOrDelete = false;
|
||
if (!isCaseClosed) {
|
||
if (isManager) {
|
||
canEditOrDelete = true;
|
||
} else {
|
||
canEditOrDelete = !isExpired;
|
||
}
|
||
}
|
||
const showEditButton = (isOwnItem || isManager) && canEditOrDelete;
|
||
|
||
// ✅ Improved status display text
|
||
const getStatusText = (status) => {
|
||
const statusMap = {
|
||
unclaimed: "Belum Diklaim",
|
||
pending_claim: "Sedang Diklaim",
|
||
verified: "Sudah Diklaim",
|
||
completed: "Selesai",
|
||
case_closed: "Kasus Ditutup",
|
||
expired: "Kadaluarsa",
|
||
};
|
||
return statusMap[status] || status;
|
||
};
|
||
|
||
return (
|
||
<div
|
||
className={`bg-gradient-to-br from-slate-800 to-slate-900 border-2 rounded-xl overflow-hidden hover:shadow-2xl transition-all cursor-pointer ${
|
||
isExpired
|
||
? "border-red-500/50 hover:border-red-500"
|
||
: "border-slate-700 hover:border-blue-500 hover:shadow-blue-500/20 hover:-translate-y-1"
|
||
}`}
|
||
>
|
||
{/* Expired Banner */}
|
||
{isExpired && (
|
||
<div className="absolute top-0 left-0 right-0 bg-red-600/90 text-white text-center py-1 text-xs font-bold z-10">
|
||
⚠️ EXPIRED - Manager Only View
|
||
</div>
|
||
)}
|
||
|
||
{/* Completed Banner - TAMBAHKAN INI */}
|
||
{isVerified && (
|
||
<div className="absolute top-0 left-0 right-0 bg-green-600/90 text-white text-center py-1 text-xs font-bold z-10">
|
||
✅ SUDAH DIKLAIM
|
||
</div>
|
||
)}
|
||
|
||
<img
|
||
src={
|
||
item.photo_url || "https://via.placeholder.com/280x200?text=No+Image"
|
||
}
|
||
alt={item.name}
|
||
className={`w-full h-48 object-cover ${isExpired ? "opacity-50" : ""} ${
|
||
isVerified ? "opacity-80" : ""
|
||
}`}
|
||
onClick={() => onViewDetail && onViewDetail(item)}
|
||
onError={(e) =>
|
||
(e.target.src = "https://via.placeholder.com/280x200?text=No+Image")
|
||
}
|
||
/>
|
||
|
||
<div className="p-4">
|
||
<h3 className="text-lg font-semibold text-white mb-2">{item.name}</h3>
|
||
|
||
<div className="flex flex-col gap-1 text-sm text-slate-400 mb-3">
|
||
<span>📍 {item.location}</span>
|
||
<span>📅 {Helpers.formatDate(item.date_found)}</span>
|
||
</div>
|
||
|
||
<div className="flex items-center justify-between mb-3">
|
||
<span
|
||
className={`px-3 py-1 rounded-full text-xs font-semibold ${Helpers.getStatusBadgeClass(
|
||
item.status
|
||
)}`}
|
||
>
|
||
{getStatusText(item.status)} {/* ✅ Better display */}
|
||
</span>
|
||
{isOwnItem && (
|
||
<span className="px-3 py-1 bg-green-500/20 text-green-400 text-xs font-semibold rounded-full border border-green-500/50">
|
||
Barang Anda
|
||
</span>
|
||
)}
|
||
</div>
|
||
|
||
{showActions && (
|
||
<div className="flex gap-2 flex-wrap">
|
||
{/* Detail Button */}
|
||
{onViewDetail && (
|
||
<button
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
onViewDetail(item);
|
||
}}
|
||
className="flex-1 px-3 py-2 bg-gradient-to-r from-blue-600 to-blue-700 text-white text-sm rounded-lg hover:from-blue-700 hover:to-blue-800 transition shadow-lg"
|
||
>
|
||
Detail
|
||
</button>
|
||
)}
|
||
|
||
{/* Manual Claim (Manager) */}
|
||
{onManualClaim && isUnclaimed && (
|
||
<button
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
onManualClaim(item);
|
||
}}
|
||
className="flex-1 px-3 py-2 bg-gradient-to-r from-green-600 to-green-700 text-white text-sm rounded-lg hover:from-green-700 hover:to-green-800 transition shadow-lg"
|
||
>
|
||
🤝 Klaim
|
||
</button>
|
||
)}
|
||
|
||
{/* User Claim - ✅ HANYA SHOW JIKA UNCLAIMED */}
|
||
{onClaim && canClaim && (
|
||
<button
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
onClaim(item);
|
||
}}
|
||
className="flex-1 px-3 py-2 bg-gradient-to-r from-green-600 to-green-700 text-white text-sm rounded-lg hover:from-green-700 hover:to-green-800 transition shadow-lg"
|
||
>
|
||
Klaim
|
||
</button>
|
||
)}
|
||
|
||
{/* Info untuk status pending */}
|
||
{isPendingClaim && !isOwnItem && (
|
||
<div className="flex-1 px-3 py-2 bg-yellow-600/20 text-yellow-400 text-xs rounded-lg border border-yellow-600/50 text-center">
|
||
⏳ Sedang diproses
|
||
</div>
|
||
)}
|
||
|
||
{/* Edit Button */}
|
||
{onEdit && showEditButton && (
|
||
<button
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
onEdit(item);
|
||
}}
|
||
className="flex-1 px-3 py-2 bg-gradient-to-r from-yellow-600 to-yellow-700 text-white text-sm rounded-lg hover:from-yellow-700 hover:to-yellow-800 transition shadow-lg"
|
||
>
|
||
Edit
|
||
</button>
|
||
)}
|
||
|
||
{/* Delete Button */}
|
||
{onDelete && canEditOrDelete && (
|
||
<button
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
if (confirm(`Yakin hapus "${item.name}"?`)) onDelete(item.id);
|
||
}}
|
||
className="px-3 py-2 bg-gradient-to-r from-red-600 to-red-700 text-white text-sm rounded-lg hover:from-red-700 hover:to-red-800 transition shadow-lg"
|
||
title="Hapus Barang"
|
||
>
|
||
🗑️
|
||
</button>
|
||
)}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|