import React, { useState, useEffect, useMemo } from 'react'; import { initializeApp } from "firebase/app"; import { getAuth, signInWithEmailAndPassword, createUserWithEmailAndPassword, signOut, onAuthStateChanged, signInAnonymously, signInWithCustomToken } from "firebase/auth"; import { getFirestore, collection, doc, setDoc, getDoc, onSnapshot, deleteDoc, updateDoc, addDoc, query, orderBy } from "firebase/firestore"; import { Home, ShoppingCart, Users, Receipt, PieChart, Settings, Plus, Edit, Trash2, Search, LogOut, Globe, ChevronDown, Check, UserPlus, AlertCircle, Loader2, ArrowLeft, Eye, CreditCard, User, Phone, FileText, Calendar, Wallet, TrendingUp, ShoppingBag } from 'lucide-react'; // --- Firebase Configuration --- const firebaseConfig = { apiKey: "AIzaSyDoG1aWaNi9QNe0oMeGCEM7BRCaOhnZB_w", authDomain: "naynnay.firebaseapp.com", projectId: "naynnay", storageBucket: "naynnay.firebasestorage.app", messagingSenderId: "558678602864", appId: "1:558678602864:web:f8c6b9f38d4edda08430b5", measurementId: "G-R3SYVK6PS2" }; const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); // Safe App ID Initialization const rawAppId = typeof __app_id !== 'undefined' ? __app_id : null; const APP_ID = (rawAppId && rawAppId !== "null") ? String(rawAppId) : 'nay-n-nay-pos'; // --- UI Design Constants --- const styles = { bgApp: "bg-[#ffeaea] min-h-screen text-[#5c3a3a] font-sans", neoCard: "bg-[#ffeaea] rounded-2xl shadow-[8px_8px_16px_#d9c7c7,-8px_-8px_16px_#ffffff] border border-white/40", neoInput: "w-full bg-[#ffeaea] rounded-xl shadow-[inset_5px_5px_10px_#d9c7c7,inset_-5px_-5px_10px_#ffffff] p-4 focus:outline-none focus:ring-2 focus:ring-red-300 transition-all text-[#5c3a3a] placeholder-[#b89c9c]", neoBtn: "bg-[#ffeaea] rounded-xl shadow-[5px_5px_10px_#d9c7c7,-5px_-5px_10px_#ffffff] active:shadow-[inset_5px_5px_10px_#d9c7c7,inset_-5px_-5px_10px_#ffffff] p-3 font-bold transition-all flex items-center justify-center gap-2 disabled:opacity-50", neoBtnPrimary: "bg-[#ff6b6b] text-white rounded-xl shadow-[5px_5px_10px_#d9c7c7,-5px_-5px_10px_#ffffff] active:shadow-[inset_5px_5px_10px_#cc5555,inset_-5px_-5px_10px_#ff8282] p-3 font-bold transition-all flex items-center justify-center gap-2 disabled:opacity-50 hover:bg-[#ff5252]", headerText: "text-2xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-red-600 to-red-400 drop-shadow-sm", }; // --- Dictionary for i18n --- const dict = { my: { system: "စနစ်", purchase: "ဝယ်ယူမှု", sale: "ရောင်းချမှု", customer: "ဖောက်သည်", expense: "အသုံးစရိတ်", report: "အစီရင်ခံစာ", login: "အကောင့်ဝင်ရန်", signup: "အကောင့်သစ်ဖွင့်ရန်", email: "အီးမေးလ်", password: "စကားဝှက်", guestLogin: "Guest (အကောင့်မပါဘဲ) ဝင်မည်", logout: "ထွက်မည်", langSwitch: "English သို့ပြောင်းရန်", add: "အသစ်ထည့်မည်", save: "သိမ်းမည်", cancel: "မလုပ်တော့ပါ", edit: "ပြင်မည်", delete: "ဖျက်မည်", search: "ရှာဖွေရန်...", name: "အမည်", cost: "အရင်း", price: "ရောင်းဈေး", qty: "အရေအတွက်", expDate: "သက်တမ်းကုန်ရက်", total: "စုစုပေါင်း", paid: "ငွေချေပြီး", unpaid: "ငွေမချေရသေး", serviceFee: "ဝန်ဆောင်ခ", payAmount: "ပေးချေငွေ", balance: "လက်ကျန်ငွေ", age: "အသက်", gender: "ကျား/မ", phone: "ဖုန်းနံပါတ်", diagnosis: "ရောဂါ/မှတ်ချက်", daily: "နေ့စဉ်", weekly: "အပတ်စဉ်", monthly: "လစဉ်", yearly: "နှစ်စဉ်", grandTotal: "စုစုပေါင်း အသားတင်", bestSelling: "အရောင်းရဆုံး ပစ္စည်းများ", inventory: "လက်ကျန် ပစ္စည်းတန်ဖိုး", deductProfit: "အမြတ်ထဲမှ နုတ်မည်", date: "ရက်စွဲ", selectCustomer: "ဖောက်သည်ရွေးပါ", addToCart: "ခြင်းထဲထည့်မည်", payBalance: "လက်ကျန်ငွေရှင်းမည်", details: "မှတ်တမ်းကြည့်မည်", salesHistory: "ဝယ်ယူမှု မှတ်တမ်းများ", payNow: "ငွေချေမည်", paymentAmount: "ပေးသွင်းငွေ ပမာဏ" }, en: { system: "System", purchase: "Purchase", sale: "Sale", customer: "Customer", expense: "Expense", report: "Report", login: "Log In", signup: "Sign Up", email: "Email", password: "Password", guestLogin: "Login as Guest", logout: "Log Out", langSwitch: "မြန်မာစာသို့ပြောင်းရန်", add: "Add New", save: "Save", cancel: "Cancel", edit: "Edit", delete: "Delete", search: "Search...", name: "Name", cost: "Cost", price: "Price", qty: "Quantity", expDate: "Expiry Date", total: "Total", paid: "Paid", unpaid: "Unpaid", serviceFee: "Service Fee", payAmount: "Pay Amount", balance: "Balance", age: "Age", gender: "Gender", phone: "Phone", diagnosis: "Diagnosis", daily: "Daily", weekly: "Weekly", monthly: "Monthly", yearly: "Yearly", grandTotal: "Grand Total", bestSelling: "Best Selling", inventory: "Inventory Asset", deductProfit: "Deduct from Profit", date: "Date", selectCustomer: "Select Customer", addToCart: "Add to Cart", payBalance: "Pay Balance", details: "View Details", salesHistory: "Detailed Sales History", payNow: "Pay Now", paymentAmount: "Payment Amount" } }; // ============================================================================ // MAIN APP COMPONENT // ============================================================================ export default function App() { const [user, setUser] = useState(null); const [lang, setLang] = useState('my'); const [currentTab, setCurrentTab] = useState('customer'); // Default Tab const t = dict[lang]; // Custom Dialog State const [dialog, setDialog] = useState({ isOpen: false, type: 'alert', message: '', onConfirm: null, isProcessing: false }); const showAlert = (message) => setDialog({ isOpen: true, type: 'alert', message, onConfirm: null, isProcessing: false }); const showConfirm = (message, onConfirm) => setDialog({ isOpen: true, type: 'confirm', message, onConfirm, isProcessing: false }); const closeDialog = () => setDialog(prev => ({ ...prev, isOpen: false })); // Global Data States const [products, setProducts] = useState([]); const [sales, setSales] = useState([]); const [customers, setCustomers] = useState([]); const [expenses, setExpenses] = useState([]); // Auth Listener useEffect(() => { const initAuth = async () => { if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) { try { await signInWithCustomToken(auth, __initial_auth_token); } catch(e){ console.error(e); } } }; initAuth(); const unsubscribe = onAuthStateChanged(auth, (u) => { setUser(u); if(u && currentTab === 'system') setCurrentTab('customer'); }); return () => unsubscribe(); }, []); // Data Fetching (FIXED MAPPING LOGIC TO GUARANTEE IDs) useEffect(() => { if (!user || !APP_ID) return; const safeUserId = String(user.uid); const errHandler = (err) => console.error("Firebase Sync Error:", err); // Note: { ...d.data(), id: d.id } ensures that document ID overwrites any accidental null ID in the data itself. const unSubP = onSnapshot(collection(db, 'artifacts', APP_ID, 'users', safeUserId, 'products'), snap => setProducts(snap.docs.map(d => ({...d.data(), id: d.id}))), errHandler); const unSubS = onSnapshot(collection(db, 'artifacts', APP_ID, 'users', safeUserId, 'sales'), snap => setSales(snap.docs.map(d => ({...d.data(), id: d.id}))), errHandler); const unSubC = onSnapshot(collection(db, 'artifacts', APP_ID, 'users', safeUserId, 'customers'), snap => setCustomers(snap.docs.map(d => ({...d.data(), id: d.id}))), errHandler); const unSubE = onSnapshot(collection(db, 'artifacts', APP_ID, 'users', safeUserId, 'expenses'), snap => setExpenses(snap.docs.map(d => ({...d.data(), id: d.id}))), errHandler); return () => { unSubP(); unSubS(); unSubC(); unSubE(); }; }, [user]); // Deep Data Connection: Map all sales dynamically into each customer const customersWithData = useMemo(() => { return customers.map(c => { const custSales = sales.filter(s => s.customerId === c.id); const balance = custSales.reduce((sum, s) => sum + (Number(s.balance) || 0), 0); const totalSpent = custSales.reduce((sum, s) => sum + (Number(s.grandTotal) || 0), 0); return { ...c, balance, totalSpent, custSales }; }); }, [customers, sales]); // Auth Handlers const handleAuth = async (e, isLogin, email, password) => { e.preventDefault(); try { if (isLogin) await signInWithEmailAndPassword(auth, email, password); else await createUserWithEmailAndPassword(auth, email, password); } catch (error) { showAlert("အကောင့်ဝင်ရာတွင် အမှားဖြစ်နေပါသည်:\n" + error.message); } }; const handleGuestLogin = async () => { try { await signInAnonymously(auth); } catch (error) { showAlert("Guest အနေဖြင့် ဝင်ရောက်ရာတွင် အမှားဖြစ်နေပါသည်:\n" + error.message); } }; return ( <> {!user ? ( ) : (
{/* Sidebar Navigation */} {/* Main Content Area */}
{currentTab === 'system' && } {currentTab === 'purchase' && } {currentTab === 'sale' && } {currentTab === 'customer' && } {currentTab === 'expense' && } {currentTab === 'report' && }
)} {/* Global Dialog Modal */} {dialog.isOpen && (

{dialog.type === 'confirm' ? 'သေချာပါသလား?' : 'အသိပေးချက်'}

{dialog.message}

{dialog.type === 'confirm' && ( )}
)} ); } // ============================================================================ // COMPONENT: AUTH SCREEN // ============================================================================ const AuthScreen = ({ handleAuth, handleGuest, t, lang, setLang }) => { const [isLogin, setIsLogin] = useState(true); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); return (

