import React, { useState, useEffect, useRef } from "react"; import { TireProduct } from "../data"; import { getTireProducts, saveTireProduct, deleteTireProduct } from "../lib/tireService"; import { loginAdmin, logoutAdmin, checkAuthState, createAdminUser, bulkUpdatePrices, getLowStockProducts, onProductsSnapshot, exportToJSON, importFromJSON, isBrowserOnline, registerNetworkStateListener, uploadProductImage, ProductDocument, getVisitorLogs, VisitorRecord } from "../lib/firebaseService"; import { Plus, Trash2, Edit, Database, Wrench, RefreshCw, Sparkles, Save, X, Search, Tag, Check, User, Lock, LogOut, Download, Upload, AlertTriangle, FileSpreadsheet, Wifi, WifiOff, Image as ImageIcon, Eye, Users, Monitor, Globe } from "lucide-react"; import { User as AuthUser } from "firebase/auth"; interface InventoryManagerProps { darkMode: boolean; onRefreshProducts: () => void; } export default function InventoryManager({ darkMode, onRefreshProducts }: InventoryManagerProps) { const [products, setProducts] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(""); const [showAddForm, setShowAddForm] = useState(false); const [editingProduct, setEditingProduct] = useState(null); // Connection State const [isOnline, setIsOnline] = useState(isBrowserOnline()); // Authentication State const [currentUser, setCurrentUser] = useState(null); const [authEmail, setAuthEmail] = useState(""); const [authPassword, setAuthPassword] = useState(""); const [isRegisterMode, setIsRegisterMode] = useState(false); const [authLoading, setAuthLoading] = useState(false); // Bulk operation states const [bulkPercent, setBulkPercent] = useState(10); const [bulkLoading, setBulkLoading] = useState(false); // Form State for Adding / Editing const [formId, setFormId] = useState(""); const [formName, setFormName] = useState(""); const [formBrand, setFormBrand] = useState(""); const [formSize, setFormSize] = useState(""); const [formFeature, setFormFeature] = useState(""); const [formPrice, setFormPrice] = useState(15000); const [formStock, setFormStock] = useState(10); const [formBadge, setFormBadge] = useState("Hot Selling"); const [formSegment, setFormSegment] = useState<"hot" | "new" | "famous">("hot"); const [formImage, setFormImage] = useState(""); const [formDescription, setFormDescription] = useState(""); // Upload state const [selectedFile, setSelectedFile] = useState(null); const [uploadLoading, setUploadLoading] = useState(false); const fileInputRef = useRef(null); // Low stock products alert list const [lowStockProducts, setLowStockProducts] = useState([]); // Visitor Analytics State const [visitorLogs, setVisitorLogs] = useState([]); const [visitorStatsLoading, setVisitorStatsLoading] = useState(false); const [activeAdminTab, setActiveAdminTab] = useState<"products" | "visitors">("products"); // Notification Toast log const [logMessage, setLogMessage] = useState<{ text: string; type: "success" | "error" | "info" } | null>(null); // Synchronize visitor analytics list when admin is authenticated useEffect(() => { if (currentUser) { fetchVisitorAnalytics(); } else { setVisitorLogs([]); } }, [currentUser]); const fetchVisitorAnalytics = async () => { setVisitorStatsLoading(true); try { const logs = await getVisitorLogs(); setVisitorLogs(logs); } catch (err) { console.error("Failed to load visitor logs:", err); } finally { setVisitorStatsLoading(false); } }; // Trigger custom state snapshots and online listener hooks useEffect(() => { // 1. Real-time online checker const removeNetworkListener = registerNetworkStateListener((online) => { setIsOnline(online); triggerToast(online ? "System online. Real-time databases synced." : "Workspace offline. Some writes may be queued.", online ? "success" : "error"); }); // 2. Auth listener const removeAuthListener = checkAuthState((user) => { setCurrentUser(user); }); // 3. Real-time Snapshot listeners const removeSnapshotListener = onProductsSnapshot((snapshotList) => { const mapped = snapshotList.map(p => ({ id: p.id, name: p.name, brand: p.brand, size: p.size, feature: p.feature, price: p.price, badge: p.badge || (p.category === "hot-selling" ? "Hot Selling" : p.category === "new-brands" ? "New Arrival" : "Famous"), segment: p.segment || (p.category === "hot-selling" ? "hot" : p.category === "new-brands" ? "new" : "famous"), image: p.image || p.imageUrl, stock: p.stock || 0, description: p.description || "" })); setProducts(mapped); setLoading(false); // Update low stock list getLowStockProducts(5).then(lows => setLowStockProducts(lows)).catch(err => console.log(err)); }); return () => { removeNetworkListener(); removeAuthListener(); removeSnapshotListener(); }; }, []); const triggerToast = (text: string, type: "success" | "error" | "info" = "success") => { setLogMessage({ text, type }); setTimeout(() => setLogMessage(null), 4000); }; // Login handler const handleAuthSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!authEmail || !authPassword) { triggerToast("Please supply email and password", "error"); return; } setAuthLoading(true); try { if (isRegisterMode) { await createAdminUser(authEmail, authPassword); triggerToast("Admin created and authenticated successfully!", "success"); } else { await loginAdmin(authEmail, authPassword); triggerToast("Authenticated successfully as Administrator!", "success"); } setAuthEmail(""); setAuthPassword(""); } catch (err: any) { triggerToast(err.message || "Authentication attempt rejected.", "error"); } finally { setAuthLoading(false); } }; const handleSignOut = async () => { try { await logoutAdmin(); triggerToast("Signed out successfully.", "info"); } catch (err) { triggerToast("Signout failed.", "error"); } }; // Pre-fill edit form const handleEditClick = (prod: any) => { setEditingProduct(prod); setFormId(prod.id); setFormName(prod.name); setFormBrand(prod.brand); setFormSize(prod.size); setFormFeature(prod.feature); setFormPrice(prod.price); setFormStock(prod.stock || 10); setFormBadge(prod.badge); setFormSegment(prod.segment); setFormImage(prod.image); setFormDescription(prod.description); setShowAddForm(true); // Open the form drawer window.scrollTo({ top: 120, behavior: "smooth" }); }; // Reset/Clear Form Fields const clearForm = () => { setEditingProduct(null); setFormId(""); setFormName(""); setFormBrand(""); setFormSize(""); setFormFeature(""); setFormPrice(15000); setFormStock(10); setFormBadge("New Arrival"); setFormSegment("new"); setFormImage(""); setFormDescription(""); setSelectedFile(null); }; // Handle storage file uploads const handleFileUploadChange = (e: React.ChangeEvent) => { if (e.target.files && e.target.files[0]) { setSelectedFile(e.target.files[0]); } }; // Trigger storage upload const handleImageUploadToStorage = async () => { if (!selectedFile) { triggerToast("Please select a file to upload first.", "info"); return; } if (!formName) { triggerToast("Please define the Tyre Name first to tag your image correctly.", "info"); return; } setUploadLoading(true); try { const responseUrl = await uploadProductImage(selectedFile, formName); setFormImage(responseUrl); triggerToast("Image asset uploaded to Storage bucket successfully!", "success"); setSelectedFile(null); } catch (err: any) { triggerToast(err.message || "Failed to upload image. Writes are restricted.", "error"); } finally { setUploadLoading(false); } }; // Create / Save Handler (triggers Firebase writing) const handleSaveProduct = async (e: React.FormEvent) => { e.preventDefault(); if (!formName || !formBrand || !formSize || !formPrice) { triggerToast("Please fill in all mandatory inputs.", "error"); return; } if (!currentUser) { triggerToast("Unauthorized operation. Please log in as Administrator first.", "error"); return; } const imgUrl = formImage.trim() || "https://images.unsplash.com/photo-1542282088-fe8426682b8f?auto=format&fit=crop&q=80&w=600"; const customId = formId || `custom-${Date.now()}`; const parsedPrice = parseInt(String(formPrice), 10); const parsedStock = parseInt(String(formStock), 10); if (isNaN(parsedPrice) || parsedPrice <= 0) { triggerToast("Price must be a valid positive integer.", "error"); return; } const categoryMapped = formSegment === "hot" ? "hot-selling" : formSegment === "new" ? "new-brands" : "famous"; const payload: TireProduct & { stock: number } = { id: customId, name: formName, brand: formBrand, size: formSize, feature: formFeature, price: parsedPrice, badge: formBadge, segment: formSegment, image: imgUrl, stock: parsedStock, description: formDescription.trim() || `Premium high-durability tire configured specifically for the local roads of Lahore.` }; try { await saveTireProduct(payload); triggerToast( editingProduct ? `Successfully saved modifications for '${payload.name}'!` : `Successfully registered and seeded '${payload.name}' into the database!`, "success" ); clearForm(); setShowAddForm(false); onRefreshProducts(); // Trigger app refetch } catch (err: any) { console.error(err); triggerToast(`Operation rejected. Verify schema rules or Admin privileges.`, "error"); } }; // Delete Handler const handleDeleteClick = async (id: string, name: string) => { if (!currentUser) { triggerToast("Authentication required. Please log in to complete deletions.", "error"); return; } if (!window.confirm(`Are you absolutely sure you want to delete '${name}'?`)) { return; } try { await deleteTireProduct(id); triggerToast(`Deleted '${name}' from Firestore!`, "info"); onRefreshProducts(); } catch (err) { triggerToast("Restricted write. Confirm your role.", "error"); } }; // Bulk rate updater const handleBulkUpdate = async () => { if (!currentUser) { triggerToast("Admin authentication is required for bulk price variations.", "error"); return; } if (!window.confirm(`Are you sure you want to alter ALL inventory prices by ${bulkPercent}%?`)) { return; } setBulkLoading(true); try { await bulkUpdatePrices(bulkPercent); triggerToast(`Successfully adjusted all catalog rates in bulk by ${bulkPercent}%!`, "success"); onRefreshProducts(); } catch (err: any) { triggerToast(err.message || "Bulk operation failed. Check rules permissions.", "error"); } finally { setBulkLoading(false); } }; // JSON backup download const handleExportJSON = async () => { try { await exportToJSON(); triggerToast("Product catalog downloaded successfully!", "success"); } catch (e) { triggerToast("Export failed.", "error"); } }; // JSON backup upload const handleImportJSONChange = async (e: React.ChangeEvent) => { if (!currentUser) { triggerToast("Admin authentication is required to run database imports.", "error"); return; } if (e.target.files && e.target.files[0]) { const file = e.target.files[0]; if (!window.confirm(`This will import products from '${file.name}'. Duplicate profiles will be ignored. Proceed?`)) { return; } try { const outcomes = await importFromJSON(file); triggerToast(`Import completed with success! Added: ${outcomes.imported} items, Ignored (Duplicates): ${outcomes.duplicates} items.`, "success"); onRefreshProducts(); } catch (err: any) { triggerToast(err.message || "Failed to process database import file.", "error"); } } }; // Filter local inventory display list const filteredProducts = products.filter((p) => { const term = searchQuery.toLowerCase(); return ( p.name.toLowerCase().includes(term) || p.brand.toLowerCase().includes(term) || p.size.toLowerCase().includes(term) || p.segment.toLowerCase().includes(term) ); }); return (
{/* Toast Alert popup banner */} {logMessage && (
{logMessage.type === "success" ? "✔" : "ℹ"}

{logMessage.text}

)} {/* Connection Checker & Admin Identity Banner */}
{isOnline ? ( SYSTEM ONLINE (bahaduralimunnabhai@gmail.com) ) : ( SYSTEM OFFLINE (LOCAL CACHE SHIELDS ACTIVE) )}
{currentUser ? (
👤 Admin: {currentUser.email}
) : ( Role: Unauthenticated Client (Sign in below to write to DB) )}
{/* Admin Credentials Login Form Panel (when not logged in) */} {!currentUser && (

{isRegisterMode ? "Create New Security Admin Account" : "Registered Administrator Authentication"}

By default, Firestore security rules block unauthorized browser requests. Use this panel to sign in with an administrator email and password, or quickly register a credentials profile below!

setAuthEmail(e.target.value)} className={`w-full p-2.5 rounded-xl text-xs border focus:outline-none focus:ring-1 focus:ring-brand-orange ${ darkMode ? "bg-black/35 border-white/10 text-white" : "bg-slate-50 border-slate-200" }`} id="admin-email-field" />
setAuthPassword(e.target.value)} className={`w-full p-2.5 rounded-xl text-xs border focus:outline-none focus:ring-1 focus:ring-brand-orange ${ darkMode ? "bg-black/35 border-white/10 text-white" : "bg-slate-50 border-slate-200" }`} id="admin-password-field" />
)} {/* KPI stats display */}
FIRESTORE PRODUCTS COUNT {products.length} Items
AVERAGE WHOLESALE RATE PKR {Math.round(products.reduce((acc, current) => acc + current.price, 0) / (products.length || 1)).toLocaleString()}
CRITICAL RESTOCK LOG (STOCK < 5) {lowStockProducts.length} Items Alerted
{/* Bulk editing & backup portability deck (visible when logged in) */}
{/* Module A: Bulk Adjustments */}

