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

469 lines
17 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// assets/js/pages/manager/ManagerModals.js
const DetailModal = ({ isOpen, onClose, item }) => (
<Modal isOpen={isOpen} onClose={onClose} title="Detail Barang">
{item && (
<div>
<img
src={item.photo_url || "https://via.placeholder.com/600x400"}
alt={item.name}
className="w-full h-64 object-cover rounded-xl mb-4 border-2 border-slate-600"
/>
<h3 className="text-2xl font-bold mb-4 text-white">{item.name}</h3>
<div className="space-y-3 text-slate-300">
<div className="bg-slate-700/50 p-3 rounded-lg">
<strong className="text-blue-400">Kategori:</strong>
<span className="ml-2">
{item.category ||
Helpers.getCategoryName(item.category_id) ||
"Tidak ada data"}
</span>
</div>
<div className="bg-slate-700/50 p-3 rounded-lg">
<strong className="text-blue-400">Lokasi:</strong>
<span className="ml-2">{item.location || "Tidak ada data"}</span>
</div>
<div className="bg-slate-700/50 p-3 rounded-lg">
<strong className="text-blue-400">Tanggal Ditemukan:</strong>
<span className="ml-2">
{Helpers.formatDate(item.date_found) || "Tidak ada data"}
</span>
</div>
<div className="bg-slate-700/50 p-3 rounded-lg">
<strong className="text-blue-400">Status:</strong>
<span
className={`ml-2 px-3 py-1 rounded-full text-xs font-semibold ${Helpers.getStatusBadgeClass(
item.status
)}`}
>
{item.status || "Tidak ada data"}
</span>
</div>
<div className="bg-slate-700/50 p-3 rounded-lg">
<strong className="text-blue-400">Deskripsi Umum:</strong>
<p className="text-slate-300 mt-2">
{item.description || "Tidak ada deskripsi"}
</p>
</div>
<div className="bg-slate-700/50 p-3 rounded-lg">
<strong className="text-blue-400">Pelapor:</strong>
<span className="ml-2">
{item.reporter_name || "Tidak ada data"}
</span>
</div>
<div className="bg-slate-700/50 p-3 rounded-lg">
<strong className="text-blue-400">Kontak Pelapor:</strong>
<span className="ml-2">
{item.reporter_contact || "Tidak ada data"}
</span>
</div>
<div className="bg-yellow-500/10 border-2 border-yellow-500/30 p-4 rounded-xl">
<div className="flex items-center gap-2 mb-2">
<span className="text-2xl">🔒</span>
<strong className="text-yellow-400 text-lg">
Ciri Khusus Rahasia (Untuk Verifikasi)
</strong>
</div>
<p className="text-slate-300 leading-relaxed">
{item.secret_details || "Tidak ada deskripsi rahasia"}
</p>
<p className="text-xs text-yellow-400 mt-2">
Info ini RAHASIA - gunakan untuk verifikasi klaim
</p>
</div>
</div>
</div>
)}
</Modal>
);
const VerifyClaimModal = ({
isOpen,
onClose,
claim,
onApprove,
onReject,
onCloseCase,
}) => (
<Modal
isOpen={isOpen}
onClose={onClose}
title="Verifikasi Klaim"
size="large"
>
{claim && (
<div>
<div className="grid grid-cols-2 gap-6 mb-6">
<div className="bg-blue-500/10 p-4 rounded-xl border border-blue-500/30">
<h4 className="font-semibold mb-3 text-blue-400">
Deskripsi Asli Barang (Rahasia)
</h4>
<p className="text-sm text-slate-300 font-medium">
{claim.item_secret_details || "Tidak ada ciri khusus rahasia"}
</p>
<div className="mt-3 pt-3 border-t border-slate-600/50">
<span className="text-xs text-slate-500 uppercase">
Deskripsi Umum:
</span>
<p className="text-xs text-slate-400">{claim.item_description}</p>
</div>
</div>
<div className="bg-yellow-500/10 p-4 rounded-xl border border-yellow-500/30">
<h4 className="font-semibold mb-3 text-yellow-400">
Deskripsi dari Pengklaim
</h4>
<p className="text-sm text-slate-300">{claim.description}</p>
</div>
</div>
{claim.match_percentage && (
<div
className={`p-6 rounded-xl text-center mb-6 ${
claim.match_percentage >= 70
? "bg-green-500/10 border border-green-500/30"
: "bg-yellow-500/10 border border-yellow-500/30"
}`}
>
<strong className="text-slate-300">Similarity Match:</strong>
<div
className={`text-4xl font-bold mt-2 ${
claim.match_percentage >= 70
? "text-green-400"
: "text-yellow-400"
}`}
>
{claim.match_percentage}%
</div>
</div>
)}
<div className="bg-slate-900/50 p-4 rounded-xl mb-6 border border-slate-700">
<strong className="text-slate-300">Info Pengklaim:</strong>
<div className="mt-2 space-y-1 text-slate-400">
<div>Nama: {claim.user_name}</div>
<div>Kontak: {claim.contact}</div>
</div>
</div>
<div className="flex gap-4">
{claim.status === "pending" && (
<>
<button
onClick={onApprove}
className="flex-1 px-4 py-3 bg-gradient-to-r from-green-600 to-green-700 text-white rounded-xl hover:from-green-700 hover:to-green-800 transition font-semibold shadow-lg"
>
Approve Klaim
</button>
<button
onClick={onReject}
className="flex-1 px-4 py-3 bg-gradient-to-r from-red-600 to-red-700 text-white rounded-xl hover:from-red-700 hover:to-red-800 transition font-semibold shadow-lg"
>
Reject Klaim
</button>
</>
)}
</div>
{claim.status === "approved" && !claim.berita_acara_no && (
<button
onClick={() => {
onClose();
onCloseCase(claim);
}}
className="w-full mt-4 px-4 py-3 bg-gradient-to-r from-blue-600 to-blue-700 text-white rounded-xl hover:from-blue-700 hover:to-blue-800 transition font-semibold shadow-lg"
>
📋 Close Case (Serah Terima)
</button>
)}
{claim.status === "approved" && claim.berita_acara_no && (
<div className="mt-4 p-4 bg-green-500/10 border-2 border-green-500/30 rounded-xl">
<div className="text-green-400 font-semibold text-center mb-2">
Case Already Closed
</div>
<div className="text-sm text-slate-300 text-center">
No. BA: <strong>{claim.berita_acara_no}</strong>
</div>
</div>
)}
</div>
)}
</Modal>
);
const CloseCaseModal = ({
isOpen,
onClose,
claim,
closeCaseData,
setCloseCaseData,
onSubmit,
loading,
}) => (
<Modal
isOpen={isOpen}
onClose={() => {
onClose();
setCloseCaseData({
berita_acara_no: "",
bukti_serah_terima: "",
notes: "",
});
}}
title="Close Case - Serah Terima Barang"
>
<form onSubmit={onSubmit} className="space-y-4">
<div className="bg-blue-500/10 p-4 rounded-lg border border-blue-500/30 mb-4">
<strong className="text-blue-400">Barang:</strong>
<p className="text-white mt-1">{claim?.item_name}</p>
<strong className="text-blue-400 mt-2 block">Penerima:</strong>
<p className="text-white">{claim?.user_name}</p>
</div>
<div>
<label className="block font-semibold mb-2 text-slate-300">
No. Berita Acara *
</label>
<input
type="text"
value={closeCaseData.berita_acara_no}
onChange={(e) =>
setCloseCaseData({
...closeCaseData,
berita_acara_no: e.target.value,
})
}
placeholder="BA/LNF/2025/001"
required
className="w-full px-4 py-3 bg-slate-700 border-2 border-slate-600 rounded-xl text-white placeholder-slate-400 focus:border-blue-500 focus:outline-none"
/>
</div>
<div>
<label className="block font-semibold mb-2 text-slate-300">
Bukti Serah Terima (Foto/PDF)
</label>
<input
type="file"
name="bukti_file"
accept="image/*,application/pdf"
className="w-full px-4 py-3 bg-slate-700 border-2 border-slate-600 rounded-xl text-white file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-semibold file:bg-blue-600 file:text-white hover:file:bg-blue-700 focus:outline-none"
/>
</div>
<div>
<label className="block font-semibold mb-2 text-slate-300">
Catatan (Opsional)
</label>
<textarea
value={closeCaseData.notes}
onChange={(e) =>
setCloseCaseData({ ...closeCaseData, notes: e.target.value })
}
rows="3"
className="w-full px-4 py-3 bg-slate-700 border-2 border-slate-600 rounded-xl text-white placeholder-slate-400 focus:border-blue-500 focus:outline-none"
placeholder="Catatan tambahan..."
/>
</div>
<button
type="submit"
disabled={loading}
className="w-full px-4 py-3 bg-gradient-to-r from-blue-600 to-blue-700 text-white rounded-xl hover:from-blue-700 hover:to-blue-800 transition font-semibold shadow-lg disabled:from-slate-600 disabled:to-slate-700"
>
{loading ? "Memproses..." : "✓ Close Case"}
</button>
</form>
</Modal>
);
const LostItemDetailModal = ({ isOpen, onClose, item }) => (
<Modal isOpen={isOpen} onClose={onClose} title="😢 Detail Barang Hilang">
{item && (
<div className="space-y-6">
{/* Header Section */}
<div className="bg-gradient-to-r from-slate-800 to-slate-900 p-5 rounded-xl border-l-4 border-yellow-500 shadow-lg">
<h3 className="text-2xl font-bold text-white mb-1">{item.name}</h3>
<div className="flex items-center gap-2 text-sm text-slate-400">
<span className="bg-slate-700 px-2 py-1 rounded text-xs text-white border border-slate-600">
{item.status === "active" ? "Aktif" : "Ditemukan"}
</span>
<span></span>
<span>ID #{item.id}</span>
</div>
</div>
{/* Grid Informasi Utama */}
<div className="grid grid-cols-2 gap-4">
<div className="bg-slate-700/30 p-4 rounded-xl border border-slate-600">
<p className="text-xs text-slate-400 uppercase font-semibold mb-1">
Kategori
</p>
<p className="text-white flex items-center gap-2">
🏷 {item.category || "-"}
</p>
</div>
<div className="bg-slate-700/30 p-4 rounded-xl border border-slate-600">
<p className="text-xs text-slate-400 uppercase font-semibold mb-1">
Tanggal Hilang
</p>
<p className="text-white flex items-center gap-2">
📅 {Helpers.formatDate(item.date_lost)}
</p>
</div>
<div className="bg-slate-700/30 p-4 rounded-xl border border-slate-600">
<p className="text-xs text-slate-400 uppercase font-semibold mb-1">
Warna
</p>
<p className="text-white flex items-center gap-2">
🎨 {item.color || "-"}
</p>
</div>
<div className="bg-slate-700/30 p-4 rounded-xl border border-slate-600">
<p className="text-xs text-slate-400 uppercase font-semibold mb-1">
Lokasi
</p>
<p className="text-white flex items-center gap-2">
📍 {item.location || "-"}
</p>
</div>
</div>
{/* Deskripsi */}
<div className="bg-slate-900/50 p-5 rounded-xl border border-slate-600">
<h4 className="text-yellow-400 font-semibold mb-2 flex items-center gap-2">
<span>📝</span> Deskripsi Lengkap
</h4>
<p className="text-slate-300 leading-relaxed text-sm">
"{item.description}"
</p>
</div>
{/* Informasi Pelapor */}
<div className="bg-blue-500/10 border border-blue-500/30 p-5 rounded-xl">
<h4 className="text-blue-400 font-semibold mb-3 flex items-center gap-2">
<span>👤</span> Informasi Pelapor
</h4>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<p className="text-xs text-slate-400">Nama Pelapor</p>
<p className="text-white font-medium">{item.user_name}</p>
</div>
<div>
<p className="text-xs text-slate-400">Kontak</p>
<div className="flex items-center gap-2">
<span className="text-white font-medium">
{item.user_contact || "-"}
</span>
{item.user_contact && (
<a
href={`https://wa.me/${item.user_contact
.replace(/^0/, "62")
.replace(/\D/g, "")}`}
target="_blank"
className="text-xs bg-green-600 px-2 py-1 rounded text-white hover:bg-green-700 transition"
>
Chat WA
</a>
)}
</div>
</div>
</div>
</div>
{/* Footer Actions */}
<div className="flex justify-end pt-4 border-t border-slate-700">
<button
onClick={onClose}
className="px-6 py-2 bg-slate-700 text-white rounded-lg hover:bg-slate-600 transition"
>
Tutup
</button>
</div>
</div>
)}
</Modal>
);
const ApproveClaimModal = ({ isOpen, onClose, onSubmit, loading }) => {
const [notes, setNotes] = React.useState("");
// Reset input saat modal dibuka
React.useEffect(() => {
if (isOpen) setNotes("");
}, [isOpen]);
const handleSubmit = (e) => {
e.preventDefault();
onSubmit(notes); // Kirim notes ke handler submitApproveClaim
};
return (
<Modal
isOpen={isOpen}
onClose={onClose}
title="✅ Konfirmasi Approval"
size="small"
>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="bg-green-500/10 border border-green-500/30 p-4 rounded-xl">
<p className="text-sm text-green-200">
Apakah Anda yakin ingin menyetujui klaim ini? Status barang akan
berubah menjadi <strong>Approved</strong>.
</p>
</div>
<div>
<label className="block font-semibold mb-2 text-slate-300">
Catatan Approval (Opsional)
</label>
<textarea
value={notes}
onChange={(e) => setNotes(e.target.value)}
rows="3"
className="w-full px-4 py-3 bg-slate-700 border-2 border-slate-600 rounded-xl text-white placeholder-slate-400 focus:border-green-500 focus:outline-none transition"
placeholder="Contoh: Identitas telah diverifikasi..."
autoFocus
/>
</div>
<div className="flex gap-3 pt-2">
<button
type="button"
onClick={onClose}
disabled={loading}
className="flex-1 px-4 py-3 bg-slate-700 text-white rounded-xl hover:bg-slate-600 transition font-semibold"
>
Batal
</button>
<button
type="submit"
disabled={loading}
className="flex-1 px-4 py-3 bg-gradient-to-r from-green-600 to-green-700 text-white rounded-xl hover:from-green-700 hover:to-green-800 transition font-semibold shadow-lg disabled:opacity-50"
>
{loading ? "Memproses..." : "Ya, Approve"}
</button>
</div>
</form>
</Modal>
);
};
// Jangan lupa export ke window
window.LostItemDetailModal = LostItemDetailModal;
window.DetailModal = DetailModal;
window.VerifyClaimModal = VerifyClaimModal;
window.CloseCaseModal = CloseCaseModal;
window.LostItemDetailModal = LostItemDetailModal;
window.ApproveClaimModal = ApproveClaimModal;