import React, { useState, useEffect } from 'react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInAnonymously, signInWithCustomToken, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, doc, getDoc, addDoc, setDoc, updateDoc, deleteDoc, onSnapshot, collection, query, where, addDoc, getDocs } from 'firebase/firestore'; // Main App component for the lemonade stand web page. export default function App() { const [db, setDb] = useState(null); const [userId, setUserId] = useState(null); const [isAuthReady, setIsAuthReady] = useState(false); const [orders, setOrders] = useState([]); const [isAdmin, setIsAdmin] = useState(false); const [password, setPassword] = useState(''); const [isEditing, setIsEditing] = useState(false); const [editingOrder, setEditingOrder] = useState(null); const [newOrder, setNewOrder] = useState({ name: '', address: '', lemonSoda: 1, status: 'Pending', createdAt: null, }); // Unique ID for the app, provided by the environment. const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; // State to hold the admin password. In a real-world app, this would be more secure. const ADMIN_PASSWORD = 'lemonade'; // useEffect to handle Firebase initialization and authentication. useEffect(() => { // Check for the required global variables. if (typeof __firebase_config !== 'undefined' && typeof __initial_auth_token !== 'undefined') { try { const firebaseConfig = JSON.parse(__firebase_config); const app = initializeApp(firebaseConfig); const firestoreDb = getFirestore(app); const auth = getAuth(app); setDb(firestoreDb); // Sign in with the custom token or anonymously. if (__initial_auth_token) { signInWithCustomToken(auth, __initial_auth_token) .then(() => { // Listen for auth state changes to get the user ID. onAuthStateChanged(auth, (user) => { if (user) { setUserId(user.uid); } else { // If auth fails, sign in anonymously as a fallback. signInAnonymously(auth).then(() => { setUserId(auth.currentUser.uid); }); } setIsAuthReady(true); }); }) .catch(() => { // Handle custom token sign-in failure. signInAnonymously(auth).then(() => { setUserId(auth.currentUser.uid); setIsAuthReady(true); }); }); } else { // No token provided, sign in anonymously. signInAnonymously(auth).then(() => { setUserId(auth.currentUser.uid); setIsAuthReady(true); }); } } catch (e) { console.error("Firebase initialization failed:", e); } } else { console.error("Firebase config or auth token is missing."); } }, []); // useEffect to subscribe to real-time order updates from Firestore. useEffect(() => { if (!db || !isAuthReady) return; // Listen to changes in the 'orders' collection. const q = collection(db, `/artifacts/${appId}/public/data/orders`); const unsubscribe = onSnapshot(q, (querySnapshot) => { const ordersData = []; querySnapshot.forEach((doc) => { ordersData.push({ id: doc.id, ...doc.data() }); }); // Sort orders by creation date (newest first). ordersData.sort((a, b) => b.createdAt.toDate() - a.createdAt.toDate()); setOrders(ordersData); }, (error) => { console.error("Error fetching orders:", error); }); // Clean up the listener on component unmount. return () => unsubscribe(); }, [db, isAuthReady, appId]); // Handler for password submission to access the admin view. const handlePasswordSubmit = (e) => { e.preventDefault(); if (password === ADMIN_PASSWORD) { setIsAdmin(true); } else { alert('Incorrect password. Please try again.'); } }; // Handler for consumer form submission. const handleAddOrder = async (e) => { e.preventDefault(); if (!db || !newOrder.name || !newOrder.address) { alert('Please fill out all fields.'); return; } try { // Add a new order document to Firestore. await addDoc(collection(db, `/artifacts/${appId}/public/data/orders`), { ...newOrder, createdAt: new Date(), // To make the data extensible items: [{ name: 'Lemon Soda', quantity: newOrder.lemonSoda }] }); // Clear the form after a successful submission. setNewOrder({ name: '', address: '', lemonSoda: 1 }); alert('Order placed successfully!'); } catch (e) { console.error('Error adding document: ', e); alert('There was an error placing your order. Please try again.'); } }; // Handler to delete an order from Firestore. const handleDeleteOrder = async (orderId) => { if (confirm('Are you sure you want to delete this order?')) { try { await deleteDoc(doc(db, `/artifacts/${appId}/public/data/orders`, orderId)); } catch (e) { console.error('Error deleting document: ', e); } } }; // Handler to mark an order as completed. const handleMarkAsCompleted = async (orderId, status) => { const newStatus = status === 'Completed' ? 'Pending' : 'Completed'; try { await updateDoc(doc(db, `/artifacts/${appId}/public/data/orders`, orderId), { status: newStatus, }); } catch (e) { console.error('Error updating document: ', e); } }; // Handler for editing an order. const handleEditOrder = (order) => { setEditingOrder(order); setIsEditing(true); setNewOrder({ ...order, lemonSoda: order.items[0].quantity }); }; // Handler for updating an edited order. const handleUpdateOrder = async (e) => { e.preventDefault(); if (!db || !newOrder.name || !newOrder.address) { alert('Please fill out all fields.'); return; } try { await updateDoc(doc(db, `/artifacts/${appId}/public/data/orders`, editingOrder.id), { name: newOrder.name, address: newOrder.address, items: [{ name: 'Lemon Soda', quantity: newOrder.lemonSoda }], }); setIsEditing(false); setEditingOrder(null); setNewOrder({ name: '', address: '', lemonSoda: 1 }); alert('Order updated successfully!'); } catch (e) { console.error('Error updating document: ', e); alert('There was an error updating the order. Please try again.'); } }; // Function to create a custom modal/dialog box instead of `confirm()` or `alert()`. const confirm = (message) => { const result = window.confirm(message); // Using window.confirm() for simplicity since it is a quick app. return result; }; // Base CSS classes for shared styles. const baseClasses = { card: 'bg-white rounded-xl shadow-lg p-6 m-4 ring-1 ring-gray-200', button: 'bg-yellow-500 hover:bg-yellow-600 text-white font-bold py-2 px-4 rounded-full transition-colors duration-300', input: 'w-full p-2 mb-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-yellow-500', header: 'text-2xl font-bold text-gray-800 text-center mb-6', table: 'w-full text-left table-auto border-collapse', th: 'py-2 px-4 bg-gray-100 font-bold uppercase text-sm text-gray-600', td: 'py-3 px-4 border-b border-gray-200', buttonGroup: 'flex flex-wrap gap-2 justify-center mt-4' }; // Render the Admin view. const renderAdminView = () => (

Admin Dashboard

{isEditing && (

Edit Order

setNewOrder({ ...newOrder, name: e.target.value })} className={baseClasses.input} /> setNewOrder({ ...newOrder, address: e.target.value })} className={baseClasses.input} />
)} {orders.length === 0 ? (

No orders yet.

) : (
{orders.map((order) => ( ))}
Name Address Items Status Actions
{order.name} {order.address} {order.items.map((item, index) => (
{item.quantity} x {item.name}
))}
{order.status}
)}
); // Render the Customer view. const renderCustomerView = () => (

Lemonade Stand

{/* Admin Login Form */}
setPassword(e.target.value)} className={`${baseClasses.input} mb-2`} />
{/* Customer Order Form */}

Place Your Order

setNewOrder({ ...newOrder, name: e.target.value })} className={baseClasses.input} /> setNewOrder({ ...newOrder, address: e.target.value })} className={baseClasses.input} />
setNewOrder({ ...newOrder, lemonSoda: parseInt(e.target.value, 10) })} className={baseClasses.input} />
); return (
{isAdmin ? renderAdminView() : renderCustomerView()}
); }