import React, { useState, useEffect, useRef, createContext, useContext } from 'react'; import { Menu, X, ShoppingCart, Package, BarChart2, User, Users, Settings, LogOut, Plus, Minus, Trash2, Edit, Eye, EyeOff, Search, Filter, Download, Printer, Save, AlertTriangle, Clock, DollarSign, CreditCard, FileText, Calendar, ChevronRight, ChevronDown, ChevronLeft, Check, RefreshCw, Lock, Unlock, ArrowRight, ArrowLeft, Home, Bell, Moon, Sun, HelpCircle } from 'lucide-react'; // Firebase imports would go here in a real implementation // import { initializeApp } from 'firebase/app'; // import { getAuth, signInWithEmailAndPassword, signOut, onAuthStateChanged } from 'firebase/auth'; // import { getDatabase, ref, set, get, update, remove, onValue, push } from 'firebase/database'; // import { getStorage, ref as storageRef, uploadBytes, getDownloadURL } from 'firebase/storage'; // Mock Firebase for demo purposes const mockFirebase = { auth: { currentUser: null, signInWithEmailAndPassword: (email, password) => { return new Promise((resolve, reject) => { setTimeout(() => { if (email === 'admin@example.com' && password === 'admin123') { mockFirebase.auth.currentUser = { uid: '1', email, displayName: 'Admin User', role: 'admin' }; resolve({ user: mockFirebase.auth.currentUser }); } else if (email === 'cashier@example.com' && password === 'cashier123') { mockFirebase.auth.currentUser = { uid: '2', email, displayName: 'Cashier User', role: 'cashier' }; resolve({ user: mockFirebase.auth.currentUser }); } else if (email === 'manager@example.com' && password === 'manager123') { mockFirebase.auth.currentUser = { uid: '3', email, displayName: 'Manager User', role: 'manager' }; resolve({ user: mockFirebase.auth.currentUser }); } else { reject(new Error('Invalid email or password')); } }, 1000); }); }, signOut: () => { return new Promise((resolve) => { setTimeout(() => { mockFirebase.auth.currentUser = null; resolve(); }, 500); }); }, onAuthStateChanged: (callback) => { callback(mockFirebase.auth.currentUser); return () => {}; } }, database: { data: { products: [ { id: '1', name: 'T-Shirt', price: 19.99, category: 'Clothing', stock: 45, barcode: '123456789', description: 'Cotton t-shirt', expires: false }, { id: '2', name: 'Jeans', price: 49.99, category: 'Clothing', stock: 30, barcode: '223456789', description: 'Blue denim jeans', expires: false }, { id: '3', name: 'Milk', price: 3.99, category: 'Dairy', stock: 25, barcode: '323456789', description: 'Fresh milk', expires: true, expiryDate: '2023-12-30' }, { id: '4', name: 'Bread', price: 2.99, category: 'Bakery', stock: 15, barcode: '423456789', description: 'Whole wheat bread', expires: true, expiryDate: '2023-12-25' }, { id: '5', name: 'Notebook', price: 4.99, category: 'Stationery', stock: 100, barcode: '523456789', description: 'Lined notebook', expires: false }, { id: '6', name: 'Yogurt', price: 1.99, category: 'Dairy', stock: 20, barcode: '623456789', description: 'Greek yogurt', expires: true, expiryDate: '2023-12-28' }, { id: '7', name: 'Water Bottle', price: 14.99, category: 'Accessories', stock: 40, barcode: '723456789', description: 'Stainless steel water bottle', expires: false }, { id: '8', name: 'Headphones', price: 89.99, category: 'Electronics', stock: 15, barcode: '823456789', description: 'Wireless headphones', expires: false }, ], categories: ['Clothing', 'Dairy', 'Bakery', 'Stationery', 'Accessories', 'Electronics'], customers: [ { id: '1', name: 'John Doe', email: 'john@example.com', phone: '123-456-7890', address: '123 Main St', creditLimit: 500, creditUsed: 200 }, { id: '2', name: 'Jane Smith', email: 'jane@example.com', phone: '234-567-8901', address: '456 Oak Ave', creditLimit: 1000, creditUsed: 750 }, { id: '3', name: 'Bob Johnson', email: 'bob@example.com', phone: '345-678-9012', address: '789 Pine Rd', creditLimit: 300, creditUsed: 0 }, { id: '4', name: 'Alice Brown', email: 'alice@example.com', phone: '456-789-0123', address: '321 Cedar Ln', creditLimit: 800, creditUsed: 400 }, ], staff: [ { id: '1', name: 'Admin User', email: 'admin@example.com', role: 'admin', phone: '123-456-7890' }, { id: '2', name: 'Cashier User', email: 'cashier@example.com', role: 'cashier', phone: '234-567-8901' }, { id: '3', name: 'Manager User', email: 'manager@example.com', role: 'manager', phone: '345-678-9012' }, ], sales: [ { id: '1', date: '2023-12-15T10:30:00', items: [ { productId: '1', name: 'T-Shirt', price: 19.99, quantity: 2 }, { productId: '5', name: 'Notebook', price: 4.99, quantity: 1 } ], subtotal: 44.97, tax: 3.15, total: 48.12, paymentMethod: 'cash', customerId: '1', customerName: 'John Doe', staffId: '2', staffName: 'Cashier User', status: 'completed' }, { id: '2', date: '2023-12-16T14:45:00', items: [ { productId: '3', name: 'Milk', price: 3.99, quantity: 2 }, { productId: '4', name: 'Bread', price: 2.99, quantity: 1 }, { productId: '6', name: 'Yogurt', price: 1.99, quantity: 3 } ], subtotal: 18.94, tax: 1.33, total: 20.27, paymentMethod: 'credit', customerId: '2', customerName: 'Jane Smith', staffId: '2', staffName: 'Cashier User', status: 'completed' }, { id: '3', date: '2023-12-17T16:20:00', items: [ { productId: '8', name: 'Headphones', price: 89.99, quantity: 1 } ], subtotal: 89.99, tax: 6.30, total: 96.29, paymentMethod: 'credit_account', customerId: '2', customerName: 'Jane Smith', staffId: '3', staffName: 'Manager User', status: 'completed' }, ], settings: { businessName: 'My POS Store', address: '123 Business St, City, State, ZIP', phone: '(123) 456-7890', email: 'contact@myposstore.com', taxRate: 7, currency: 'USD', receiptFooter: 'Thank you for your business!', lowStockThreshold: 10, theme: 'light' } }, ref: (path) => ({ path, set: (data) => { return new Promise((resolve) => { setTimeout(() => { const pathParts = path.split('/'); let current = mockFirebase.database.data; for (let i = 0; i < pathParts.length - 1; i++) { if (!current[pathParts[i]]) { current[pathParts[i]] = {}; } current = current[pathParts[i]]; } current[pathParts[pathParts.length - 1]] = data; resolve(); }, 500); }); }, update: (data) => { return new Promise((resolve) => { setTimeout(() => { const pathParts = path.split('/'); let current = mockFirebase.database.data; for (let i = 0; i < pathParts.length - 1; i++) { if (!current[pathParts[i]]) { current[pathParts[i]] = {}; } current = current[pathParts[i]]; } if (!current[pathParts[pathParts.length - 1]]) { current[pathParts[pathParts.length - 1]] = {}; } Object.assign(current[pathParts[pathParts.length - 1]], data); resolve(); }, 500); }); }, push: () => { const newId = Math.random().toString(36).substring(2, 15); return { key: newId, set: (data) => { return new Promise((resolve) => { setTimeout(() => { const pathParts = path.split('/'); let current = mockFirebase.database.data; for (let i = 0; i < pathParts.length; i++) { if (!current[pathParts[i]]) { current[pathParts[i]] = {}; } current = current[pathParts[i]]; } if (!Array.isArray(current)) { current = mockFirebase.database.data[pathParts[0]] = []; } current.push({ ...data, id: newId }); resolve(); }, 500); }); } }; }, remove: () => { return new Promise((resolve) => { setTimeout(() => { const pathParts = path.split('/'); let current = mockFirebase.database.data; for (let i = 0; i < pathParts.length - 1; i++) { if (!current[pathParts[i]]) { return resolve(); } current = current[pathParts[i]]; } if (pathParts.length === 1) { delete mockFirebase.database.data[pathParts[0]]; } else { delete current[pathParts[pathParts.length - 1]]; } resolve(); }, 500); }); }, onValue: (callback) => { setTimeout(() => { const pathParts = path.split('/'); let data = mockFirebase.database.data; for (let i = 0; i < pathParts.length; i++) { if (!data[pathParts[i]]) { data = null; break; } data = data[pathParts[i]]; } callback({ val: () => data }); }, 500); return () => {}; }, get: () => { return new Promise((resolve) => { setTimeout(() => { const pathParts = path.split('/'); let data = mockFirebase.database.data; for (let i = 0; i < pathParts.length; i++) { if (!data[pathParts[i]]) { data = null; break; } data = data[pathParts[i]]; } resolve({ val: () => data }); }, 500); }); } }) } }; // Create context for global state const AppContext = createContext(); // Main POS Application export default function POSSystem() { const [isAuthenticated, setIsAuthenticated] = useState(false); const [user, setUser] = useState(null); const [isLoading, setIsLoading] = useState(true); const [isDemo, setIsDemo] = useState(false); const [menuOpen, setMenuOpen] = useState(false); const [activeView, setActiveView] = useState('dashboard'); const [darkMode, setDarkMode] = useState(false); const [settings, setSettings] = useState(null); const [notification, setNotification] = useState(null); // Initialize app and check authentication useEffect(() => { // Check for existing session const savedUser = localStorage.getItem('posUser'); const savedIsDemo = localStorage.getItem('posIsDemo'); if (savedUser) { setUser(JSON.parse(savedUser)); setIsAuthenticated(true); setIsDemo(savedIsDemo === 'true'); } // Load settings loadSettings(); setIsLoading(false); }, []); // Load settings from Firebase const loadSettings = async () => { try { const settingsRef = mockFirebase.database.ref('settings'); const snapshot = await settingsRef.get(); const settingsData = snapshot.val(); if (settingsData) { setSettings(settingsData); setDarkMode(settingsData.theme === 'dark'); } } catch (error) { console.error('Error loading settings:', error); } }; // Handle login const handleLogin = (userData, demo = false) => { setUser(userData); setIsAuthenticated(true); setIsDemo(demo); // Save to localStorage localStorage.setItem('posUser', JSON.stringify(userData)); localStorage.setItem('posIsDemo', demo.toString()); // Show welcome notification showNotification(`Welcome, ${userData.displayName || userData.email}!`, 'success'); }; // Handle logout const handleLogout = async () => { try { await mockFirebase.auth.signOut(); setUser(null); setIsAuthenticated(false); // Clear from localStorage localStorage.removeItem('posUser'); localStorage.removeItem('posIsDemo'); showNotification('You have been logged out successfully', 'info'); } catch (error) { console.error('Error signing out:', error); showNotification('Error signing out', 'error'); } }; // Show notification const showNotification = (message, type = 'info', duration = 3000) => { setNotification({ message, type }); if (duration) { setTimeout(() => { setNotification(null); }, duration); } }; // Toggle dark mode const toggleDarkMode = async () => { const newMode = !darkMode; setDarkMode(newMode); // Update settings in Firebase if (settings) { const updatedSettings = { ...settings, theme: newMode ? 'dark' : 'light' }; setSettings(updatedSettings); try { await mockFirebase.database.ref('settings').update(updatedSettings); } catch (error) { console.error('Error updating theme setting:', error); } } }; // Context value const contextValue = { user, isDemo, settings, darkMode, showNotification, toggleDarkMode }; if (isLoading) { return (