Bulk Margin Adjustment Command

Instantly increment or decrement ALL prices of tires stored in your Firestore database using a single batch payload.

-50% setBulkPercent(parseInt(e.target.value, 10))} className="w-full accent-brand-orange bg-slate-200 dark:bg-neutral-800 rounded-lg" /> +50%
{/* Module B: JSON Data Portability (Export & Import) */}

Firebase Backup Data Portability

Download your complete inventory collection as a standard JSON file, or restore assets from backups with automatic duplicate detection.

{/* Export */} {/* Import file mask */}
Upload JSON
{/* Button controls */}
{currentUser && ( )}
{/* Display badge for low stock warning items */} {lowStockProducts.length > 0 && (
Stock alerts: {lowStockProducts.length} items cataloged under 5 units!
)}
{/* Add / Edit Form Panel */} {showAddForm && currentUser && (

{editingProduct ? `Edit Tyre Configuration: ${editingProduct.name}` : "Create New Tyre Product"}

{/* Tyre Name */}
setFormName(e.target.value)} className={`w-full p-2.5 rounded-xl text-xs border focus:ring-1 focus:ring-brand-orange focus:outline-none ${ darkMode ? "bg-black/35 border-white/10 text-white" : "bg-white border-slate-200 text-slate-800" }`} />
{/* Brand */}
setFormBrand(e.target.value)} className={`w-full p-2.5 rounded-xl text-xs border focus:ring-1 focus:ring-brand-orange focus:outline-none ${ darkMode ? "bg-black/35 border-white/10 text-white" : "bg-white border-slate-200 text-slate-800" }`} />
{/* Size */}
setFormSize(e.target.value)} className={`w-full p-2.5 rounded-xl text-xs border focus:ring-1 focus:ring-brand-orange focus:outline-none ${ darkMode ? "bg-black/35 border-white/10 text-white" : "bg-white border-slate-200 text-slate-800" }`} />
{/* Feature Highlight */}
setFormFeature(e.target.value)} className={`w-full p-2.5 rounded-xl text-xs border focus:ring-1 focus:ring-brand-orange focus:outline-none ${ darkMode ? "bg-black/35 border-white/10 text-white" : "bg-white border-slate-200 text-slate-800" }`} />
{/* Price (PKR) */}
setFormPrice(parseInt(e.target.value, 10) || 15000)} className={`w-full p-2.5 rounded-xl text-xs border focus:ring-1 focus:ring-brand-orange focus:outline-none ${ darkMode ? "bg-black/35 border-white/10 text-white" : "bg-white border-slate-200 text-slate-800" }`} />
{/* Segment Type */}
{/* Stock Levels */}
setFormStock(parseInt(e.target.value, 10) || 0)} className={`w-full p-2.5 rounded-xl text-xs border focus:ring-1 focus:ring-brand-orange focus:outline-none ${ darkMode ? "bg-black/35 border-white/10 text-white" : "bg-white border-slate-200 text-slate-800" }`} />
{/* Image path */}
setFormImage(e.target.value)} className={`w-full p-2.5 rounded-xl text-xs border focus:ring-1 focus:ring-brand-orange focus:outline-none ${ darkMode ? "bg-black/35 border-white/10 text-white" : "bg-white border-slate-200 text-slate-800" }`} />
{/* Firebase Storage Image Upload module */}
{selectedFile && ( )}
{/* Display Badge */}
setFormBadge(e.target.value)} className={`w-full p-2.5 rounded-xl text-xs border focus:ring-1 focus:ring-brand-orange focus:outline-none ${ darkMode ? "bg-black/35 border-white/10 text-white" : "bg-white border-slate-200 text-slate-800" }`} />
{/* Detailed Description */}