Basdat/web/js/pages/user/UserTabsMy.js
2025-12-20 00:01:08 +07:00

284 lines
12 KiB
JavaScript

// assets/js/pages/user/UserTabsMy.js
const MyLostItemsTab = ({ state, handlers, myClaims }) => {
const { myLostItems, loading } = state;
const { handleUserRespondClaim, handleUserCompleteCase, loadData } = handlers;
// ✅ PERBAIKAN: Gunakan lost_item_id yang dikirim backend, jangan pakai Regex deskripsi
const findMatchingClaim = (lostItemId) => {
if (!myClaims || myClaims.length === 0) return null;
// Cari claim yang memiliki lost_item_id sama dengan item ini
// DAN statusnya relevan (menunggu owner, approved/verified)
return myClaims.find((c) => c.lost_item_id === lostItemId);
};
return (
<div className="bg-gradient-to-br from-slate-800 to-slate-900 rounded-xl p-6 shadow-xl border border-slate-700">
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-semibold text-white">Barang Hilang Saya</h2>
<div className="flex gap-2">
<button
onClick={() => loadData()}
className="px-4 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-600 transition border border-slate-600"
>
🔄 Refresh
</button>
<button
onClick={() => state.setShowReportLostModal(true)}
className="px-4 py-2 bg-gradient-to-r from-blue-600 to-blue-700 text-white rounded-lg hover:from-blue-700 hover:to-blue-800 transition shadow-lg"
>
+ Lapor Kehilangan
</button>
</div>
</div>
{loading ? (
<div className="text-center py-12 text-slate-400">
<div className="text-6xl mb-4 animate-pulse"></div>Memuat data...
</div>
) : myLostItems.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{myLostItems.map((item) => {
// ✅ PERBAIKAN UTAMA: Ambil klaim langsung dari objek item (dikirim backend)
// Bukan mencari dari list myClaims
const matchingClaim = item.direct_claim;
return (
<div
key={item.id}
className={`bg-gradient-to-br from-slate-700 to-slate-800 border-2 rounded-xl p-4 transition-all ${
matchingClaim
? "border-yellow-500 shadow-yellow-500/20"
: "border-slate-600"
}`}
>
<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">
{/* Tampilkan Badge Status Item */}
<span
className={`px-2 py-1 rounded text-xs font-bold w-fit ${Helpers.getStatusBadgeClass(
item.status
)}`}
>
{item.status.replace("_", " ").toUpperCase()}
</span>
</div>
{/* --- LOGIKA TOMBOL APPROVE/REJECT --- */}
{matchingClaim && (
<div className="mt-3 p-3 rounded-lg border bg-slate-900/50 border-slate-600">
{/* KASUS 1: STATUS WAITING_OWNER (Munculkan Tombol) */}
{matchingClaim.status === "waiting_owner" && (
<>
<div className="mb-3">
<p className="text-yellow-400 text-xs font-bold flex items-center gap-1 mb-1">
🔔 DITEMUKAN OLEH:{" "}
{matchingClaim.reporter_name || "Seseorang"}
</p>
<p className="text-xs text-slate-300 italic">
"{matchingClaim.description}"
</p>
</div>
<div className="flex gap-2">
<button
onClick={() =>
handleUserRespondClaim(matchingClaim.id, "reject")
}
className="flex-1 py-2 bg-red-900/30 text-red-400 border border-red-500/30 rounded hover:bg-red-600 hover:text-white text-xs font-bold transition"
>
Tolak
</button>
<button
onClick={() =>
handleUserRespondClaim(
matchingClaim.id,
"approve"
)
}
className="flex-1 py-2 bg-green-600 hover:bg-green-700 text-white rounded text-xs font-bold shadow-lg transition"
>
Terima Barang
</button>
</div>
</>
)}
{/* KASUS 2: STATUS VERIFIED (Munculkan Tombol Selesai) */}
{(matchingClaim.status === "verified" ||
matchingClaim.status === "approved") && (
<>
<p className="text-green-400 text-xs font-bold mb-2">
SUDAH ANDA SETUJUI
</p>
<p className="text-xs text-slate-400 mb-3">
Hubungi: {matchingClaim.contact}
</p>
<button
onClick={() =>
handleUserCompleteCase(matchingClaim.id)
}
className="w-full py-2 bg-blue-600 hover:bg-blue-700 text-white rounded text-xs font-bold transition"
>
📦 Barang Sudah Diterima (Selesai)
</button>
</>
)}
{/* KASUS 3: STATUS REJECTED */}
{matchingClaim.status === "rejected" && (
<p className="text-red-400 text-xs font-bold text-center">
KLAIM DITOLAK
</p>
)}
</div>
)}
</div>
);
})}
</div>
) : (
<div className="text-center text-slate-400 py-8">
Belum ada laporan kehilangan.
</div>
)}
</div>
);
};
const MyFoundItemsTab = ({ state, handlers }) => {
const { myFoundItems, loading, user } = state;
const { handleViewDetail } = handlers;
return (
<div className="bg-gradient-to-br from-slate-800 to-slate-900 rounded-xl p-6 shadow-xl border border-slate-700">
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-semibold text-white">
Barang yang Saya Temukan
</h2>
<button
onClick={() => state.setShowReportFoundModal(true)}
className="px-4 py-2 bg-gradient-to-r from-green-600 to-green-700 text-white rounded-lg hover:from-green-700 hover:to-green-800 transition shadow-lg"
>
+ Lapor Penemuan
</button>
</div>
{loading ? (
<div className="text-center py-12 text-slate-400">
<div className="text-6xl mb-4 animate-pulse"></div>
<p>Memuat data...</p>
</div>
) : myFoundItems.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{myFoundItems.map((item) => (
<div key={item.id} className="relative">
<ItemCard
item={item}
currentUserId={user?.id}
onViewDetail={handleViewDetail}
showActions={true}
/>
{/* --- TAMBAHAN VISUAL UNTUK STATUS --- */}
{/* Jika status Pending Claim (Menunggu Pemilik/Admin) */}
{item.status === "pending_claim" && (
<div className="mt-2 bg-yellow-500/10 border border-yellow-500/30 p-2 rounded-lg text-center">
<p className="text-xs text-yellow-400 font-semibold">
Menunggu Konfirmasi
</p>
<p className="text-[10px] text-slate-400">
Menunggu pemilik asli atau admin memverifikasi.
</p>
</div>
)}
{/* Jika status Verified (Sudah Diapprove) */}
{item.status === "verified" && (
<div className="mt-2 bg-green-500/10 border border-green-500/30 p-2 rounded-lg text-center">
<p className="text-xs text-green-400 font-semibold">
Terverifikasi
</p>
<p className="text-[10px] text-slate-400">
Pemilik telah mengonfirmasi. Silakan serahkan barang.
</p>
</div>
)}
{/* Jika status Case Closed (Selesai) */}
{item.status === "case_closed" && (
<div className="mt-2 bg-blue-500/10 border border-blue-500/30 p-2 rounded-lg text-center">
<p className="text-xs text-blue-400 font-semibold">
🏁 Kasus Selesai
</p>
<p className="text-[10px] text-slate-400">
Barang telah dikembalikan. Terima kasih!
</p>
</div>
)}
</div>
))}
</div>
) : (
<div className="text-center py-12 text-slate-400">
<div className="text-6xl mb-4">🎉</div>
<p>Anda belum melaporkan barang temuan</p>
<button
onClick={() => state.setShowReportFoundModal(true)}
className="mt-4 px-6 py-2 bg-gradient-to-r from-green-600 to-green-700 text-white rounded-lg hover:from-green-700 hover:to-green-800 transition shadow-lg"
>
Lapor Sekarang
</button>
</div>
)}
</div>
);
};
const MyClaimsTab = ({ state, handlers }) => {
const { myClaims, loading } = state;
const { handleUserRespondClaim } = handlers;
return (
<div className="bg-gradient-to-br from-slate-800 to-slate-900 rounded-xl p-6 shadow-xl border border-slate-700">
<h2 className="text-xl font-semibold mb-6 text-white">
Klaim Saya & Konfirmasi
</h2>
{loading ? (
<div className="text-center py-12 text-slate-400">
<div className="text-6xl mb-4"></div>
<p>Memuat data...</p>
</div>
) : myClaims.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{myClaims.map((claim) => (
<ClaimCard
key={claim.id}
claim={claim}
onUserRespond={handleUserRespondClaim}
/>
))}
</div>
) : (
<div className="text-center py-12 text-slate-400">
<div className="text-6xl mb-4">🤝</div>
<p>Anda belum memiliki riwayat klaim</p>
<button
onClick={() => state.setActiveTab("browse")}
className="mt-4 px-6 py-2 bg-gradient-to-r from-blue-600 to-blue-700 text-white rounded-lg hover:from-blue-700 hover:to-blue-800 transition shadow-lg"
>
Lihat Barang Ditemukan
</button>
</div>
)}
</div>
);
};
window.MyLostItemsTab = MyLostItemsTab;
window.MyFoundItemsTab = MyFoundItemsTab;
window.MyClaimsTab = MyClaimsTab;