Nenhuma peça encontrada.
Tente limpar os filtros ou buscar por outra marca.
{product.brand}
{product.name}
{formatPrice(product.price)}
import React, { useState, useEffect, useMemo } from 'react'; import { ShoppingBag, Search, Menu, X, Crown, Trash2, Edit, Plus, LogIn, LogOut, CheckCircle, Image as ImageIcon, ChevronRight, Filter } from 'lucide-react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInAnonymously, signInWithCustomToken, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, collection, onSnapshot, doc, setDoc, deleteDoc } from 'firebase/firestore'; // --- FIREBASE SETUP --- const getFirebaseConfig = () => { if (typeof __firebase_config !== 'undefined' && __firebase_config) { try { return JSON.parse(__firebase_config); } catch(e) {} } return { apiKey: "demo-key", projectId: "demo-project", appId: "12345" }; }; const app = initializeApp(getFirebaseConfig()); const auth = getAuth(app); const db = getFirestore(app); const appId = typeof __app_id !== 'undefined' ? __app_id : 'brecho-grifes-app'; const COLLECTION_PATH = `artifacts/${appId}/public/data/products`; export default function App() { // --- STATE --- const [user, setUser] = useState(null); const [isAdmin, setIsAdmin] = useState(false); const [currentView, setCurrentView] = useState('store'); // 'store', 'admin-login', 'admin-panel' const [products, setProducts] = useState([]); const [cart, setCart] = useState([]); const [isCartOpen, setIsCartOpen] = useState(false); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const [toastMsg, setToastMsg] = useState({ text: '', isError: false }); // Filters const [searchQuery, setSearchQuery] = useState(''); const [activeCategory, setActiveCategory] = useState('todas'); const [activeSubCategory, setActiveSubCategory] = useState('todas'); const [activeSize, setActiveSize] = useState('todos'); // Admin Form State const initialForm = { id: '', name: '', brand: '', category: 'feminino', subCategory: '', size: '', price: '', image: '' }; const [formData, setFormData] = useState(initialForm); const [isEditing, setIsEditing] = useState(false); const [productToDelete, setProductToDelete] = useState(null); // --- FIREBASE AUTH & FETCH --- 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 (error) { console.error('Auth error:', error); } }; initAuth(); const unsubscribe = onAuthStateChanged(auth, setUser); return () => unsubscribe(); }, []); useEffect(() => { if (!user) return; const productsRef = collection(db, 'artifacts', appId, 'public', 'data', 'products'); const unsubscribe = onSnapshot(productsRef, (snapshot) => { const items = []; snapshot.forEach((doc) => items.push({ id: doc.id, ...doc.data() })); setProducts(items.sort((a, b) => b.createdAt - a.createdAt)); }, (err) => console.error("Firestore error:", err)); return () => unsubscribe(); }, [user]); // --- HELPERS --- const showToast = (msg, isError = false) => { setToastMsg({ text: msg, isError }); setTimeout(() => setToastMsg({ text: '', isError: false }), 3000); }; const formatPrice = (price) => { return Number(price).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' }); }; // --- ADMIN ACTIONS --- const handleAdminLogin = (e) => { e.preventDefault(); const username = e.target.username.value; const password = e.target.password.value; if (username === 'admin' && password === '1234') { setIsAdmin(true); setCurrentView('admin-panel'); showToast('Login realizado com sucesso!'); } else { showToast('Credenciais inválidas!', true); } }; const handleImageUpload = (e) => { const file = e.target.files[0]; if (!file) return; // Compress image before saving to base64 to avoid Firestore 1MB limits const reader = new FileReader(); reader.onload = (event) => { const img = new Image(); img.onload = () => { const canvas = document.createElement('canvas'); const MAX_WIDTH = 600; const scaleSize = MAX_WIDTH / img.width; canvas.width = MAX_WIDTH; canvas.height = img.height * scaleSize; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); const base64 = canvas.toDataURL('image/jpeg', 0.8); setFormData({ ...formData, image: base64 }); }; img.src = event.target.result; }; reader.readAsDataURL(file); }; const saveProduct = async (e) => { e.preventDefault(); if (!user) return; try { const docId = isEditing ? formData.id : crypto.randomUUID(); const productRef = doc(db, 'artifacts', appId, 'public', 'data', 'products', docId); await setDoc(productRef, { name: formData.name, brand: formData.brand, category: formData.category, subCategory: formData.category === 'infantil' ? formData.subCategory : '', size: formData.size, price: Number(formData.price), image: formData.image, createdAt: isEditing ? formData.createdAt : Date.now() }); setFormData(initialForm); setIsEditing(false); showToast('Produto salvo com sucesso!'); } catch (err) { console.error(err); showToast('Erro ao salvar produto.', true); } }; const deleteProduct = async (id) => { try { await deleteDoc(doc(db, 'artifacts', appId, 'public', 'data', 'products', id)); showToast('Produto removido!'); setProductToDelete(null); } catch (err) { console.error(err); showToast('Erro ao excluir produto.', true); } }; const editProduct = (product) => { setFormData(product); setIsEditing(true); window.scrollTo({ top: 0, behavior: 'smooth' }); }; // --- CART & STORE ACTIONS --- const addToCart = (product) => { if (cart.find(item => item.id === product.id)) { showToast('Esta peça já está na sacola!'); return; } setCart([...cart, product]); showToast('Peça adicionada à sacola!'); }; const removeFromCart = (id) => { setCart(cart.filter(item => item.id !== id)); }; const checkoutWhatsApp = () => { if (cart.length === 0) return; let text = `*Olá! Vim pelo site e tenho interesse nestas peças:* 🛍️\n\n`; cart.forEach((item, index) => { text += `${index + 1}. *${item.name}* (${item.brand})\n Tam: ${item.size} | ${formatPrice(item.price)}\n\n`; }); const total = cart.reduce((sum, item) => sum + item.price, 0); text += `*Total estimado: ${formatPrice(total)}*\n\nComo podemos prosseguir?`; window.open(`https://wa.me/5511999999999?text=${encodeURIComponent(text)}`, '_blank'); }; // --- FILTERS & DERIVED STATE --- const availableSizes = useMemo(() => { const sizes = new Set(products.map(p => p.size.toUpperCase())); return ['todos', ...Array.from(sizes).sort()]; }, [products]); const filteredProducts = useMemo(() => { return products.filter(p => { const matchSearch = p.name.toLowerCase().includes(searchQuery.toLowerCase()) || p.brand.toLowerCase().includes(searchQuery.toLowerCase()); const matchCat = activeCategory === 'todas' || p.category === activeCategory; const matchSubCat = activeCategory !== 'infantil' || activeSubCategory === 'todas' || p.subCategory === activeSubCategory; const matchSize = activeSize === 'todos' || p.size.toUpperCase() === activeSize; return matchSearch && matchCat && matchSubCat && matchSize; }); }, [products, searchQuery, activeCategory, activeSubCategory, activeSize]); // --- COMPONENTS --- if (!user) return
Moda circular premium com foco em qualidade e exclusividade. Descubra desapegos incríveis a pronta entrega.
Tente limpar os filtros ou buscar por outra marca.
{product.brand}
{formatPrice(product.price)}
Gerencie seu catálogo de desapegos.
| Foto | Produto / Marca | Cat / Tam | Preço | Ações |
|---|---|---|---|---|
|
|
{p.name} {p.brand} |
{p.category} {p.subCategory && `(${p.subCategory})`} Tam: {p.size} |
{formatPrice(p.price)} | |
| Nenhum produto cadastrado. | ||||
Sua sacola está vazia.
{item.brand} | Tam: {item.size}
{formatPrice(item.price)}
Esta ação não pode ser desfeita. A peça será removida do catálogo.