import React, { useState, useEffect, useMemo } from 'react'; import { Plus, Search, ShoppingCart, History, Download, TrendingUp, Package, Store, Users, ChevronRight, LogOut, Trash2, AlertCircle, FileSpreadsheet } from 'lucide-react'; import { initializeApp } from 'firebase/app'; import { getFirestore, collection, doc, setDoc, getDoc, getDocs, onSnapshot, updateDoc, addDoc, deleteDoc, query, orderBy } from 'firebase/firestore'; import { getAuth, signInAnonymously, signInWithCustomToken, onAuthStateChanged } from 'firebase/auth'; // --- CONFIGURATION --- const firebaseConfig = JSON.parse(__firebase_config); const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); const appId = typeof __app_id !== 'undefined' ? __app_id : 'sneaker-sales-manager'; // --- PRE-DEFINED DATA FROM CSV (Fallback & Initial Seed) --- const INITIAL_INVENTORY = [ { id: "1", sku: "DC0774-001", size: "38.5", count: 1, price: 6400 }, { id: "2", sku: "DC0774-001", size: "38", count: 1, price: 6000 }, { id: "3", sku: "DC0774-001", size: "37.5", count: 1, price: 5700 }, { id: "4", sku: "MR530AD", size: "40", count: 1, price: 6500 }, { id: "5", sku: "MR530AD", size: "39.5", count: 1, price: 6000 }, { id: "6", sku: "MR530AD", size: "38.5", count: 1, price: 6000 }, { id: "7", sku: "DC0774-105", size: "39", count: 1, price: 6775 }, { id: "8", sku: "DD1503-103", size: "40", count: 1, price: 5720 }, { id: "9", sku: "DD1391-103", size: "45", count: 1, price: 6072 }, ]; export default function App() { const [user, setUser] = useState(null); const [inventory, setInventory] = useState([]); const [sales, setSales] = useState([]); const [loading, setLoading] = useState(true); const [view, setView] = useState('inventory'); // 'inventory' | 'sales' | 'stats' const [searchTerm, setSearchTerm] = useState(''); const [selectedItem, setSelectedItem] = useState(null); const [showSaleModal, setShowSaleModal] = useState(false); const [saleChannel, setSaleChannel] = useState('Личная встреча'); const [customPrice, setCustomPrice] = useState(''); // 1. Auth Init useEffect(() => { const initAuth = async () => { try { if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) { await signInWithCustomToken(auth, __initial_auth_token); } else { await signInAnonymously(auth); } } catch (err) { console.error("Auth error:", err); } }; initAuth(); const unsubscribe = onAuthStateChanged(auth, (u) => { setUser(u); }); return () => unsubscribe(); }, []); // 2. Data Sync useEffect(() => { if (!user) return; const invCol = collection(db, 'artifacts', appId, 'public', 'data', 'inventory'); const salesCol = collection(db, 'artifacts', appId, 'public', 'data', 'sales'); const unsubInv = onSnapshot(invCol, (snapshot) => { const data = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); // If empty, seed from initial data if (data.length === 0) { INITIAL_INVENTORY.forEach(async (item) => { await setDoc(doc(invCol, item.id), item); }); } setInventory(data); setLoading(false); }, (err) => console.error(err)); const unsubSales = onSnapshot(salesCol, (snapshot) => { const data = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); setSales(data.sort((a, b) => b.timestamp - a.timestamp)); }, (err) => console.error(err)); return () => { unsubInv(); unsubSales(); }; }, [user]); // Handlers const handleSale = async () => { if (!selectedItem || !user) return; const salePrice = parseFloat(customPrice) || selectedItem.price; const saleData = { sku: selectedItem.sku, size: selectedItem.size, originalPrice: selectedItem.price, salePrice: salePrice, channel: saleChannel, timestamp: Date.now(), sellerId: user.uid }; try { // 1. Add to sales await addDoc(collection(db, 'artifacts', appId, 'public', 'data', 'sales'), saleData); // 2. Update inventory (decrement count) const invDocRef = doc(db, 'artifacts', appId, 'public', 'data', 'inventory', selectedItem.id); if (selectedItem.count > 1) { await updateDoc(invDocRef, { count: selectedItem.count - 1 }); } else { await deleteDoc(invDocRef); } setShowSaleModal(false); setSelectedItem(null); setCustomPrice(''); } catch (err) { alert("Ошибка при сохранении продажи: " + err.message); } }; const exportToCSV = () => { const headers = ["Дата", "Артикул", "Размер", "Цена закупа", "Цена продажи", "Канал"]; const rows = sales.map(s => [ new Date(s.timestamp).toLocaleString('ru-RU'), s.sku, s.size, s.originalPrice, s.salePrice, s.channel ]); let csvContent = "data:text/csv;charset=utf-8," + [headers, ...rows].map(e => e.join(",")).join("\n"); const encodedUri = encodeURI(csvContent); const link = document.createElement("a"); link.setAttribute("href", encodedUri); link.setAttribute("download", `sales_export_${new Date().toLocaleDateString()}.csv`); document.body.appendChild(link); link.click(); document.body.removeChild(link); }; const filteredInventory = useMemo(() => { return inventory.filter(item => item.sku.toLowerCase().includes(searchTerm.toLowerCase()) ); }, [inventory, searchTerm]); if (loading) { return (
); } return (
{/* Header */}

SneakerSales

{/* Main Content */}
{view === 'inventory' && (
setSearchTerm(e.target.value)} />
{filteredInventory.length > 0 ? ( filteredInventory.map((item) => (
{ setSelectedItem(item); setShowSaleModal(true); }} className="bg-white p-4 rounded-xl border border-slate-200 flex items-center justify-between hover:border-indigo-300 hover:shadow-md transition-all cursor-pointer active:scale-[0.98]" >

{item.sku}

Размер: {item.size} В наличии: {item.count}
{item.price} ₽
Продать →
)) ) : (

Ничего не найдено

)}
)} {view === 'sales' && (

История продаж

{sales.length > 0 ? ( sales.map((sale) => (
{sale.sku}
{new Date(sale.timestamp).toLocaleString('ru-RU')}
{sale.channel} р. {sale.size}
+{sale.salePrice} ₽
закуп {sale.originalPrice}
)) ) : (
Пока нет продаж
)}
)} {view === 'stats' && (

Всего пар

{inventory.reduce((acc, i) => acc + i.count, 0)}

Продано

{sales.length}

Выручка по каналам

{['Маркет', 'Авито', 'Личная встреча'].map(channel => { const total = sales.filter(s => s.channel === channel).reduce((acc, s) => acc + s.salePrice, 0); const count = sales.filter(s => s.channel === channel).length; return (
{channel}
{total} ₽
{count} шт.
) })}
)}
{/* Navigation Bar */} {/* Sale Modal */} {showSaleModal && selectedItem && (

Продажа товара

{selectedItem.sku} • Размер {selectedItem.size}

{['Маркет', 'Авито', 'Встреча'].map((ch) => { const actualCh = ch === 'Встреча' ? 'Личная встреча' : ch; return ( ) })}
setCustomPrice(e.target.value)} />
)}
); }