Nay N Nay
POS

handleAuth(e, isLogin, email, password)} className="space-y-6">
setEmail(e.target.value)} />
setPassword(e.target.value)} />

OR
); }; // ============================================================================ // COMPONENT: SYSTEM TAB // ============================================================================ const SystemTab = ({ user, t, lang, setLang }) => (

{t.system}

Logged in as: {user.isAnonymous ? "Guest User" : user.email}


); // ============================================================================ // COMPONENT: PURCHASE TAB (Products) // ============================================================================ const PurchaseTab = ({ t, products, userId, showAlert, showConfirm }) => { const [search, setSearch] = useState(''); const [showForm, setShowForm] = useState(false); const [form, setForm] = useState({ id: null, name: '', cost: '', price: '', qty: '', expDate: '' }); const sortedProducts = useMemo(() => { return [...products].filter(p => (p.name || '').toLowerCase().includes(search.toLowerCase())).sort((a, b) => (a.name || '').localeCompare(b.name || '')); }, [products, search]); const handleSubmit = async (e) => { e.preventDefault(); try { const data = { name: form.name, cost: Number(form.cost), price: Number(form.price), quantity: Number(form.qty), expiredDate: form.expDate }; const safeUserId = String(userId); if (form.id) await updateDoc(doc(db, 'artifacts', APP_ID, 'users', safeUserId, 'products', String(form.id)), data); else await addDoc(collection(db, 'artifacts', APP_ID, 'users', safeUserId, 'products'), data); setShowForm(false); setForm({ id: null, name: '', cost: '', price: '', qty: '', expDate: '' }); showAlert("အောင်မြင်စွာ သိမ်းဆည်းပြီးပါပြီ။"); } catch (err) { showAlert("Data သိမ်းဆည်းရာတွင် အမှားဖြစ်နေပါသည်: \n" + err.message); } }; const deleteItem = (id) => { if (!id) return; showConfirm('ဤပစ္စည်းကို စာရင်းမှ ဖယ်ရှားရန် သေချာပါသလား?', async () => { try { await deleteDoc(doc(db, 'artifacts', APP_ID, 'users', String(userId), 'products', String(id))); showAlert("အောင်မြင်စွာ ဖယ်ရှားပြီးပါပြီ။"); } catch (err) { showAlert("ဖျက်ရာတွင် အမှားဖြစ်နေပါသည်: \n" + err.message); } }); }; const getRowStyle = (p) => { if (!p.expiredDate) return styles.neoCard; const today = new Date(); const exp = new Date(p.expiredDate); const monthsDiff = (exp.getFullYear() - today.getFullYear()) * 12 + (exp.getMonth() - today.getMonth()); const isLowQty = p.quantity < 10; const isExpiring = monthsDiff < 3 && monthsDiff >= 0; if (isLowQty && isExpiring) return "bg-gradient-to-r from-red-200 to-yellow-200 border-red-300"; if (isLowQty) return "bg-red-100 border-red-300"; if (isExpiring) return "bg-yellow-100 border-yellow-300"; return styles.neoCard; }; return (

