import React, { useState, useEffect } from 'react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInWithCustomToken, signInAnonymously, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, doc, setDoc, collection, query, onSnapshot, updateDoc } from 'firebase/firestore'; // Main App component for the lead generation application. export default function App() { const [file, setFile] = useState(null); const [clients, setClients] = useState([]); const [selectedClient, setSelectedClient] = useState(null); const [offers, setOffers] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(''); const [db, setDb] = useState(null); const [auth, setAuth] = useState(null); const [userId, setUserId] = useState(null); const [appId, setAppId] = useState(''); // 1. Initialize Firebase and authenticate the user. useEffect(() => { const firebaseConfig = typeof __firebase_config !== 'undefined' ? JSON.parse(__firebase_config) : null; const initialAuthToken = typeof __initial_auth_token !== 'undefined' ? __initial_auth_token : null; const currentAppId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; setAppId(currentAppId); if (firebaseConfig) { const app = initializeApp(firebaseConfig); const firestoreDb = getFirestore(app); const firebaseAuth = getAuth(app); setDb(firestoreDb); setAuth(firebaseAuth); const handleAuth = async () => { try { if (initialAuthToken) { await signInWithCustomToken(firebaseAuth, initialAuthToken); } else { await signInAnonymously(firebaseAuth); } } catch (e) { console.error("Firebase auth error:", e); setError("Failed to sign in. Please try again."); } }; onAuthStateChanged(firebaseAuth, (user) => { if (user) { setUserId(user.uid); } else { setUserId(null); } }); handleAuth(); } }, []); // 2. Fetch client data from Firestore in real-time. useEffect(() => { if (db && userId) { try { const clientCollectionRef = collection(db, `artifacts/${appId}/users/${userId}/clients`); // Use onSnapshot to get real-time updates. const unsubscribe = onSnapshot(clientCollectionRef, (querySnapshot) => { const fetchedClients = []; querySnapshot.forEach((doc) => { fetchedClients.push({ id: doc.id, ...doc.data() }); }); setClients(fetchedClients); // If a client was previously selected, update the offers if they exist. if (selectedClient) { const updatedClient = fetchedClients.find(c => c.id === selectedClient.id); if (updatedClient) { setOffers(updatedClient.offers || null); } } }, (err) => { console.error("Failed to fetch clients:", err); setError("Failed to load client data. Please refresh."); }); // Clean up the listener when the component unmounts. return () => unsubscribe(); } catch (e) { console.error("Firestore data fetch setup failed:", e); setError("Could not set up data listener. Please check your connection."); } } }, [db, userId, appId, selectedClient]); // Handle file input changes. const handleFileChange = (e) => { setFile(e.target.files[0]); setError(''); }; // Process the uploaded Excel file using the read-excel-file library. const handleFileUpload = async () => { if (!file) { setError("Please select a file to upload."); return; } setLoading(true); setError(''); try { // The readXlsxFile function is globally available from the script tag at the bottom. const data = await readXlsxFile(file); // The first row is the header, subsequent rows are the data. const headers = data[0]; const jsonData = data.slice(1).map(row => { const obj = {}; headers.forEach((header, index) => { obj[header] = row[index]; }); return obj; }); // Save each client to Firestore. if (db && userId) { const clientCollectionRef = collection(db, `artifacts/${appId}/users/${userId}/clients`); await Promise.all(jsonData.map(async (clientData) => { // Use the client's email as the document ID for uniqueness, or a random ID if not available. const docId = clientData.Email || crypto.randomUUID(); const docRef = doc(clientCollectionRef, docId); await setDoc(docRef, { ...clientData, timestamp: new Date().toISOString() }, { merge: true }); })); } setLoading(false); setError("File uploaded and clients saved successfully!"); } catch (e) { console.error("File processing error:", e); setLoading(false); setError("Error processing file. Make sure it's a valid Excel (.xlsx) file with columns: Name, Email, Last_Ordered_Product."); } }; // Generate offers using the Gemini API. const handleGenerateOffers = async () => { if (!selectedClient) { setError("Please select a client to generate offers for."); return; } setLoading(true); setError(''); setOffers(null); const prompt = `Act as a marketing expert for a natural health supplements company. You are retargeting an existing client to promote new products for weight loss, prostate health, or male enhancement. The client's name is ${selectedClient.Name}. Their last ordered product was a ${selectedClient.Last_Ordered_Product || 'general health supplement'}. Propose a personalized offer or discount for a new product, referencing their past purchase. Make the offer sound enticing and exclusive. Keep the response to 1-2 short, compelling paragraphs.`; try { const apiKey = ""; const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:generateContent?key=${apiKey}`; const payload = { contents: [{ role: "user", parts: [{ text: prompt }] }] }; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const result = await response.json(); const newOfferText = result.candidates?.[0]?.content?.parts?.[0]?.text; if (newOfferText) { // Save the generated offer back to the client document in Firestore. const docRef = doc(db, `artifacts/${appId}/users/${userId}/clients`, selectedClient.id); await updateDoc(docRef, { offers: newOfferText }); setOffers(newOfferText); setError('Offers generated and saved successfully!'); } else { throw new Error('No text generated by the model.'); } } catch (e) { console.error("API call error:", e); setError("Failed to generate offers. Please try again."); } finally { setLoading(false); } }; return (
Upload an Excel file with client data (columns: Name, Email, Last_Ordered_Product). Then, select a client to generate smart offers and discounts using AI.
{userId && (| Name | Last Product | Actions | |
|---|---|---|---|
| {client.Name} | {client.Email} | {client.Last_Ordered_Product || 'N/A'} |
{offers}