Basdat/web/js/pages/admin/tabs/MyClaimTab.js
2025-12-20 00:01:08 +07:00

321 lines
13 KiB
JavaScript

const MyClaimsTab = ({ state, handlers }) => {
const { myLostItems, myClaims, loading } = state;
// Lost items dengan pending claims (untuk OWNER perspective)
const lostItemsWithClaims = myLostItems.filter(
(item) =>
item.direct_claim_id &&
item.direct_claim_status &&
item.status !== "completed" &&
item.direct_claim_status !== "completed"
);
const regularClaims = myClaims || [];
// Status badge untuk OWNER perspective (di section "Barang Hilang Saya")
const getOwnerStatusBadge = (status) => {
const badges = {
active: { color: "bg-blue-500", text: "🔍 Masih Hilang", emoji: "😢" },
claimed: {
color: "bg-yellow-500",
text: "⏳ Menunggu Persetujuan Anda",
emoji: "🤔",
},
found: { color: "bg-green-500", text: "✅ Ditemukan", emoji: "🎉" },
completed: {
color: "bg-purple-500",
text: "✅ Selesai - Barang Diterima",
emoji: "🎉",
},
waiting_owner: {
color: "bg-orange-500",
text: "⏳ Menunggu Keputusan Anda", // Owner yang harus decide
emoji: "🔔",
},
verified: {
color: "bg-green-600",
text: "✅ Terverifikasi",
emoji: "✅",
},
};
return (
badges[status] || {
color: "bg-gray-500",
text: status,
emoji: "❓",
}
);
};
// Status badge untuk CLAIMANT perspective (di section "Klaim yang Saya Ajukan")
const getClaimantStatusBadge = (status) => {
const badges = {
pending: {
color: "bg-yellow-500",
text: "⏳ Menunggu Verifikasi Admin",
emoji: "⏳",
},
approved: {
color: "bg-green-500",
text: "✅ Disetujui",
emoji: "✅",
},
rejected: {
color: "bg-red-500",
text: "❌ Ditolak",
emoji: "❌",
},
waiting_owner: {
color: "bg-orange-500",
text: "⏳ Menunggu Keputusan Pemilik", // Claimant menunggu owner
emoji: "💤",
},
verified: {
color: "bg-green-600",
text: "✅ Terverifikasi",
emoji: "✅",
},
completed: {
color: "bg-purple-500",
text: "🎉 Selesai",
emoji: "🎉",
},
};
return (
badges[status] || {
color: "bg-gray-500",
text: status,
emoji: "❓",
}
);
};
if (loading) {
return (
<div className="text-center py-12 text-slate-400">
<div className="animate-spin text-4xl mb-4"></div>
<p>Memuat data klaim...</p>
</div>
);
}
return (
<div className="space-y-8">
{/* SECTION 1: OWNER PERSPECTIVE - Barang Hilang Saya yang Ada Klaimnya */}
{lostItemsWithClaims.length > 0 && (
<div className="bg-slate-800/50 backdrop-blur-sm rounded-2xl border border-slate-700 p-6">
<h3 className="text-2xl font-bold text-white mb-4 flex items-center gap-3">
<span className="text-3xl">😢</span>
Barang Hilang Saya
<span className="bg-orange-500/20 text-orange-400 text-sm px-3 py-1 rounded-full border border-orange-500/30">
{lostItemsWithClaims.length} item dengan klaim pending
</span>
</h3>
<p className="text-slate-400 mb-6">
Ada yang menemukan barang Anda! Silakan approve atau reject klaim
mereka.
</p>
<div className="space-y-4">
{lostItemsWithClaims.map((lostItem) => {
const statusBadge = getOwnerStatusBadge(
lostItem.direct_claim_status || lostItem.status
);
const isWaitingOwner =
lostItem.direct_claim_status === "waiting_owner";
const isVerified =
lostItem.direct_claim_status === "verified" ||
lostItem.status === "found";
return (
<div
key={lostItem.id}
className={`bg-slate-900/80 rounded-xl border ${
isWaitingOwner
? "border-orange-500/50 shadow-lg shadow-orange-500/20"
: "border-slate-700"
} p-6 hover:shadow-xl transition-all`}
>
{/* Header dengan status */}
<div className="flex justify-between items-start mb-4">
<div className="flex-1">
<div className="flex items-center gap-3 mb-2">
<h4 className="text-xl font-bold text-white">
{lostItem.name}
</h4>
<span
className={`${statusBadge.color} text-white text-xs px-3 py-1 rounded-full font-medium`}
>
{statusBadge.emoji} {statusBadge.text}
</span>
</div>
<div className="space-y-1 text-sm text-slate-400">
<p>
<span className="font-medium">📦 Kategori:</span>{" "}
{lostItem.category}
</p>
{lostItem.color && (
<p>
<span className="font-medium">🎨 Warna:</span>{" "}
{lostItem.color}
</p>
)}
<p>
<span className="font-medium">📍 Lokasi Hilang:</span>{" "}
{lostItem.location}
</p>
<p>
<span className="font-medium">
📅 Tanggal Hilang:
</span>{" "}
{new Date(lostItem.date_lost).toLocaleDateString(
"id-ID"
)}
</p>
<p className="mt-2">
<span className="font-medium">📝 Deskripsi:</span>{" "}
{lostItem.description}
</p>
</div>
</div>
</div>
{/* Action Area untuk Owner */}
{isWaitingOwner && (
<div className="bg-orange-900/30 border border-orange-500/30 rounded-lg p-4 mt-4">
<p className="text-orange-300 font-semibold mb-3 flex items-center gap-2">
<span className="text-2xl">🔔</span>
Ada yang mengaku menemukan barang ini!
</p>
<p className="text-sm text-slate-300 mb-4">
Seseorang telah mengajukan klaim untuk barang ini.
Silakan putuskan apakah ini benar barang Anda.
</p>
<div className="flex gap-3">
<button
onClick={() =>
handlers.handleUserRespondClaim(
lostItem.direct_claim_id,
"approve"
)
}
className="flex-1 bg-gradient-to-r from-green-600 to-green-700 text-white px-4 py-3 rounded-lg font-semibold hover:from-green-700 hover:to-green-800 transition shadow-lg shadow-green-500/30"
>
Approve (Ini barang saya!)
</button>
<button
onClick={() =>
handlers.handleUserRespondClaim(
lostItem.direct_claim_id,
"reject"
)
}
className="flex-1 bg-gradient-to-r from-red-600 to-red-700 text-white px-4 py-3 rounded-lg font-semibold hover:from-red-700 hover:to-red-800 transition shadow-lg shadow-red-500/30"
>
Reject (Bukan barang saya)
</button>
</div>
</div>
)}
{isVerified && (
<div className="bg-green-900/30 border border-green-500/30 rounded-lg p-4 mt-4">
<p className="text-green-300 font-semibold mb-3 flex items-center gap-2">
<span className="text-2xl"></span>
Klaim Disetujui!
</p>
<p className="text-sm text-slate-300 mb-4">
Anda telah menyetujui bahwa penemu menemukan barang
Anda. Koordinasikan pengambilan barang, lalu konfirmasi
setelah menerima barang.
</p>
<button
onClick={() =>
handlers.handleUserCompleteCase(
lostItem.direct_claim_id
)
}
className="w-full bg-gradient-to-r from-purple-600 to-purple-700 text-white px-4 py-3 rounded-lg font-semibold hover:from-purple-700 hover:to-purple-800 transition shadow-lg shadow-purple-500/30"
>
🎉 Konfirmasi: Saya Sudah Terima Barang
</button>
</div>
)}
</div>
);
})}
</div>
</div>
)}
{/* SECTION 2: CLAIMANT PERSPECTIVE - Klaim yang Saya Ajukan */}
{regularClaims.length > 0 && (
<div className="bg-slate-800/50 backdrop-blur-sm rounded-2xl border border-slate-700 p-6">
<h3 className="text-2xl font-bold text-white mb-4 flex items-center gap-3">
<span className="text-3xl">🤝</span>
Klaim Barang yang Saya Ajukan
<span className="bg-blue-500/20 text-blue-400 text-sm px-3 py-1 rounded-full border border-blue-500/30">
{regularClaims.length} klaim
</span>
</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{regularClaims.map((claim) => {
const statusBadge = getClaimantStatusBadge(claim.status);
return (
<div
key={claim.id}
className="bg-slate-900/80 rounded-xl border border-slate-700 p-5 hover:shadow-xl transition-all"
>
<div className="flex items-start justify-between mb-3">
<h4 className="text-lg font-bold text-white flex-1">
{claim.item_name}
</h4>
<span
className={`${statusBadge.color} text-white text-xs px-3 py-1 rounded-full font-medium whitespace-nowrap ml-2`}
>
{statusBadge.emoji} {statusBadge.text}
</span>
</div>
<div className="space-y-2 text-sm text-slate-400">
<p>
<span className="font-medium">📝 Deskripsi:</span>{" "}
{claim.description}
</p>
<p>
<span className="font-medium">📞 Kontak:</span>{" "}
{claim.contact}
</p>
<p>
<span className="font-medium">📅 Tanggal Klaim:</span>{" "}
{new Date(claim.created_at).toLocaleDateString("id-ID")}
</p>
{claim.notes && (
<p className="text-yellow-400 mt-2">
<span className="font-medium">💬 Catatan:</span>{" "}
{claim.notes}
</p>
)}
</div>
</div>
);
})}
</div>
</div>
)}
{/* Empty State */}
{lostItemsWithClaims.length === 0 && regularClaims.length === 0 && (
<div className="text-center py-16 bg-slate-800/30 rounded-2xl border border-slate-700">
<div className="text-6xl mb-4">🔭</div>
<h3 className="text-xl font-bold text-white mb-2">Belum Ada Klaim</h3>
<p className="text-slate-400">
Anda belum memiliki klaim atau barang hilang dengan klaim pending.
</p>
</div>
)}
</div>
);
};
window.MyClaimsTab = MyClaimsTab;