{t.purchase} (ပစ္စည်းစာရင်း)

{showForm && (
setForm({...form, name: e.target.value})} className={styles.neoInput} /> setForm({...form, cost: e.target.value})} className={styles.neoInput} /> setForm({...form, price: e.target.value})} className={styles.neoInput} /> setForm({...form, qty: e.target.value})} className={styles.neoInput} /> setForm({...form, expDate: e.target.value})} className={styles.neoInput} />
)}
setSearch(e.target.value)} className={`${styles.neoInput} pl-12`} />
{sortedProducts.length === 0 &&

No products found.

} {sortedProducts.map(p => (

{p.name}

{t.cost}: {p.cost} | {t.price}: {p.price} | {t.qty}: {p.quantity} | EXP: {p.expiredDate}

))}
); }; // ============================================================================ // COMPONENT: EXPENSE TAB // ============================================================================ const ExpenseTab = ({ t, expenses, userId, showAlert, showConfirm }) => { const [showForm, setShowForm] = useState(false); const [form, setForm] = useState({ id: null, name: '', amount: '', deductProfit: true }); const handleSubmit = async (e) => { e.preventDefault(); try { const data = { name: form.name, amount: Number(form.amount), deductProfit: form.deductProfit, date: new Date().toISOString() }; const safeUserId = String(userId); if (form.id) await updateDoc(doc(db, 'artifacts', APP_ID, 'users', safeUserId, 'expenses', String(form.id)), data); else await addDoc(collection(db, 'artifacts', APP_ID, 'users', safeUserId, 'expenses'), data); setShowForm(false); setForm({ id: null, name: '', amount: '', deductProfit: true }); showAlert("အသုံးစရိတ် သိမ်းဆည်းပြီးပါပြီ။"); } catch (err) { showAlert("Data သိမ်းဆည်းရာတွင် အမှားဖြစ်နေပါသည်:\n" + err.message); } }; const deleteItem = (id) => { if (!id) return; showConfirm('ဤအသုံးစရိတ်ကို ဖယ်ရှားရန် သေချာပါသလား?', async () => { try { await deleteDoc(doc(db, 'artifacts', APP_ID, 'users', String(userId), 'expenses', String(id))); showAlert("အောင်မြင်စွာ ဖယ်ရှားပြီးပါပြီ။"); } catch (err) { showAlert("ဖျက်ရာတွင် အမှားဖြစ်နေပါသည်:\n" + err.message); } }); }; return (

