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

240 lines
7.0 KiB
JavaScript

// assets/js/pages/manager/ManagerApp.js
const { useState, useEffect } = React;
const ManagerApp = () => {
const state = useManagerState();
const handlers = useManagerHandlers(state);
const {
user,
setUser,
activeTab,
setActiveTab,
stats,
showDetailModal,
setShowDetailModal,
selectedItem,
showVerifyModal,
setShowVerifyModal,
selectedClaim,
toast,
setToast,
showCloseCaseModal,
setShowCloseCaseModal,
closeCaseData,
setCloseCaseData,
loading,
showReportFoundModal,
setShowReportFoundModal,
photoPreview,
setPhotoPreview,
showManualClaimModal,
setShowManualClaimModal,
selectedItemForClaim,
setSelectedItemForClaim,
showApproveModal,
setShowApproveModal,
} = state;
const {
loadData,
handleApproveClaim,
handleRejectClaim,
handleCloseCase,
submitCloseCase,
submitReportFound,
handlePhotoChange,
handleLogout,
submitApproveClaim,
} = handlers;
useEffect(() => {
if (!AuthUtils.checkAuthAndRedirect("manager")) return;
const currentUser = AuthUtils.getCurrentUser();
setUser(currentUser);
loadData();
}, []);
useEffect(() => {
if (activeTab === "claims") {
handlers.loadClaims();
}
}, [activeTab]);
return (
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-blue-900 to-slate-900">
<Navbar user={user} onLogout={handleLogout} userType="manager" />
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="mb-8">
<h1 className="text-3xl font-bold text-white mb-2">
Dashboard Manager
</h1>
<p className="text-slate-400">
Kelola barang temuan dan verifikasi klaim
</p>
</div>
{/* Stats */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
<StatCard
title="Total Barang"
value={stats.total_items || 0}
icon="📦"
/>
<StatCard
title="Pending Claim"
value={stats.pending_claims || 0}
icon="⏳"
colorClass="text-yellow-400"
/>
<StatCard
title="Verified"
value={stats.verified || 0}
icon="✅"
colorClass="text-green-400"
/>
<StatCard
title="Expired"
value={stats.expired || 0}
icon="⚠️"
colorClass="text-red-400"
/>
</div>
{/* Tabs */}
<div className="flex gap-2 mb-6 flex-wrap">
<button
onClick={() => setActiveTab("items")}
className={`px-6 py-3 rounded-xl font-semibold transition ${
activeTab === "items"
? "bg-gradient-to-r from-blue-600 to-blue-700 text-white shadow-lg shadow-blue-500/50"
: "bg-slate-800 text-slate-300 hover:bg-slate-700 border border-slate-700"
}`}
>
📦 Kelola Barang
</button>
<button
onClick={() => {
setActiveTab("lost-items");
handlers.loadLostItems();
}}
className={`px-6 py-3 rounded-xl font-semibold transition ${
activeTab === "lost-items"
? "bg-gradient-to-r from-blue-600 to-blue-700 text-white shadow-lg shadow-blue-500/50"
: "bg-slate-800 text-slate-300 hover:bg-slate-700 border border-slate-700"
}`}
>
😢 Kelola Barang Hilang
</button>
<button
onClick={() => setActiveTab("claims")}
className={`px-6 py-3 rounded-xl font-semibold transition ${
activeTab === "claims"
? "bg-gradient-to-r from-blue-600 to-blue-700 text-white shadow-lg shadow-blue-500/50"
: "bg-slate-800 text-slate-300 hover:bg-slate-700 border border-slate-700"
}`}
>
🤝 Verifikasi Klaim
</button>
</div>
{/* Tab Content */}
{activeTab === "items" && (
<ItemsTabManager state={state} handlers={handlers} />
)}
{activeTab === "lost-items" && (
<LostItemsTabManager state={state} handlers={handlers} />
)}
{activeTab === "claims" && (
<ClaimsTabManager state={state} handlers={handlers} />
)}
{/* Modals */}
<DetailModal
isOpen={showDetailModal}
onClose={() => setShowDetailModal(false)}
item={selectedItem}
/>
<VerifyClaimModal
isOpen={showVerifyModal}
onClose={() => setShowVerifyModal(false)}
claim={selectedClaim}
onApprove={handleApproveClaim}
onReject={handleRejectClaim}
onCloseCase={handleCloseCase}
/>
<CloseCaseModal
isOpen={showCloseCaseModal}
onClose={() => setShowCloseCaseModal(false)}
claim={selectedClaim}
closeCaseData={closeCaseData}
setCloseCaseData={setCloseCaseData}
onSubmit={submitCloseCase}
loading={loading}
/>
<ManagerReportFoundModal
isOpen={showReportFoundModal}
onClose={() => {
setShowReportFoundModal(false);
setPhotoPreview(null);
}}
categories={state.categories}
onSubmit={submitReportFound}
loading={loading}
photoPreview={photoPreview}
onPhotoChange={(e) => handlePhotoChange(e)}
/>
<MatchLostItemModal
isOpen={state.showMatchLostItemModal}
onClose={() => {
state.setShowMatchLostItemModal(false);
state.setSelectedLostItem(null);
}}
lostItem={state.selectedLostItem}
items={state.items}
onSubmit={handlers.submitMatchLostItem}
loading={loading}
/>
<ApproveClaimModal
isOpen={showApproveModal}
onClose={() => setShowApproveModal(false)}
onSubmit={submitApproveClaim}
loading={loading}
/>
<ManagerManualClaimModal
isOpen={showManualClaimModal}
onClose={() => {
setShowManualClaimModal(false);
setSelectedItemForClaim(null);
}}
item={selectedItemForClaim}
onSubmit={handlers.submitManualClaim}
loading={loading}
/>
<EditItemModal state={state} handlers={handlers} />
{/* Toast */}
{toast && (
<Toast
message={toast.message}
type={toast.type}
onClose={() => setToast(null)}
/>
)}
<AIChatbot />
</div>
</div>
);
};
ReactDOM.render(<ManagerApp />, document.getElementById("root"));