Loading POS System...

); } if (!isAuthenticated) { return ; } return (
{/* Header */}

{settings?.businessName || 'POS System'} {isDemo && DEMO MODE}

{user.displayName || user.email}
{/* Main Content with Slide Menu */}
{/* Slide Menu */}
{/* Overlay for mobile menu */} {menuOpen && (
setMenuOpen(false)} >
)} {/* Main Content Area */}
{activeView === 'dashboard' && } {activeView === 'pos' && } {activeView === 'products' && } {activeView === 'customers' && } {activeView === 'invoices' && } {activeView === 'reports' && } {activeView === 'staff' && } {activeView === 'settings' && } {activeView === 'help' && } {activeView === 'notifications' && }
{/* Notification Toast */} {notification && (
{notification.type === 'success' && } {notification.type === 'error' && } {notification.type === 'warning' && } {notification.type === 'info' && }

{notification.message}

)}
); } // Menu Item Component function MenuItem({ icon, label, onClick, active, collapsed, disabled = false }) { const { darkMode } = useContext(AppContext); return (
  • ); } // Login Screen Component function LoginScreen({ onLogin }) { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const [isLoading, setIsLoading] = useState(false); const [showPassword, setShowPassword] = useState(false); const handleSubmit = async (e) => { e.preventDefault(); // Simple validation if (!email || !password) { setError('Please enter both email and password'); return; } setIsLoading(true); setError(''); try { // Sign in with Firebase Auth const result = await mockFirebase.auth.signInWithEmailAndPassword(email, password); onLogin(result.user, false); } catch (error) { console.error('Error signing in:', error); setError(error.message); } finally { setIsLoading(false); } }; const handleDemoLogin = async () => { setIsLoading(true); try { // Use admin credentials for demo const result = await mockFirebase.auth.signInWithEmailAndPassword('admin@example.com', 'admin123'); onLogin(result.user, true); } catch (error) { console.error('Error signing in to demo:', error); setError(error.message); } finally { setIsLoading(false); } }; return (

    POS System Login

    Enter your credentials to access the system

    setEmail(e.target.value)} className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm" placeholder="Email address" />
    setPassword(e.target.value)} className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm pr-10" placeholder="Password" />
    {error && (
    {error}
    )}

    Demo accounts:

    Admin

    admin@example.com

    admin123

    Manager

    manager@example.com

    manager123

    Cashier

    cashier@example.com

    cashier123

    Or
    ); } // Dashboard View function DashboardView() { const { darkMode, isDemo, settings } = useContext(AppContext); const [salesData, setSalesData] = useState([]); const [products, setProducts] = useState([]); const [customers, setCustomers] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const loadDashboardData = async () => { try { // Fetch sales data const salesRef = mockFirebase.database.ref('sales'); const salesSnapshot = await salesRef.get(); const salesData = salesSnapshot.val() || []; setSalesData(salesData); // Fetch products const productsRef = mockFirebase.database.ref('products'); const productsSnapshot = await productsRef.get(); const productsData = productsSnapshot.val() || []; setProducts(productsData); // Fetch customers const customersRef = mockFirebase.database.ref('customers'); const customersSnapshot = await customersRef.get(); const customersData = customersSnapshot.val() || []; setCustomers(customersData); setIsLoading(false); } catch (error) { console.error('Error loading dashboard data:', error); setIsLoading(false); } }; loadDashboardData(); }, []); // Calculate dashboard metrics const calculateDailyTotal = () => { const today = new Date().toISOString().split('T')[0]; return salesData .filter(sale => sale.date.startsWith(today)) .reduce((sum, sale) => sum + sale.total, 0); }; const calculateTotalSales = () => { return salesData.reduce((sum, sale) => sum + sale.total, 0); }; const calculateAverageOrderValue = () => { if (salesData.length === 0) return 0; return calculateTotalSales() / salesData.length; }; const calculateLowStockItems = () => { const threshold = settings?.lowStockThreshold || 10; return products.filter(product => product.stock < threshold).length; }; const calculateTotalCustomers = () => { return customers.length; }; const calculateTotalCredit = () => { return customers.reduce((sum, customer) => sum + (customer.creditUsed || 0), 0); }; const calculateExpiringItems = () => { const today = new Date(); const nextWeek = new Date(); nextWeek.setDate(today.getDate() + 7); return products.filter(product => { if (!product.expires || !product.expiryDate) return false; const expiryDate = new Date(product.expiryDate); return expiryDate > today && expiryDate <= nextWeek; }).length; }; if (isLoading) { return (

    Loading dashboard data...

    ); } return (

    Dashboard

    Welcome back! Here's an overview of your business.

    {/* Dashboard Cards */}
    } color="indigo" /> } color="green" /> } color={calculateLowStockItems() > 0 ? "amber" : "green"} /> } color="blue" />
    {/* Recent Sales */}

    Recent Sales

    {salesData.length === 0 ? (

    No sales data available yet

    ) : (
    {salesData.slice(0, 5).map(sale => ( ))}
    Date Customer Items Total
    {new Date(sale.date).toLocaleDateString()} {sale.customerName || 'Walk-in'} {sale.items.length} ${sale.total.toFixed(2)}
    )}
    {/* Low Stock Items */}

    Low Stock Items

    {products.filter(product => product.stock < (settings?.lowStockThreshold || 10)).length === 0 ? (

    No low stock items

    ) : (
    {products .filter(product => product.stock < (settings?.lowStockThreshold || 10)) .slice(0, 5) .map(product => ( ))}
    Name Category Current Stock Status
    {product.name}
    {product.category} {product.stock} 5 ? 'bg-yellow-100 text-yellow-800' : 'bg-red-100 text-red-800' }`}> {product.stock > 5 ? 'Low Stock' : 'Critical'}
    )}
    {/* Credit Alerts */}

    Credit Alerts

    {customers.filter(customer => (customer.creditUsed || 0) > (customer.creditLimit * 0.8)).length === 0 ? (

    No credit alerts

    ) : (
    {customers .filter(customer => (customer.creditUsed || 0) > (customer.creditLimit * 0.8)) .slice(0, 5) .map(customer => ( ))}
    Customer Credit Used Credit Limit Status
    {customer.name}
    ${customer.creditUsed.toFixed(2)} ${customer.creditLimit.toFixed(2)} = customer.creditLimit ? 'bg-red-100 text-red-800' : 'bg-yellow-100 text-yellow-800' }`}> {customer.creditUsed >= customer.creditLimit ? 'Limit Reached' : 'Near Limit'}
    )}
    {/* Expiring Products */}

    Expiring Products

    {products.filter(product => { if (!product.expires || !product.expiryDate) return false; const expiryDate = new Date(product.expiryDate); const today = new Date(); const nextWeek = new Date(); nextWeek.setDate(today.getDate() + 7); return expiryDate > today && expiryDate <= nextWeek; }).length === 0 ? (

    No products expiring soon

    ) : (
    {products .filter(product => { if (!product.expires || !product.expiryDate) return false; const expiryDate = new Date(product.expiryDate); const today = new Date(); const nextWeek = new Date(); nextWeek.setDate(today.getDate() + 7); return expiryDate > today && expiryDate <= nextWeek; }) .slice(0, 5) .map(product => { const expiryDate = new Date(product.expiryDate); const today = new Date(); const daysUntilExpiry = Math.ceil((expiryDate - today) / (1000 * 60 * 60 * 24)); return ( ); })}
    Name Category Expiry Date Status
    {product.name}
    {product.category} {new Date(product.expiryDate).toLocaleDateString()} {daysUntilExpiry <= 3 ? 'Critical' : `${daysUntilExpiry} days left`}
    )}
    ); } // Dashboard Card Component function DashboardCard({ title, value, icon, color }) { const { darkMode } = useContext(AppContext); const getColorClasses = () => { if (darkMode) { switch (color) { case 'indigo': return 'bg-indigo-900 text-indigo-200'; case 'green': return 'bg-green-900 text-green-200'; case 'amber': return 'bg-amber-900 text-amber-200'; case 'blue': return 'bg-blue-900 text-blue-200'; case 'red': return 'bg-red-900 text-red-200'; default: return 'bg-gray-800 text-gray-200'; } } else { switch (color) { case 'indigo': return 'bg-indigo-100 text-indigo-600'; case 'green': return 'bg-green-100 text-green-600'; case 'amber': return 'bg-amber-100 text-amber-600'; case 'blue': return 'bg-blue-100 text-blue-600'; case 'red': return 'bg-red-100 text-red-600'; default: return 'bg-gray-100 text-gray-600'; } } }; return (
    {icon}

    {title}

    {value}

    ); } // POS View function POSView() { const { darkMode, isDemo, settings, showNotification } = useContext(AppContext); const [products, setProducts] = useState([]); const [categories, setCategories] = useState([]); const [customers, setCustomers] = useState([]); const [cart, setCart] = useState([]); const [isLoading, setIsLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const [selectedCategory, setSelectedCategory] = useState('all'); const [showCheckoutModal, setShowCheckoutModal] = useState(false); const [paymentMethod, setPaymentMethod] = useState('cash'); const [amountReceived, setAmountReceived] = useState(''); const [selectedCustomer, setSelectedCustomer] = useState(null); const [showCustomerModal, setShowCustomerModal] = useState(false); const [showReceiptModal, setShowReceiptModal] = useState(false); const [currentReceipt, setCurrentReceipt] = useState(null); const [barcodeInput, setBarcodeInput] = useState(''); const barcodeInputRef = useRef(null); useEffect(() => { const loadPOSData = async () => { try { // Fetch products const productsRef = mockFirebase.database.ref('products'); const productsSnapshot = await productsRef.get(); const productsData = productsSnapshot.val() || []; setProducts(productsData); // Fetch categories const categoriesRef = mockFirebase.database.ref('categories'); const categoriesSnapshot = await categoriesRef.get(); const categoriesData = categoriesSnapshot.val() || []; setCategories(categoriesData); // Fetch customers const customersRef = mockFirebase.database.ref('customers'); const customersSnapshot = await customersRef.get(); const customersData = customersSnapshot.val() || []; setCustomers(customersData); setIsLoading(false); } catch (error) { console.error('Error loading POS data:', error); setIsLoading(false); } }; loadPOSData(); }, []); // Focus on barcode input when component mounts useEffect(() => { if (barcodeInputRef.current) { barcodeInputRef.current.focus(); } }, []); // Handle barcode input const handleBarcodeSubmit = (e) => { e.preventDefault(); if (!barcodeInput) return; const product = products.find(p => p.barcode === barcodeInput); if (product) { addToCart(product); setBarcodeInput(''); } else { showNotification(`Product with barcode ${barcodeInput} not found`, 'error'); setBarcodeInput(''); } }; // Add product to cart const addToCart = (product) => { if (product.stock <= 0) { showNotification(`${product.name} is out of stock`, 'error'); return; } const existingItem = cart.find(item => item.id === product.id); if (existingItem) { if (existingItem.quantity >= product.stock) { showNotification(`Cannot add more ${product.name}. Only ${product.stock} in stock.`, 'warning'); return; } setCart(cart.map(item => item.id === product.id ? { ...item, quantity: item.quantity + 1 } : item )); } else { setCart([...cart, { id: product.id, name: product.name, price: product.price, quantity: 1, stock: product.stock }]); } showNotification(`${product.name} added to cart`, 'success'); }; // Update cart item quantity const updateCartItemQuantity = (productId, newQuantity) => { const product = products.find(p => p.id === productId); if (newQuantity <= 0) { removeFromCart(productId); return; } if (newQuantity > product.stock) { showNotification(`Cannot add more ${product.name}. Only ${product.stock} in stock.`, 'warning'); return; } setCart(cart.map(item => item.id === productId ? { ...item, quantity: newQuantity } : item )); }; // Remove item from cart const removeFromCart = (productId) => { setCart(cart.filter(item => item.id !== productId)); }; // Clear cart const clearCart = () => { if (cart.length === 0) return; if (confirm('Are you sure you want to clear the cart?')) { setCart([]); setSelectedCustomer(null); showNotification('Cart cleared', 'info'); } }; // Calculate cart subtotal const calculateSubtotal = () => { return cart.reduce((total, item) => total + (item.price * item.quantity), 0); }; // Calculate tax const calculateTax = () => { const taxRate = settings?.taxRate || 7; return calculateSubtotal() * (taxRate / 100); }; // Calculate total const calculateTotal = () => { return calculateSubtotal() + calculateTax(); }; // Process checkout const processCheckout = async () => { if (cart.length === 0) return; try { const subtotal = calculateSubtotal(); const tax = calculateTax(); const total = calculateTotal(); const change = paymentMethod === 'cash' ? parseFloat(amountReceived) - total : 0; // Check if customer has enough credit limit for credit_account payment if (paymentMethod === 'credit_account') { if (!selectedCustomer) { showNotification('Please select a customer for credit account payment', 'error'); return; } const customer = customers.find(c => c.id === selectedCustomer.id); const newCreditUsed = (customer.creditUsed || 0) + total; if (newCreditUsed > customer.creditLimit) { showNotification(`This purchase exceeds ${customer.name}'s credit limit`, 'error'); return; } } // Create receipt const receipt = { id: Date.now().toString(), date: new Date().toISOString(), items: cart.map(item => ({ productId: item.id, name: item.name, price: item.price, quantity: item.quantity })), subtotal, tax, total, paymentMethod, amountReceived: paymentMethod === 'cash' ? parseFloat(amountReceived) : total, change, customerId: selectedCustomer?.id || null, customerName: selectedCustomer?.name || 'Walk-in Customer', staffId: mockFirebase.auth.currentUser.uid, staffName: mockFirebase.auth.currentUser.displayName || mockFirebase.auth.currentUser.email, status: 'completed' }; // Update inventory and sales if (isDemo) { // Update demo data in memory only updateDemoData(receipt); } else { // Update real data in Firebase await updateRealData(receipt); } // Show receipt setCurrentReceipt(receipt); setShowReceiptModal(true); setShowCheckoutModal(false); // Clear cart and reset setCart([]); setAmountReceived(''); setSelectedCustomer(null); showNotification('Sale completed successfully', 'success'); } catch (error) { console.error('Error processing checkout:', error); showNotification('Error processing checkout', 'error'); } }; // Update demo data const updateDemoData = (receipt) => { // Update products stock const updatedProducts = products.map(product => { const cartItem = cart.find(item => item.id === product.id); if (cartItem) { return { ...product, stock: product.stock - cartItem.quantity }; } return product; }); setProducts(updatedProducts); // Update customer credit if payment method is credit_account if (receipt.paymentMethod === 'credit_account' && receipt.customerId) { const updatedCustomers = customers.map(customer => { if (customer.id === receipt.customerId) { return { ...customer, creditUsed: (customer.creditUsed || 0) + receipt.total }; } return customer; }); setCustomers(updatedCustomers); } }; // Update real data in Firebase const updateRealData = async (receipt) => { try { // Add sale to Firebase const salesRef = mockFirebase.database.ref('sales'); await salesRef.push().set(receipt); // Update product stock for (const item of cart) { const productRef = mockFirebase.database.ref(`products/${item.id}`); const productSnapshot = await productRef.get(); const product = productSnapshot.val(); if (product) { await productRef.update({ stock: product.stock - item.quantity }); } } // Update customer credit if payment method is credit_account if (receipt.paymentMethod === 'credit_account' && receipt.customerId) { const customerRef = mockFirebase.database.ref(`customers/${receipt.customerId}`); const customerSnapshot = await customerRef.get(); const customer = customerSnapshot.val(); if (customer) { await customerRef.update({ creditUsed: (customer.creditUsed || 0) + receipt.total }); } } } catch (error) { console.error('Error updating data in Firebase:', error); throw error; } }; // Filter products based on search and category const filteredProducts = products.filter(product => { const matchesSearch = product.name.toLowerCase().includes(searchQuery.toLowerCase()) || (product.barcode && product.barcode.includes(searchQuery)); const matchesCategory = selectedCategory === 'all' || product.category === selectedCategory; return matchesSearch && matchesCategory; }); if (isLoading) { return (

    Loading POS data...

    ); } return (

    Point of Sale

    Process sales and manage transactions.

    {/* Product Catalog */}
    {/* Search and Filter */}
    setBarcodeInput(e.target.value)} placeholder="Scan barcode..." className={`w-full pl-10 pr-4 py-2 border ${darkMode ? 'bg-gray-700 border-gray-600 text-white placeholder-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder-gray-500'} rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500`} />
    setSearchQuery(e.target.value)} className={`w-full pl-10 pr-4 py-2 border ${darkMode ? 'bg-gray-700 border-gray-600 text-white placeholder-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder-gray-500'} rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500`} />
    {/* Products Grid */}
    {filteredProducts.length === 0 ? (

    No products found

    ) : (
    {filteredProducts.map(product => (
    addToCart(product)} >

    {product.name}

    ${product.price.toFixed(2)}

    {product.category}

    10 ? darkMode ? 'text-green-400' : 'text-green-600' : darkMode ? 'text-red-400' : 'text-red-600' }`}> Stock: {product.stock}
    ))}
    )}
    {/* Shopping Cart */}

    Shopping Cart

    {cart.length === 0 ? (

    Your cart is empty

    ) : (
    {cart.map(item => (

    {item.name}

    ${item.price.toFixed(2)} each

    {item.quantity}
    ))}
    )}
    Subtotal: ${calculateSubtotal().toFixed(2)}
    Tax ({settings?.taxRate || 7}%): ${calculateTax().toFixed(2)}
    Total: ${calculateTotal().toFixed(2)}
    {/* Customer Selection Modal */} {showCustomerModal && ( { setSelectedCustomer(customer); setShowCustomerModal(false); }} onClose={() => setShowCustomerModal(false)} /> )} {/* Checkout Modal */} {showCheckoutModal && ( setShowCheckoutModal(false)} /> )} {/* Receipt Modal */} {showReceiptModal && currentReceipt && ( setShowReceiptModal(false)} /> )}
    ); } // Customer Selection Modal function CustomerSelectionModal({ customers, selectedCustomer, onSelectCustomer, onClose }) { const { darkMode } = useContext(AppContext); const [searchQuery, setSearchQuery] = useState(''); const filteredCustomers = customers.filter(customer => customer.name.toLowerCase().includes(searchQuery.toLowerCase()) || customer.email.toLowerCase().includes(searchQuery.toLowerCase()) || customer.phone.includes(searchQuery) ); return (

    Select Customer

    setSearchQuery(e.target.value)} className={`w-full pl-10 pr-4 py-2 border ${darkMode ? 'bg-gray-700 border-gray-600 text-white placeholder-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder-gray-500'} rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500`} />
    {filteredCustomers.map(customer => ( ))}
    Name Contact Credit Action
    Walk-in Customer
    N/A
    N/A
    {customer.name}
    {customer.phone}
    {customer.email}
    customer.creditLimit * 0.8 ? darkMode ? 'text-red-400' : 'text-red-600' : '' }`}> ${(customer.creditUsed || 0).toFixed(2)} {' / '} ${customer.creditLimit.toFixed(2)}
    ); } // Checkout Modal function CheckoutModal({ cart, subtotal, tax, total, paymentMethod, setPaymentMethod, amountReceived, setAmountReceived, selectedCustomer, onCheckout, onClose }) { const { darkMode } = useContext(AppContext); const handleSubmit = (e) => { e.preventDefault(); onCheckout(); }; return (

    Checkout

    Order Summary

    {cart.map(item => (
    {item.name} x {item.quantity} ${(item.price * item.quantity).toFixed(2)}
    ))}
    Subtotal ${subtotal.toFixed(2)}
    Tax ${tax.toFixed(2)}
    Total ${total.toFixed(2)}

    Payment Method

    {paymentMethod === 'credit_account' && !selectedCustomer && (

    Please select a customer to use credit account payment.

    )}
    {paymentMethod === 'cash' && (
    setAmountReceived(e.target.value)} className={`pl-10 pr-4 py-2 w-full border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 ${ darkMode ? 'bg-gray-700 border-gray-600 text-white placeholder-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder-gray-500' }`} placeholder="0.00" />
    {parseFloat(amountReceived) > 0 && (
    Change: ${Math.max(0, parseFloat(amountReceived) - total).toFixed(2)}
    )}
    )} {paymentMethod === 'credit_account' && selectedCustomer && (

    Credit Account Information

    Customer: {selectedCustomer.name}

    Credit Limit: ${selectedCustomer.creditLimit.toFixed(2)}

    Credit Used: ${(selectedCustomer.creditUsed || 0).toFixed(2)}

    Available Credit: ${(selectedCustomer.creditLimit - (selectedCustomer.creditUsed || 0)).toFixed(2)}

    New Balance After Purchase: ${((selectedCustomer.creditUsed || 0) + total).toFixed(2)}

    )}
    ); } // Receipt Modal function ReceiptModal({ receipt, settings, onClose }) { const { darkMode } = useContext(AppContext); const receiptRef = useRef(null); const handlePrint = () => { const printContent = receiptRef.current.innerHTML; const originalContent = document.body.innerHTML; document.body.innerHTML = `
    ${printContent}
    `; window.print(); document.body.innerHTML = originalContent; }; const handleDownload = () => { // In a real implementation, this would generate a PDF alert('PDF download functionality would be implemented here.'); }; return (

    Receipt

    {settings?.businessName || 'My POS Store'}

    {settings?.address || '123 Business St, City, State, ZIP'}

    Tel: {settings?.phone || '(123) 456-7890'}

    Receipt #: {receipt.id}
    Date: {new Date(receipt.date).toLocaleString()}
    Cashier: {receipt.staffName}
    Customer: {receipt.customerName}
    Item
    Qty Price Total
    {receipt.items.map(item => (
    {item.name}
    {item.quantity} ${item.price.toFixed(2)} ${(item.price * item.quantity).toFixed(2)}
    ))}
    Subtotal ${receipt.subtotal.toFixed(2)}
    Tax ${receipt.tax.toFixed(2)}
    Total ${receipt.total.toFixed(2)}
    {receipt.paymentMethod === 'cash' && ( <>
    Amount Received ${parseFloat(receipt.amountReceived).toFixed(2)}
    Change ${receipt.change.toFixed(2)}
    )}
    Payment Method {receipt.paymentMethod === 'cash' ? 'Cash' : receipt.paymentMethod === 'credit' ? 'Credit Card' : 'Credit Account'}

    {settings?.receiptFooter || 'Thank you for your business!'}

    Please come again

    ); } // Products View function ProductsView() { const { darkMode, showNotification } = useContext(AppContext); const [products, setProducts] = useState([]); const [categories, setCategories] = useState([]); const [isLoading, setIsLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const [selectedCategory, setSelectedCategory] = useState('all'); const [showAddProductModal, setShowAddProductModal] = useState(false); const [showEditProductModal, setShowEditProductModal] = useState(false); const [currentProduct, setCurrentProduct] = useState(null); const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false); const [productToDelete, setProductToDelete] = useState(null); const [showExpiringOnly, setShowExpiringOnly] = useState(false); const [showLowStockOnly, setShowLowStockOnly] = useState(false); useEffect(() => { const loadProductsData = async () => { try { // Fetch products const productsRef = mockFirebase.database.ref('products'); const productsSnapshot = await productsRef.get(); const productsData = productsSnapshot.val() || []; setProducts(productsData); // Fetch categories const categoriesRef = mockFirebase.database.ref('categories'); const categoriesSnapshot = await categoriesRef.get(); const categoriesData = categoriesSnapshot.val() || []; setCategories(categoriesData); setIsLoading(false); } catch (error) { console.error('Error loading products data:', error); setIsLoading(false); } }; loadProductsData(); }, []); // Handle adding a new product const handleAddProduct = async (productData) => { try { // Generate a new ID const newId = Date.now().toString(); const newProduct = { ...productData, id: newId }; // Add to products array const updatedProducts = [...products, newProduct]; setProducts(updatedProducts); // Save to Firebase const productRef = mockFirebase.database.ref(`products/${newId}`); await productRef.set(newProduct); showNotification('Product added successfully', 'success'); } catch (error) { console.error('Error adding product:', error); showNotification('Error adding product', 'error'); } }; // Handle editing a product const handleEditProduct = async (productData) => { try { // Update in products array const updatedProducts = products.map(product => product.id === productData.id ? productData : product ); setProducts(updatedProducts); // Save to Firebase const productRef = mockFirebase.database.ref(`products/${productData.id}`); await productRef.update(productData); showNotification('Product updated successfully', 'success'); } catch (error) { console.error('Error updating product:', error); showNotification('Error updating product', 'error'); } }; // Handle deleting a product const handleDeleteProduct = async (productId) => { try { // Remove from products array const updatedProducts = products.filter(product => product.id !== productId); setProducts(updatedProducts); // Remove from Firebase const productRef = mockFirebase.database.ref(`products/${productId}`); await productRef.remove(); showNotification('Product deleted successfully', 'success'); } catch (error) { console.error('Error deleting product:', error); showNotification('Error deleting product', 'error'); } }; // Filter products based on search, category, and other filters const filteredProducts = products.filter(product => { const matchesSearch = product.name.toLowerCase().includes(searchQuery.toLowerCase()) || (product.barcode && product.barcode.includes(searchQuery)) || (product.description && product.description.toLowerCase().includes(searchQuery.toLowerCase())); const matchesCategory = selectedCategory === 'all' || product.category === selectedCategory; const matchesExpiring = !showExpiringOnly || (product.expires && product.expiryDate); const matchesLowStock = !showLowStockOnly || product.stock < 10; return matchesSearch && matchesCategory && matchesExpiring && matchesLowStock; }); if (isLoading) { return (

    Loading products data...

    ); } return (

    Products

    Manage your product inventory.

    setSearchQuery(e.target.value)} className={`pl-10 pr-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 ${ darkMode ? 'bg-gray-700 border-gray-600 text-white placeholder-gray-400' : 'bg-white border-gray-300 text-gray-900 placeholder-gray-500' }`} />
    {filteredProducts.length === 0 ? (

    No products found

    ) : (
    {filteredProducts.map(product => ( ))}
    Name Category Price Stock Expiry Actions
    {product.name}
    {product.barcode}
    {product.category} ${product.price.toFixed(2)} 10 ? darkMode ? 'bg-green-900 text-green-200' : 'bg-green-100 text-green-800' : product.stock > 0 ? darkMode ? 'bg-yellow-900 text-yellow-200' : 'bg-yellow-100 text-yellow-800' : darkMode ? 'bg-red-900 text-red-200' : 'bg-red-100 text-red-800' }`}> {product.stock} {product.expires ? ( {new Date(product.expiryDate).toLocaleDateString()} ) : ( N/A )}
    )}
    {/* Add/Edit Product Modal */} {(showAddProductModal || showEditProductModal) && ( { setShowAddProductModal(false); setShowEditProductModal(false); setCurrentProduct(null); }} isEdit={showEditProductModal} /> )} {/* Delete Confirmation Modal */} {showDeleteConfirmation && ( { handleDeleteProduct(productToDelete.id); setShowDeleteConfirmation(false); setProductToDelete(null); }} onCancel={() => { setShowDeleteConfirmation(false); setProductToDelete(null); }} confirmButtonClass="bg-red-600 hover:bg-red-700" /> )}
    ); } // Product Form Modal function ProductFormModal({ product, categories, onSave, onClose, isEdit }) { const { darkMode } = useContext(AppContext); const [formData, setFormData] = useState( product ? { ...product } : { name: '', price: '', category: '', stock: '', barcode: '', description: '', expires: false, expiryDate: '' } ); const handleChange = (e) => { const { name, value, type, checked } = e.target; setFormData({ ...formData, [name]: type === 'checkbox' ? checked : value }); }; const handleSubmit = (e) => { e.preventDefault(); // Validate form if (!formData.name || !formData.price || !formData.category || !formData.stock) { alert('Please fill in all required fields'); return; } // Convert price and stock to numbers const processedData = { ...formData, price: parseFloat(formData.price), stock: parseInt(formData.stock) }; onSave(processedData); onClose(); }; return (
    import React, { useState, useEffect } from 'react'; import { Search, ShoppingCart, Package, BarChart2, User, LogOut, Plus, Minus, Trash2, X, Check, DollarSign, Eye, EyeOff } from 'lucide-react'; // Main POS Application export default function POSSystem() { // State management const [activeTab, setActiveTab] = useState('pos'); const [products, setProducts] = useState([]); const [cart, setCart] = useState([]); const [isLoading, setIsLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const [isAuthenticated, setIsAuthenticated] = useState(false); const [user, setUser] = useState(null); const [sales, setSales] = useState([]); const [showCheckoutModal, setShowCheckoutModal] = useState(false); const [paymentMethod, setPaymentMethod] = useState('cash'); const [amountReceived, setAmountReceived] = useState(''); const [showReceiptModal, setShowReceiptModal] = useState(false); const [currentReceipt, setCurrentReceipt] = useState(null); const [categories, setCategories] = useState([]); const [selectedCategory, setSelectedCategory] = useState('all'); const [showAddProductModal, setShowAddProductModal] = useState(false); const [newProduct, setNewProduct] = useState({ name: '', price: '', category: '', stock: '', barcode: '', description: '' }); const [isDemo, setIsDemo] = useState(false); const [registeredUsers, setRegisteredUsers] = useState([ { username: 'admin', password: 'admin123', role: 'admin' }, { username: 'cashier', password: 'cashier123', role: 'cashier' }, { username: 'manager', password: 'manager123', role: 'manager' } ]); const [showRegisterModal, setShowRegisterModal] = useState(false); const [newUser, setNewUser] = useState({ username: '', password: '', confirmPassword: '', role: 'cashier' }); // Load data on component mount useEffect(() => { // Check for existing session const savedUser = localStorage.getItem('posUser'); const savedIsDemo = localStorage.getItem('posIsDemo'); if (savedUser) { setUser(JSON.parse(savedUser)); setIsAuthenticated(true); setIsDemo(savedIsDemo === 'true'); } // Load registered users from localStorage if available const savedUsers = localStorage.getItem('posRegisteredUsers'); if (savedUsers) { setRegisteredUsers(JSON.parse(savedUsers)); } else { // Save default users to localStorage localStorage.setItem('posRegisteredUsers', JSON.stringify(registeredUsers)); } // Load data based on authentication status loadData(); }, [isAuthenticated, isDemo]); // Load data function const loadData = async () => { try { if (isAuthenticated) { if (isDemo) { // Load demo data loadDemoData(); } else { // Load real data from API or localStorage await fetchProducts(); await fetchSales(); await fetchCategories(); } } setIsLoading(false); } catch (error) { console.error('Error loading data:', error); setIsLoading(false); } }; // Load demo data const loadDemoData = () => { // Load demo products const demoProducts = [ { _id: '1', name: 'T-Shirt', price: 19.99, category: 'Clothing', stock: 45, barcode: '123456789', description: 'Cotton t-shirt' }, { _id: '2', name: 'Jeans', price: 49.99, category: 'Clothing', stock: 30, barcode: '223456789', description: 'Blue denim jeans' }, { _id: '3', name: 'Sneakers', price: 79.99, category: 'Footwear', stock: 25, barcode: '323456789', description: 'Running shoes' }, { _id: '4', name: 'Coffee Mug', price: 12.99, category: 'Accessories', stock: 50, barcode: '423456789', description: 'Ceramic coffee mug' }, { _id: '5', name: 'Notebook', price: 4.99, category: 'Stationery', stock: 100, barcode: '523456789', description: 'Lined notebook' }, { _id: '6', name: 'Backpack', price: 39.99, category: 'Accessories', stock: 20, barcode: '623456789', description: 'School backpack' }, { _id: '7', name: 'Water Bottle', price: 14.99, category: 'Accessories', stock: 40, barcode: '723456789', description: 'Stainless steel water bottle' }, { _id: '8', name: 'Headphones', price: 89.99, category: 'Electronics', stock: 15, barcode: '823456789', description: 'Wireless headphones' }, ]; setProducts(demoProducts); // Load demo sales const demoSales = [ { _id: '1', date: '2023-06-01', total: 149.95, items: 3, paymentMethod: 'credit' }, { _id: '2', date: '2023-06-02', total: 89.97, items: 2, paymentMethod: 'cash' }, { _id: '3', date: '2023-06-03', total: 199.96, items: 4, paymentMethod: 'credit' }, { _id: '4', date: '2023-06-04', total: 59.98, items: 2, paymentMethod: 'cash' }, { _id: '5', date: '2023-06-05', total: 129.95, items: 3, paymentMethod: 'credit' }, ]; setSales(demoSales); // Load demo categories const demoCategories = ['Clothing', 'Footwear', 'Accessories', 'Electronics', 'Stationery']; setCategories(demoCategories); }; // Fetch products from API or localStorage const fetchProducts = async () => { try { // Check if we have products in localStorage const savedProducts = localStorage.getItem(`posProducts_${user.username}`); if (savedProducts) { setProducts(JSON.parse(savedProducts)); } else { // If no saved products, we could fetch from API // For now, initialize with empty array setProducts([]); localStorage.setItem(`posProducts_${user.username}`, JSON.stringify([])); } } catch (error) { console.error('Error fetching products:', error); } }; // Fetch sales from API or localStorage const fetchSales = async () => { try { // Check if we have sales in localStorage const savedSales = localStorage.getItem(`posSales_${user.username}`); if (savedSales) { setSales(JSON.parse(savedSales)); } else { // If no saved sales, we could fetch from API // For now, initialize with empty array setSales([]); localStorage.setItem(`posSales_${user.username}`, JSON.stringify([])); } } catch (error) { console.error('Error fetching sales:', error); } }; // Fetch categories from API or localStorage const fetchCategories = async () => { try { // Check if we have categories in localStorage const savedCategories = localStorage.getItem(`posCategories_${user.username}`); if (savedCategories) { setCategories(JSON.parse(savedCategories)); } else { // If no saved categories, initialize with default categories const defaultCategories = ['Clothing', 'Footwear', 'Accessories', 'Electronics', 'Stationery']; setCategories(defaultCategories); localStorage.setItem(`posCategories_${user.username}`, JSON.stringify(defaultCategories)); } } catch (error) { console.error('Error fetching categories:', error); } }; // Handle login const handleLogin = (userData, demo = false) => { setUser(userData); setIsAuthenticated(true); setIsDemo(demo); // Save to localStorage localStorage.setItem('posUser', JSON.stringify(userData)); localStorage.setItem('posIsDemo', demo.toString()); }; // Handle logout const handleLogout = () => { setUser(null); setIsAuthenticated(false); setCart([]); // Clear from localStorage localStorage.removeItem('posUser'); localStorage.removeItem('posIsDemo'); }; // Add product to cart const addToCart = (product) => { const existingItem = cart.find(item => item._id === product._id); if (existingItem) { setCart(cart.map(item => item._id === product._id ? { ...item, quantity: item.quantity + 1 } : item )); } else { setCart([...cart, { ...product, quantity: 1 }]); } }; // Update cart item quantity const updateCartItemQuantity = (productId, newQuantity) => { if (newQuantity <= 0) { removeFromCart(productId); return; } setCart(cart.map(item => item._id === productId ? { ...item, quantity: newQuantity } : item )); }; // Remove item from cart const removeFromCart = (productId) => { setCart(cart.filter(item => item._id !== productId)); }; // Calculate cart total const calculateTotal = () => { return cart.reduce((total, item) => total + (item.price * item.quantity), 0); }; // Process checkout const processCheckout = async () => { if (cart.length === 0) return; try { const total = calculateTotal(); const change = paymentMethod === 'cash' ? parseFloat(amountReceived) - total : 0; // Create receipt const receipt = { _id: Date.now().toString(), date: new Date().toISOString(), items: cart, total: total, paymentMethod: paymentMethod, amountReceived: paymentMethod === 'cash' ? parseFloat(amountReceived) : total, change: change }; // Update inventory and sales if (isDemo) { // Update demo data in memory only updateDemoData(receipt); } else { // Update real data in localStorage or API await updateRealData(receipt); } // Show receipt setCurrentReceipt(receipt); setShowReceiptModal(true); setShowCheckoutModal(false); // Clear cart setCart([]); setAmountReceived(''); } catch (error) { console.error('Error processing checkout:', error); } }; // Update demo data const updateDemoData = (receipt) => { // Update products stock const updatedProducts = products.map(product => { const cartItem = cart.find(item => item._id === product._id); if (cartItem) { return { ...product, stock: product.stock - cartItem.quantity }; } return product; }); setProducts(updatedProducts); // Update sales const newSale = { _id: receipt._id, date: receipt.date, total: receipt.total, items: cart.reduce((sum, item) => sum + item.quantity, 0), paymentMethod: receipt.paymentMethod }; setSales([...sales, newSale]); }; // Update real data const updateRealData = async (receipt) => { // Update products stock const updatedProducts = products.map(product => { const cartItem = cart.find(item => item._id === product._id); if (cartItem) { return { ...product, stock: product.stock - cartItem.quantity }; } return product; }); setProducts(updatedProducts); // Save updated products to localStorage localStorage.setItem(`posProducts_${user.username}`, JSON.stringify(updatedProducts)); // Update sales const newSale = { _id: receipt._id, date: receipt.date, total: receipt.total, items: cart.reduce((sum, item) => sum + item.quantity, 0), paymentMethod: receipt.paymentMethod }; const updatedSales = [...sales, newSale]; setSales(updatedSales); // Save updated sales to localStorage localStorage.setItem(`posSales_${user.username}`, JSON.stringify(updatedSales)); // In a real app, you would also make API calls here // await fetch('https://www.sitebrew.ai/api/eNqleS/sales', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify({ document: receipt }) // }); // For each product in cart, update inventory // cart.forEach(async (item) => { // const updatedProduct = products.find(p => p._id === item._id); // await fetch(`https://www.sitebrew.ai/api/eNqleS/products`, { // method: 'PUT', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify({ document: updatedProduct }) // }); // }); }; // Add new product const handleAddProduct = async () => { try { const productToAdd = { ...newProduct, _id: Date.now().toString(), price: parseFloat(newProduct.price), stock: parseInt(newProduct.stock) }; if (isDemo) { // Add to demo products setProducts([...products, productToAdd]); } else { // Add to real products const updatedProducts = [...products, productToAdd]; setProducts(updatedProducts); // Save to localStorage localStorage.setItem(`posProducts_${user.username}`, JSON.stringify(updatedProducts)); // In a real app, you would also make API call here // await fetch('https://www.sitebrew.ai/api/eNqleS/products', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify({ document: productToAdd }) // }); } // Reset form setNewProduct({ name: '', price: '', category: '', stock: '', barcode: '', description: '' }); setShowAddProductModal(false); } catch (error) { console.error('Error adding product:', error); } }; // Register new user const handleRegisterUser = () => { // Validate form if (newUser.password !== newUser.confirmPassword) { alert("Passwords don't match"); return; } if (registeredUsers.some(user => user.username === newUser.username)) { alert("Username already exists"); return; } // Create new user object const userToAdd = { username: newUser.username, password: newUser.password, role: newUser.role }; // Add to registered users const updatedUsers = [...registeredUsers, userToAdd]; setRegisteredUsers(updatedUsers); // Save to localStorage localStorage.setItem('posRegisteredUsers', JSON.stringify(updatedUsers)); // Reset form and close modal setNewUser({ username: '', password: '', confirmPassword: '', role: 'cashier' }); setShowRegisterModal(false); }; // Filter products based on search and category const filteredProducts = products.filter(product => { const matchesSearch = product.name.toLowerCase().includes(searchQuery.toLowerCase()) || (product.barcode && product.barcode.includes(searchQuery)); const matchesCategory = selectedCategory === 'all' || product.category === selectedCategory; return matchesSearch && matchesCategory; }); // Calculate dashboard metrics const calculateDailyTotal = () => { const today = new Date().toISOString().split('T')[0]; return sales .filter(sale => sale.date.startsWith(today)) .reduce((sum, sale) => sum + sale.total, 0); }; const calculateTotalSales = () => { return sales.reduce((sum, sale) => sum + sale.total, 0); }; const calculateAverageOrderValue = () => { if (sales.length === 0) return 0; return calculateTotalSales() / sales.length; }; const calculateLowStockItems = () => { return products.filter(product => product.stock < 10).length; }; // Check if user has admin privileges const isAdmin = user && (user.role === 'admin' || user.role === 'manager'); if (isLoading) { return (

    Loading POS System...

    ); } if (!isAuthenticated) { return ; } return (
    {/* Header */}

    POS System {isDemo && DEMO MODE}

    {user.username} ({user.role})
    {isAdmin && ( )}
    {/* Navigation */} {/* Main Content */}
    {activeTab === 'pos' && (
    {/* Product Catalog */}
    setSearchQuery(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#4fd1c5]" />
    {filteredProducts.length === 0 ? (

    No products found

    {products.length === 0 && ( )}
    ) : (
    {filteredProducts.map(product => (

    {product.name}

    ${product.price.toFixed(2)}

    {product.category}

    {product.description}

    10 ? 'text-green-600' : 'text-red-600'}`}> Stock: {product.stock}
    ))}
    )}
    {/* Shopping Cart */}

    Shopping Cart

    {cart.length === 0 ? (

    Your cart is empty

    ) : (
    {cart.map(item => (

    {item.name}

    ${item.price.toFixed(2)} each

    {item.quantity}
    ))}
    )}
    Subtotal: ${calculateTotal().toFixed(2)}
    Tax (7%): ${(calculateTotal() * 0.07).toFixed(2)}
    Total: ${(calculateTotal() * 1.07).toFixed(2)}
    )} {activeTab === 'inventory' && (

    Inventory Management

    setSearchQuery(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#4fd1c5]" />
    {products.length === 0 ? (

    No products found

    ) : (
    {filteredProducts.map(product => ( ))}
    Name Category Price Stock Barcode Actions
    {product.name}
    {product.description}
    {product.category} ${product.price.toFixed(2)} 10 ? 'bg-green-100 text-green-800' : product.stock > 0 ? 'bg-yellow-100 text-yellow-800' : 'bg-red-100 text-red-800' }`}> {product.stock} {product.barcode}
    )}
    )} {activeTab === 'reports' && (

    Reports & Analytics

    {/* Dashboard Cards */}

    Today's Sales

    ${calculateDailyTotal().toFixed(2)}

    Total Sales

    ${calculateTotalSales().toFixed(2)}

    Average Order Value

    ${calculateAverageOrderValue().toFixed(2)}

    Low Stock Items

    {calculateLowStockItems()}

    {/* Sales History */}

    Recent Sales

    {sales.length === 0 ? (

    No sales data available yet

    ) : (
    {sales.map(sale => ( ))}
    Date Transaction ID Items Payment Method Total
    {new Date(sale.date).toLocaleDateString()} {sale._id} {sale.items} {sale.paymentMethod === 'cash' ? 'Cash' : 'Credit Card'} ${sale.total.toFixed(2)}
    )}
    {/* Low Stock Items */}

    Low Stock Items

    {products.filter(product => product.stock < 10).length === 0 ? (

    No low stock items

    ) : (
    {products.filter(product => product.stock < 10).map(product => ( ))}
    Name Category Current Stock Status
    {product.name}
    {product.category} {product.stock} 5 ? 'bg-yellow-100 text-yellow-800' : 'bg-red-100 text-red-800' }`}> {product.stock > 5 ? 'Low Stock' : 'Critical'}
    )}
    )}
    {/* Checkout Modal */} {showCheckoutModal && (

    Checkout

    Order Summary

    {cart.map(item => (
    {item.name} x {item.quantity} ${(item.price * item.quantity).toFixed(2)}
    ))}
    Subtotal ${calculateTotal().toFixed(2)}
    Tax (7%) ${(calculateTotal() * 0.07).toFixed(2)}
    Total ${(calculateTotal() * 1.07).toFixed(2)}

    Payment Method

    {paymentMethod === 'cash' && (
    setAmountReceived(e.target.value)} className="pl-10 pr-4 py-2 w-full border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#4fd1c5]" placeholder="0.00" />
    {parseFloat(amountReceived) > 0 && (
    Change: ${Math.max(0, parseFloat(amountReceived) - (calculateTotal() * 1.07)).toFixed(2)}
    )}
    )}
    )} {/* Receipt Modal */} {showReceiptModal && currentReceipt && (

    Receipt

    Your Business Name

    123 Main Street, City, State

    Tel: (123) 456-7890

    Receipt #: {currentReceipt._id}
    Date: {new Date(currentReceipt.date).toLocaleString()}
    Item
    Qty Price Total
    {currentReceipt.items.map(item => (
    {item.name}
    {item.quantity} ${item.price.toFixed(2)} ${(item.price * item.quantity).toFixed(2)}
    ))}
    Subtotal ${(currentReceipt.total).toFixed(2)}
    Tax (7%) ${(currentReceipt.total * 0.07).toFixed(2)}
    Total ${(currentReceipt.total * 1.07).toFixed(2)}
    {currentReceipt.paymentMethod === 'cash' && ( <>
    Amount Received ${parseFloat(currentReceipt.amountReceived).toFixed(2)}
    Change ${currentReceipt.change.toFixed(2)}
    )}
    Payment Method {currentReceipt.paymentMethod === 'cash' ? 'Cash' : 'Credit Card'}

    Thank you for your purchase!

    Please come again

    )} {/* Add Product Modal */} {showAddProductModal && (

    Add New Product

    setNewProduct({...newProduct, name: e.target.value})} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#4fd1c5]" placeholder="Enter product name" />
    setNewProduct({...newProduct, price: e.target.value})} className="pl-10 pr-4 py-2 w-full border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#4fd1c5]" placeholder="0.00" step="0.01" />
    setNewProduct({...newProduct, stock: e.target.value})} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#4fd1c5]" placeholder="Enter quantity" />
    setNewProduct({...newProduct, barcode: e.target.value})} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#4fd1c5]" placeholder="Enter barcode" />
    )} {/* Register User Modal */} {showRegisterModal && (

    Register New User

    setNewUser({...newUser, username: e.target.value})} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#4fd1c5]" placeholder="Enter username" />
    setNewUser({...newUser, password: e.target.value})} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#4fd1c5]" placeholder="Enter password" />
    setNewUser({...newUser, confirmPassword: e.target.value})} className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-[#4fd1c5]" placeholder="Confirm password" />
    )}
    ); } // Login Screen Component function LoginScreen({ onLogin, registeredUsers }) { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const [showPassword, setShowPassword] = useState(false); const handleSubmit = (e) => { e.preventDefault(); // Simple validation if (!username || !password) { setError('Please enter both username and password'); return; } // Check if user exists const user = registeredUsers.find(u => u.username === username && u.password === password); if (user) { // Real login onLogin({ username: user.username, role: user.role }, false); } else { setError('Invalid username or password'); } }; const handleDemoLogin = () => { // Demo login onLogin({ username: 'demo', role: 'admin' }, true); }; return (

    POS System Login

    Enter your credentials to access the system

    setUsername(e.target.value)} className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-[#4fd1c5] focus:border-[#4fd1c5] focus:z-10 sm:text-sm" placeholder="Username" />
    setPassword(e.target.value)} className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-[#4fd1c5] focus:border-[#4fd1c5] focus:z-10 sm:text-sm pr-10" placeholder="Password" />
    {error && (
    {error}
    )}

    Default accounts:

    Admin

    Username: admin

    Password: admin123

    Manager

    Username: manager

    Password: manager123

    Cashier

    Username: cashier

    Password: cashier123

    Or
    ); }