{t.expense}

{showForm && (
setForm({...form, name: e.target.value})} className={styles.neoInput} /> setForm({...form, amount: e.target.value})} className={styles.neoInput} />
)}
{expenses.sort((a,b)=>new Date(b.date)-new Date(a.date)).map(e => (

{e.name}

Amount: {e.amount} | {e.deductProfit ? 'Deducts Profit' : 'Does not deduct'}

))}
); }; // ============================================================================ // COMPONENT: REPORT TAB // ============================================================================ const ReportTab = ({ t, products, sales, expenses }) => { const [filter, setFilter] = useState('daily'); const filteredData = useMemo(() => { const now = new Date(); let fSales = []; let fExpenses = []; const isSameDay = (d1, d2) => d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate(); const isSameWeek = (d1, d2) => { const oneJan = new Date(d1.getFullYear(),0,1); const w1 = Math.ceil((((d1.getTime() - oneJan.getTime()) / 86400000) + oneJan.getDay()+1)/7); const oneJan2 = new Date(d2.getFullYear(),0,1); const w2 = Math.ceil((((d2.getTime() - oneJan2.getTime()) / 86400000) + oneJan2.getDay()+1)/7); return w1 === w2 && d1.getFullYear() === d2.getFullYear(); }; const isSameMonth = (d1, d2) => d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth(); const isSameYear = (d1, d2) => d1.getFullYear() === d2.getFullYear(); fSales = sales.filter(s => { const d = new Date(s.date); if(filter==='daily') return isSameDay(d, now); if(filter==='weekly') return isSameWeek(d, now); if(filter==='monthly') return isSameMonth(d, now); if(filter==='yearly') return isSameYear(d, now); return true; }); fExpenses = expenses.filter(e => { if(!e.deductProfit) return false; const d = new Date(e.date); if(filter==='daily') return isSameDay(d, now); if(filter==='weekly') return isSameWeek(d, now); if(filter==='monthly') return isSameMonth(d, now); if(filter==='yearly') return isSameYear(d, now); return true; }); let totalSalePrice = 0; let totalCost = 0; let totalServiceFee = 0; let itemSalesCount = {}; fSales.forEach(s => { totalServiceFee += Number(s.serviceFee || 0); s.items.forEach(i => { totalSalePrice += (i.price * i.qty); totalCost += (i.cost * i.qty); itemSalesCount[i.productId] = (itemSalesCount[i.productId] || 0) + i.qty; }); }); const totalExpense = fExpenses.reduce((sum, e) => sum + Number(e.amount), 0); const netProfit = (totalSalePrice - totalCost) + totalServiceFee - totalExpense; const bestSellers = Object.keys(itemSalesCount).map(id => { const p = products.find(x => x.id === id); return { name: p ? p.name : 'Unknown', qty: itemSalesCount[id] }; }).sort((a,b) => b.qty - a.qty).slice(0, 10); return { totalSalePrice: totalSalePrice + totalServiceFee, netProfit, bestSellers, totalExpense }; }, [sales, expenses, products, filter]); const inventoryAsset = useMemo(() => { return products.reduce((sum, p) => sum + (p.cost * p.quantity), 0); }, [products]); return (

