import React, { useState, useEffect, useRef } from 'react'; import { Plus, X, Search, Filter, MoreVertical, RefreshCw, Edit2, Power, PowerOff, ShoppingCart, Package, ExternalLink } from 'lucide-react'; import Pagination from '../components/Pagination'; interface BaseItem { id: number; name: string; description: string; active: boolean; } interface Product { id: number; name: string; price: number; category: string; active: boolean; } const BaseMenu = () => { const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const [showModal, setShowModal] = useState(false); const [editingItem, setEditingItem] = useState(null); const [newItem, setNewItem] = useState({ name: '', description: '', active: true }); const [openMenuId, setOpenMenuId] = useState(null); const [searchTerm, setSearchTerm] = useState(''); // Pagination States const [currentPage, setCurrentPage] = useState(0); const [pageSize, setPageSize] = useState(10); const [totalElements, setTotalElements] = useState(0); const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(''); // Associated Products State const [selectedBaseItem, setSelectedBaseItem] = useState(null); const [associatedProducts, setAssociatedProducts] = useState([]); const [productsLoading, setProductsLoading] = useState(false); const [showProductsModal, setShowProductsModal] = useState(false); const menuRef = useRef(null); // Debounce search term useEffect(() => { const timer = setTimeout(() => { setDebouncedSearchTerm(searchTerm); }, 500); return () => clearTimeout(timer); }, [searchTerm]); // Reset to first page when search changes useEffect(() => { setCurrentPage(0); }, [debouncedSearchTerm]); useEffect(() => { fetchItems(); }, [currentPage, pageSize, debouncedSearchTerm]); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (menuRef.current && !menuRef.current.contains(event.target as Node)) { setOpenMenuId(null); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); const fetchItems = async () => { setLoading(true); try { const host = window.location.hostname; const params = new URLSearchParams(); params.append('page', currentPage.toString()); params.append('size', pageSize.toString()); if (debouncedSearchTerm) { params.append('search', debouncedSearchTerm); } const response = await fetch(`http://${host}:8080/api/base-items?${params.toString()}`); const data = await response.json(); if (data && data.content) { setItems(data.content); setTotalElements(data.totalElements); } else { setItems([]); setTotalElements(0); } } catch (error) { console.error('Error fetching items:', error); } finally { setLoading(false); } }; const fetchAssociatedProducts = async (baseItem: BaseItem) => { setSelectedBaseItem(baseItem); setShowProductsModal(true); setProductsLoading(true); try { const response = await fetch(`http://localhost:8080/api/products/category/${encodeURIComponent(baseItem.name)}`); const data = await response.json(); setAssociatedProducts(data); } catch (error) { console.error('Error fetching associated products:', error); } finally { setProductsLoading(false); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); const url = editingItem ? `http://localhost:8080/api/base-items/${editingItem.id}` : 'http://localhost:8080/api/base-items'; const method = editingItem ? 'PUT' : 'POST'; try { const response = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newItem), }); if (response.ok) { setShowModal(false); setEditingItem(null); setNewItem({ name: '', description: '', active: true }); fetchItems(); } } catch (error) { console.error('Error saving item:', error); } }; const handleEdit = (item: BaseItem) => { setEditingItem(item); setNewItem({ name: item.name, description: item.description, active: item.active }); setShowModal(true); setOpenMenuId(null); }; const handleToggleActive = async (item: BaseItem) => { try { const response = await fetch(`http://localhost:8080/api/base-items/${item.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...item, active: !item.active }), }); if (response.ok) { fetchItems(); setOpenMenuId(null); } } catch (error) { console.error('Error toggling active status:', error); } }; return (

Base Items

Manage your base inventory items

{/* Filters Bar */}
setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2 bg-gray-50 border border-[#e2e8f0] rounded-lg text-sm focus:outline-none focus:border-[#231651]/30 transition-all" />
{/* Table */}
{loading ? ( ) : items.length === 0 ? ( ) : ( items.map((item) => ( )) )}
ID Item Name Description Products Status Actions

Loading items...

No items found

Try adjusting your search or add a new item.

#{item.id} {item.name} {item.description}
{item.active ? 'Active' : 'Inactive'}
{openMenuId === item.id && (
)}
{ setPageSize(newSize); setCurrentPage(0); }} />
{/* Associated Products Modal */} {showProductsModal && (

Products for: {selectedBaseItem?.name}

Showing all associated products in this category

{productsLoading ? (

Fetching associated products...

) : associatedProducts.length === 0 ? (

No Products Found

There are no products currently linked to the "{selectedBaseItem?.name}" category.

) : (
{associatedProducts.map(product => (

{product.name}

{product.active ? 'Active' : 'Inactive'}

₹{product.price}

Sale Price

))}
)}
)} {/* Standard Modal (Add/Edit) */} {showModal && (

{editingItem ? 'Edit Base Item' : 'Add New Base Item'}

setNewItem({ ...newItem, name: e.target.value })} placeholder="e.g. Fresh Tomato" className="w-full px-4 py-2.5 border border-[#e2e8f0] rounded-xl focus:outline-none focus:border-[#231651] focus:ring-1 focus:ring-[#231651] transition-all text-sm" />