284 lines
12 KiB
JavaScript
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; |