{t.report}

{['daily', 'weekly', 'monthly', 'yearly', 'grand'].map(f => ( ))}

Total Sales ({filter})

{filteredData.totalSalePrice.toLocaleString()}

Net Profit

{filteredData.netProfit.toLocaleString()}

(Sales - Cost + Service Fee - Deductible Expenses)

{t.bestSelling} (Top 10)

{filteredData.bestSellers.length === 0 &&

No data

} {filteredData.bestSellers.map((b, i) => (
{i+1}. {b.name}{b.qty} sold
))}

{t.inventory}

{inventoryAsset.toLocaleString()}

); }; // ============================================================================ // COMPONENT: SALE TAB // ============================================================================ const SaleTab = ({ t, products, customersWithData, sales, userId, showAlert, showConfirm }) => { const [cart, setCart] = useState([]); const [selectedProduct, setSelectedProduct] = useState(''); const [qty, setQty] = useState(1); const [customerId, setCustomerId] = useState(''); const [serviceFee, setServiceFee] = useState(0); const [payAmountInput, setPayAmountInput] = useState(''); // Real-time Calculation const itemsTotal = cart.reduce((sum, item) => sum + (item.price * item.qty), 0); const grandTotal = itemsTotal + Number(serviceFee || 0); const payAmount = Number(payAmountInput || 0); const balance = grandTotal - payAmount; const isPaid = balance <= 0 && grandTotal > 0; const addToCart = () => { const p = products.find(x => x.id === selectedProduct); if (!p) return; if (p.quantity < qty) return showAlert('စတော့စာရင်းတွင် ပစ္စည်းအရေအတွက် မလောက်ပါ!'); const existing = cart.find(c => c.productId === p.id); if (existing) { if (p.quantity < existing.qty + Number(qty)) return showAlert('စတော့စာရင်းတွင် ပစ္စည်းအရေအတွက် မလောက်ပါ!'); setCart(cart.map(c => c.productId === p.id ? { ...c, qty: c.qty + Number(qty) } : c)); } else { setCart([...cart, { productId: p.id, name: p.name, price: p.price, cost: p.cost, qty: Number(qty) }]); } setQty(1); setSelectedProduct(''); }; const removeCart = (idx) => setCart(cart.filter((_, i) => i !== idx)); const handleCheckout = async () => { if (!customerId) return showAlert('ကျေးဇူးပြု၍ Customer အမည်ကို ရွေးချယ်ပါ။ (မရှိပါက Customer စာမျက်နှာတွင် အရင်ထည့်ပါ)'); if (cart.length === 0) return showAlert('ရောင်းချရန် ပစ္စည်းများကို ခြင်းထဲသို့ အရင်ထည့်ပါ။'); if (payAmount > grandTotal) return showAlert('ပေးချေငွေသည် စုစုပေါင်းကျသင့်ငွေထက် များနေပါသည်။'); try { const customerObj = customersWithData.find(c => c.id === customerId); const safeUserId = String(userId); const saleDateString = new Date().toISOString(); const saleData = { customerId: customerId, customerName: customerObj ? customerObj.name : 'Unknown', date: saleDateString, items: cart, itemsTotal: itemsTotal, serviceFee: Number(serviceFee), grandTotal: grandTotal, payAmount: payAmount, balance: balance > 0 ? balance : 0, status: isPaid ? 'Paid' : 'Unpaid' }; for (let item of cart) { const p = products.find(x => x.id === item.productId); if (p && p.id) { await updateDoc(doc(db, 'artifacts', APP_ID, 'users', safeUserId, 'products', String(p.id)), { quantity: p.quantity - item.qty }); } } await addDoc(collection(db, 'artifacts', APP_ID, 'users', safeUserId, 'sales'), saleData); setCart([]); setCustomerId(''); setServiceFee(0); setPayAmountInput(''); showAlert("အောင်မြင်စွာ ရောင်းချပြီးပါပြီ။\nသက်ဆိုင်ရာ Customer ၏ မှတ်တမ်းထဲသို့ တိုက်ရိုက် ရောက်ရှိသွားပါမည်။"); } catch (err) { showAlert("ရောင်းချရာတွင် အမှားဖြစ်နေပါသည်: \n" + err.message); } }; const deleteSale = (sale) => { if (!sale || !sale.id) return; showConfirm('ဤရောင်းချမှုမှတ်တမ်းကို ဖျက်ပြီး ပစ္စည်းအရေအတွက်ကို စာရင်းထဲသို့ ပြန်ပေါင်းထည့်မလား?', async () => { try { const safeUserId = String(userId); for (let item of sale.items) { const p = products.find(x => x.id === item.productId); if (p && p.id) { await updateDoc(doc(db, 'artifacts', APP_ID, 'users', safeUserId, 'products', String(p.id)), { quantity: p.quantity + item.qty }); } } await deleteDoc(doc(db, 'artifacts', APP_ID, 'users', safeUserId, 'sales', String(sale.id))); showAlert("ရောင်းချမှုမှတ်တမ်းကို ဖျက်သိမ်းပြီး ပစ္စည်းများကို ပြန်လည်ပေါင်းထည့်ပြီးပါပြီ။"); } catch (err) { showAlert("ဖျက်ရာတွင် အမှားဖြစ်နေပါသည်:\n" + err.message); } }); }; return (

