import React, { useState, useEffect } from 'react'; import { X, Save, Plus, Search, Trash2, Calendar, Building, CreditCard, Tag, ShoppingBag } from 'lucide-react'; export default function AddCollectionModal({ isOpen, onClose, onSave, branches, types }) { const [formData, setFormData] = useState({ date: new Date().toISOString().split('T')[0], branch_id: '', collection_type_id: '', payment_method: 'Cash', amount: '', remarks: '', items: [] }); const isReceptionist = window.__APP_DATA__?.role === 'receptionist'; const receptionistBranchId = window.__APP_DATA__?.branch?.id; const [products, setProducts] = useState([]); const [loadingProducts, setLoadingProducts] = useState(false); const [searchTerm, setSearchTerm] = useState(''); const [showProductSearch, setShowProductSearch] = useState(false); const [paymentMethods, setPaymentMethods] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { if (isReceptionist && receptionistBranchId) { setFormData(prev => ({ ...prev, branch_id: receptionistBranchId })); } else if (branches.length > 0 && !formData.branch_id) { setFormData(prev => ({ ...prev, branch_id: branches[0].id })); } }, [branches, isReceptionist, receptionistBranchId]); useEffect(() => { if (isOpen) { fetchPaymentMethods(); if (formData.branch_id) { fetchProducts(); } } }, [isOpen, formData.branch_id]); const fetchPaymentMethods = async () => { try { const res = await fetch('/api/masters/payment_method'); if (res.ok) { const data = await res.json(); setPaymentMethods(data.filter(m => m.status === 'Active')); // Set default if current is not in active methods or if it's the default 'Cash' if (data.length > 0 && !data.find(m => m.name === formData.payment_method)) { setFormData(prev => ({ ...prev, payment_method: data[0].name })); } } } catch (error) { console.error('Error fetching payment methods:', error); } }; const fetchProducts = async () => { setLoadingProducts(true); try { const res = await fetch(`/api/inventory/products?branch_id=${formData.branch_id}`); if (res.ok) { setProducts(await res.json()); } } catch (error) { console.error('Error fetching products:', error); } finally { setLoadingProducts(false); } }; if (!isOpen) return null; const selectedType = types.find(t => t.id.toString() === formData.collection_type_id.toString()); const isProductSale = selectedType && ( selectedType.name.toLowerCase().includes('product sale') || selectedType.name.toLowerCase().includes('product saled') ); const addItem = (product) => { if (product.current_stock <= 0) { alert('This product is out of stock in the selected branch.'); return; } const existing = formData.items.find(i => i.product_id === product.id); let newItems; if (existing) { if (existing.quantity + 1 > product.current_stock) { alert(`Only ${product.current_stock} units available in stock.`); return; } newItems = formData.items.map(i => i.product_id === product.id ? { ...i, quantity: i.quantity + 1 } : i ); } else { newItems = [...formData.items, { product_id: product.id, name: product.name, unit_price: product.selling_price, quantity: 1, max_stock: product.current_stock // Store for easy validation }]; } const newAmount = newItems.reduce((sum, i) => sum + (i.quantity * i.unit_price), 0); setFormData({ ...formData, items: newItems, amount: newAmount.toString() }); setShowProductSearch(false); }; const updateItemQty = (productId, delta) => { const item = formData.items.find(i => i.product_id === productId); if (delta > 0 && item.quantity + delta > item.max_stock) { alert(`Only ${item.max_stock} units available in stock.`); return; } const newItems = formData.items.map(i => { if (i.product_id === productId) { return { ...i, quantity: Math.max(1, i.quantity + delta) }; } return i; }); const newAmount = newItems.reduce((sum, i) => sum + (i.quantity * i.unit_price), 0); setFormData({ ...formData, items: newItems, amount: newAmount.toString() }); }; const removeItem = (productId) => { const newItems = formData.items.filter(i => i.product_id !== productId); const newAmount = newItems.reduce((sum, i) => sum + (i.quantity * i.unit_price), 0); setFormData({ ...formData, items: newItems, amount: newAmount.toString() }); }; const handleSubmit = async (e) => { if (e) e.preventDefault(); if (isProductSale && formData.items.length === 0) { alert('Please add at least one product for a Product Sale entry.'); return; } if (!formData.amount || parseFloat(formData.amount) <= 0) { alert('Please enter a valid amount.'); return; } setLoading(true); try { const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); const res = await fetch('/api/collections', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken }, body: JSON.stringify(formData) }); if (res.ok) { const newCollection = await res.json(); onSave(newCollection); setFormData({ date: new Date().toISOString().split('T')[0], branch_id: window.__APP_DATA__?.role === 'receptionist' ? window.__APP_DATA__?.branch?.id : (branches[0]?.id || ''), collection_type_id: '', payment_method: 'Cash', amount: '', remarks: '', items: [] }); onClose(); } } catch (error) { console.error('Error adding collection:', error); } finally { setLoading(false); } }; const filteredProducts = products.filter(p => p.name.toLowerCase().includes(searchTerm.toLowerCase()) ); return (
Record incoming revenue.
No products found