import React, { useState, useEffect, createContext, useContext } from 'react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInAnonymously, signInWithCustomToken, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, collection, query, onSnapshot, doc, setDoc, updateDoc, deleteDoc, getDoc, addDoc, where, getDocs } from 'firebase/firestore'; // Firebase Context to provide db, auth, and userId to components const FirebaseContext = createContext(null); const App = () => { const [db, setDb] = useState(null); const [auth, setAuth] = useState(null); const [userId, setUserId] = useState(null); const [isAuthReady, setIsAuthReady] = useState(false); // Initialize Firebase and set up auth listener useEffect(() => { try { const firebaseConfig = typeof __firebase_config !== 'undefined' ? JSON.parse(__firebase_config) : {}; const app = initializeApp(firebaseConfig); const firestoreDb = getFirestore(app); const firebaseAuth = getAuth(app); setDb(firestoreDb); setAuth(firebaseAuth); const unsubscribe = onAuthStateChanged(firebaseAuth, async (user) => { if (user) { setUserId(user.uid); } else { // Sign in anonymously if no user is found try { if (typeof __initial_auth_token !== 'undefined') { await signInWithCustomToken(firebaseAuth, __initial_auth_token); } else { await signInAnonymously(firebaseAuth); } } catch (error) { console.error("Error signing in anonymously:", error); } } setIsAuthReady(true); // Mark auth as ready after initial check }); return () => unsubscribe(); } catch (error) { console.error("Failed to initialize Firebase:", error); } }, []); if (!isAuthReady) { return (
Loading...
); } return (
); }; const Header = () => { const { userId } = useContext(FirebaseContext); return (

Evangeline's

{/* Updated name here */} {userId && (
User ID: {userId}
)}
); }; const Footer = () => { return ( ); }; const MainContent = () => { const [view, setView] = useState('products'); // 'products', 'cart', 'checkout' const navigateTo = (newView) => { setView(newView); }; return (
{view === 'products' && } {view === 'cart' && } {view === 'checkout' && }
); }; const ProductList = ({ navigateTo }) => { const { db, userId } = useContext(FirebaseContext); const [products, setProducts] = useState([]); const [cartItems, setCartItems] = useState({}); // {productId: quantity} const [message, setMessage] = useState(''); const [showModal, setShowModal] = useState(false); // Fetch products from Firestore useEffect(() => { if (!db || !userId) return; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const productsCollectionRef = collection(db, `artifacts/${appId}/public/data/products`); const q = query(productsCollectionRef); const unsubscribe = onSnapshot(q, (snapshot) => { const fetchedProducts = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); setProducts(fetchedProducts); }, (error) => { console.error("Error fetching products:", error); setMessage("Error loading products."); setShowModal(true); }); return () => unsubscribe(); }, [db, userId]); // Fetch cart items from Firestore useEffect(() => { if (!db || !userId) return; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const cartDocRef = doc(db, `artifacts/${appId}/users/${userId}/cart/current`); const unsubscribe = onSnapshot(cartDocRef, (docSnap) => { if (docSnap.exists()) { const data = docSnap.data(); // Ensure data.items is an object, default to empty if not setCartItems(data.items || {}); } else { setCartItems({}); } }, (error) => { console.error("Error fetching cart:", error); setMessage("Error loading cart."); setShowModal(true); }); return () => unsubscribe(); }, [db, userId]); const addToCart = async (product) => { if (!db || !userId) { setMessage("Please wait for authentication to complete."); setShowModal(true); return; } const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const cartDocRef = doc(db, `artifacts/${appId}/users/${userId}/cart/current`); try { const newQuantity = (cartItems[product.id] || 0) + 1; const updatedCartItems = { ...cartItems, [product.id]: newQuantity }; await setDoc(cartDocRef, { items: updatedCartItems }, { merge: true }); setMessage(`${product.name} added to cart!`); setShowModal(true); } catch (error) { console.error("Error adding to cart:", error); setMessage("Failed to add to cart."); setShowModal(true); } }; // Function to seed initial products (run once for testing) const seedProducts = async () => { if (!db) return; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const productsCollectionRef = collection(db, `artifacts/${appId}/public/data/products`); const initialProducts = [ { name: "Wireless Headphones", price: 99.99, description: "High-fidelity sound with noise cancellation.", imageUrl: "https://placehold.co/300x200/FFD700/000000?text=Headphones" }, { name: "Smartwatch", price: 199.99, description: "Track your fitness and receive notifications.", imageUrl: "https://placehold.co/300x200/ADD8E6/000000?text=Smartwatch" }, { name: "Portable Bluetooth Speaker", price: 49.99, description: "Powerful sound in a compact design.", imageUrl: "https://placehold.co/300x200/90EE90/000000?text=Speaker" }, { name: "Gaming Mouse", price: 59.99, description: "Precision and speed for serious gamers.", imageUrl: "https://placehold.co/300x200/FFA07A/000000?text=Gaming+Mouse" }, ]; try { for (const product of initialProducts) { // Check if product already exists to avoid duplicates const q = query(productsCollectionRef, where("name", "==", product.name)); const querySnapshot = await getDocs(q); if (querySnapshot.empty) { await addDoc(productsCollectionRef, product); } } setMessage("Products seeded successfully!"); setShowModal(true); } catch (error) { console.error("Error seeding products:", error); setMessage("Failed to seed products."); setShowModal(true); } }; return (

Our Products

{products.length === 0 ? (
No products available.
) : ( products.map((product) => (
{product.name} { e.target.onerror = null; e.target.src = `https://placehold.co/300x200/CCCCCC/000000?text=Image+Error`; }} />

{product.name}

{product.description}

${product.price.toFixed(2)}
)) )}
{showModal && ( setShowModal(false)} /> )}
); }; const ShoppingCart = ({ navigateTo }) => { const { db, userId } = useContext(FirebaseContext); const [cartItems, setCartItems] = useState({}); // {productId: quantity} const [products, setProducts] = useState([]); // To get product details const [message, setMessage] = useState(''); const [showModal, setShowModal] = useState(false); // Fetch products (needed to display product names/prices in cart) useEffect(() => { if (!db || !userId) return; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const productsCollectionRef = collection(db, `artifacts/${appId}/public/data/products`); const unsubscribe = onSnapshot(productsCollectionRef, (snapshot) => { const fetchedProducts = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); setProducts(fetchedProducts); }, (error) => { console.error("Error fetching products for cart:", error); setMessage("Error loading product details for cart."); setShowModal(true); }); return () => unsubscribe(); }, [db, userId]); // Fetch cart items useEffect(() => { if (!db || !userId) return; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const cartDocRef = doc(db, `artifacts/${appId}/users/${userId}/cart/current`); const unsubscribe = onSnapshot(cartDocRef, (docSnap) => { if (docSnap.exists()) { setCartItems(docSnap.data().items || {}); } else { setCartItems({}); } }, (error) => { console.error("Error fetching cart:", error); setMessage("Error loading cart."); setShowModal(true); }); return () => unsubscribe(); }, [db, userId]); const updateCartItemQuantity = async (productId, newQuantity) => { if (!db || !userId) { setMessage("Please wait for authentication to complete."); setShowModal(true); return; } const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const cartDocRef = doc(db, `artifacts/${appId}/users/${userId}/cart/current`); try { const updatedCartItems = { ...cartItems }; if (newQuantity <= 0) { delete updatedCartItems[productId]; } else { updatedCartItems[productId] = newQuantity; } await setDoc(cartDocRef, { items: updatedCartItems }, { merge: true }); } catch (error) { console.error("Error updating cart quantity:", error); setMessage("Failed to update cart quantity."); setShowModal(true); } }; const getProductDetails = (productId) => { return products.find(p => p.id === productId); }; const calculateTotal = () => { let total = 0; for (const productId in cartItems) { const product = getProductDetails(productId); if (product) { total += product.price * cartItems[productId]; } } return total; }; const totalItems = Object.values(cartItems).reduce((sum, qty) => sum + qty, 0); return (

Your Shopping Cart

{totalItems === 0 ? (
Your cart is empty.
) : ( <>
{Object.entries(cartItems).map(([productId, quantity]) => { const product = getProductDetails(productId); if (!product) return null; // Product might not be loaded yet or deleted return (
{product.name} { e.target.onerror = null; e.target.src = `https://placehold.co/80x80/CCCCCC/000000?text=Image`; }} />

{product.name}

${product.price.toFixed(2)}

{quantity}
${(product.price * quantity).toFixed(2)}
); })}
Total: ${calculateTotal().toFixed(2)}
)} {showModal && ( setShowModal(false)} /> )}
); }; const Checkout = ({ navigateTo }) => { const { db, userId } = useContext(FirebaseContext); const [cartItems, setCartItems] = useState({}); const [products, setProducts] = useState([]); const [message, setMessage] = useState(''); const [showModal, setShowModal] = useState(false); // Fetch products useEffect(() => { if (!db || !userId) return; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const productsCollectionRef = collection(db, `artifacts/${appId}/public/data/products`); const unsubscribe = onSnapshot(productsCollectionRef, (snapshot) => { const fetchedProducts = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); setProducts(fetchedProducts); }); return () => unsubscribe(); }, [db, userId]); // Fetch cart items useEffect(() => { if (!db || !userId) return; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const cartDocRef = doc(db, `artifacts/${appId}/users/${userId}/cart/current`); const unsubscribe = onSnapshot(cartDocRef, (docSnap) => { if (docSnap.exists()) { setCartItems(docSnap.data().items || {}); } else { setCartItems({}); } }); return () => unsubscribe(); }, [db, userId]); const getProductDetails = (productId) => { return products.find(p => p.id === productId); }; const calculateTotal = () => { let total = 0; for (const productId in cartItems) { const product = getProductDetails(productId); if (product) { total += product.price * cartItems[productId]; } } return total; }; const handlePlaceOrder = async () => { if (!db || !userId) { setMessage("Please wait for authentication to complete."); setShowModal(true); return; } const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const ordersCollectionRef = collection(db, `artifacts/${appId}/users/${userId}/orders`); const cartDocRef = doc(db, `artifacts/${appId}/users/${userId}/cart/current`); if (Object.keys(cartItems).length === 0) { setMessage("Your cart is empty. Please add items before checking out."); setShowModal(true); return; } try { const orderDetails = { userId: userId, items: cartItems, total: calculateTotal(), orderDate: new Date().toISOString(), status: 'Pending', }; await addDoc(ordersCollectionRef, orderDetails); // Add order to orders collection await deleteDoc(cartDocRef); // Clear the cart setMessage("Order placed successfully! Thank you for your purchase."); setShowModal(true); // Optionally navigate to an order confirmation page or products page after a delay setTimeout(() => navigateTo('products'), 2000); } catch (error) { console.error("Error placing order:", error); setMessage("Failed to place order. Please try again."); setShowModal(true); } }; return (

Checkout

Order Summary

{Object.keys(cartItems).length === 0 ? (

No items in cart for checkout.

) : ( )}
Total: ${calculateTotal().toFixed(2)}

Shipping Information

Payment Information

{showModal && ( setShowModal(false)} /> )}
); }; const MessageModal = ({ message, onClose }) => { return (

{message}

); }; export default App;