{t.sale} (ဘေလ်ဖွင့်ရန်)

setQty(e.target.value)} className={`${styles.neoInput} w-20 text-center`} />
{cart.length === 0 &&

ခြင်းထဲတွင် ပစ္စည်းမရှိသေးပါ

} {cart.map((c, i) => (
{c.name} {c.price} x {c.qty}
{(c.price * c.qty).toLocaleString()}
))}
ပစ္စည်းတန်ဖိုး စုစုပေါင်း: {itemsTotal.toLocaleString()}
{t.serviceFee}: setServiceFee(e.target.value)} placeholder="0" className={`${styles.neoInput} w-32 py-1.5 h-9 text-right font-bold`} />
ကျသင့်ငွေ စုစုပေါင်း: {grandTotal.toLocaleString()}
ပေးသွင်းငွေ (Pay Amount): setPayAmountInput(e.target.value)} placeholder="0" className={`${styles.neoInput} w-32 py-1.5 h-9 text-right font-bold text-green-700 bg-white/70`} />
0 ? 'text-green-600' : 'text-red-500'}`}> {isPaid && grandTotal > 0 ? 'ငွေချေမှု အခြေအနေ:' : 'အကြွေးကျန် (Balance):'} {isPaid && grandTotal > 0 ? t.paid : balance.toLocaleString()}

ယနေ့ အရောင်းမှတ်တမ်းများ

{sales.length === 0 &&

မှတ်တမ်းမရှိသေးပါ။

} {sales.sort((a,b) => new Date(b.date) - new Date(a.date)).slice(0, 15).map(s => { const customerNameDisplay = s.customerName || 'Unknown'; return (
{customerNameDisplay} {new Date(s.date).toLocaleTimeString('en-US', {hour:'2-digit', minute:'2-digit'})}
{s.status}
{s.items.map((i, idx) => (
{i.name} x{i.qty}
))}
Total: {s.grandTotal.toLocaleString()} {s.balance > 0 && Bal: {s.balance.toLocaleString()}}
); })}
); }; // ============================================================================ // COMPONENT: CUSTOMER TAB // ============================================================================ const CustomerTab = ({ t, customersWithData, sales, userId, showAlert, showConfirm }) => { const [activeView, setActiveView] = useState('list'); const [search, setSearch] = useState(''); const [sortOrder, setSortOrder] = useState('alpha'); const [form, setForm] = useState({ id: null, name: '', age: '', gender: 'Male', phone1: '', phone2: '', phone3: '', diagnosis: '' }); const [selectedCustomerId, setSelectedCustomerId] = useState(null); const [payAmountInput, setPayAmountInput] = useState(''); const sortedCustomers = useMemo(() => { let res = [...customersWithData].filter(c => (c.name || '').toLowerCase().includes(search.toLowerCase())); if (sortOrder === 'alpha') res.sort((a, b) => (a.name || '').localeCompare(b.name || '')); else res.sort((a, b) => b.balance - a.balance); return res; }, [customersWithData, search, sortOrder]); const openForm = (c = null) => { if (c) { setForm({ id: c.id, name: c.name, age: c.age || '', gender: c.gender || 'Male', phone1: c.phone1 || '', phone2: c.phone2 || '', phone3: c.phone3 || '', diagnosis: c.diagnosis || '' }); } else { setForm({ id: null, name: '', age: '', gender: 'Male', phone1: '', phone2: '', phone3: '', diagnosis: '' }); } setActiveView('form'); }; const openDetail = (id) => { setSelectedCustomerId(id); setPayAmountInput(''); setActiveView('detail'); }; const handleSaveCustomer = async (e) => { e.preventDefault(); try { const safeUserId = String(userId); // FIXED: Extract id out of form to prevent overwriting document properties incorrectly const { id, ...customerData } = form; if (id) { await updateDoc(doc(db, 'artifacts', APP_ID, 'users', safeUserId, 'customers', String(id)), customerData); showAlert("Customer အချက်အလက်များကို အောင်မြင်စွာ ပြင်ဆင်ပြီးပါပြီ။"); } else { await addDoc(collection(db, 'artifacts', APP_ID, 'users', safeUserId, 'customers'), customerData); showAlert("Customer အချက်အလက်ကို အောင်မြင်စွာ သိမ်းဆည်းပြီးပါပြီ။"); } setActiveView('list'); } catch (err) { showAlert("Data သိမ်းဆည်းရာတွင် အမှားဖြစ်နေပါသည်:\n" + err.message); } }; const handleDeleteCustomer = (id) => { if (!id) return; showConfirm('ဤဖောက်သည်၏ အချက်အလက်များကို အပြီးတိုင် ဖယ်ရှားရန် သေချာပါသလား?', async () => { try { await deleteDoc(doc(db, 'artifacts', APP_ID, 'users', String(userId), 'customers', String(id))); showAlert("အောင်မြင်စွာ ဖယ်ရှားပြီးပါပြီ။"); if(activeView === 'detail') setActiveView('list'); } catch (err) { showAlert("ဖျက်ရာတွင် အမှားဖြစ်နေပါသည်:\n" + err.message); } }); }; const handleIndividualPayment = (customerId, totalUnpaidBalance) => { const payment = Number(payAmountInput); if (!payment || payment <= 0) return showAlert("ပေးသွင်းငွေ ပမာဏကို မှန်ကန်စွာ ထည့်ပါ။"); if (payment > totalUnpaidBalance) return showAlert(`ပေးသွင်းငွေသည် လက်ကျန်အကြွေး (${totalUnpaidBalance.toLocaleString()}) ထက် များနေပါသည်။`); showConfirm(`${payment.toLocaleString()} ကျပ် ငွေချေရန် သေချာပါသလား?\n\n(စနစ်မှ အဟောင်းဆုံး အကြွေးဘေလ်များကို အရင်ဆုံး အလိုအလျောက် ဖြတ်တောက် ရှင်းလင်းပေးသွားပါမည်။)`, async () => { try { const safeUserId = String(userId); let amountLeftToDistribute = payment; const unpaidSales = sales .filter(s => s.customerId === customerId && s.status === 'Unpaid' && Number(s.balance) > 0) .sort((a, b) => new Date(a.date) - new Date(b.date)); for (let s of unpaidSales) { if (amountLeftToDistribute <= 0) break; let currentSaleBalance = Number(s.balance); let currentPaidAmount = Number(s.payAmount || 0); if (amountLeftToDistribute >= currentSaleBalance) { amountLeftToDistribute -= currentSaleBalance; await updateDoc(doc(db, 'artifacts', APP_ID, 'users', safeUserId, 'sales', String(s.id)), { balance: 0, payAmount: currentPaidAmount + currentSaleBalance, status: 'Paid' }); } else { await updateDoc(doc(db, 'artifacts', APP_ID, 'users', safeUserId, 'sales', String(s.id)), { balance: currentSaleBalance - amountLeftToDistribute, payAmount: currentPaidAmount + amountLeftToDistribute }); amountLeftToDistribute = 0; } } setPayAmountInput(''); showAlert("ငွေချေမှု အောင်မြင်ပါသည်။\nသက်ဆိုင်ရာ အရောင်းမှတ်တမ်းများတွင် အကြွေးများ အလိုအလျောက် ရှင်းလင်းသွားပါပြီ။"); } catch (err) { showAlert("ငွေချေရာတွင် အမှားဖြစ်နေပါသည်:\n" + err.message); } }); }; if (activeView === 'form') { return (

{form.id ? 'ဖောက်သည် အချက်အလက် ပြင်ဆင်ရန်' : 'ဖောက်သည် အသစ်ထည့်ရန်'}

setForm({...form, name: e.target.value})} className={styles.neoInput} />
setForm({...form, age: e.target.value})} className={styles.neoInput} />
setForm({...form, phone1: e.target.value})} className={styles.neoInput} />
setForm({...form, phone2: e.target.value})} className={styles.neoInput} />
setForm({...form, phone3: e.target.value})} className={styles.neoInput} />