import { useState, useRef } from "react"; import jsPDF from "jspdf"; import html2canvas from "html2canvas"; export default function QuoteApp() { const baseSetupFee = 997; const [buildCost, setBuildCost] = useState(0); const [discount, setDiscount] = useState(0); const [annual, setAnnual] = useState(false); const [notes, setNotes] = useState(""); const [selectedPlan, setSelectedPlan] = useState(null); const [includeOrb, setIncludeOrb] = useState(false); const [taxRate, setTaxRate] = useState(0); const [shippingCost, setShippingCost] = useState(0); const [clientName, setClientName] = useState(""); const [signature, setSignature] = useState(""); const [signedDate, setSignedDate] = useState(""); const quoteRef = useRef(); const plans = [ { name: "Essentials Plan", price: 297 }, { name: "Pro Plan", price: 497 }, { name: "Elite Plan", price: 697 } ]; const orbAddOn = { name: "Orb Add-On", price: 497 }; const handleDiscountChange = (e) => { const value = e.target.value; setDiscount(parseFloat(value)); }; const totalBuildCost = buildCost - buildCost * (discount / 100); const annualMultiplier = annual ? 10 : 1; const selectedPlanCost = selectedPlan !== null ? plans[selectedPlan].price * annualMultiplier : 0; const totalOrbCost = includeOrb ? orbAddOn.price : 0; const taxAmount = (totalBuildCost + totalOrbCost + baseSetupFee + shippingCost + selectedPlanCost) * (taxRate / 100); const grandTotal = totalBuildCost + totalOrbCost + baseSetupFee + selectedPlanCost + shippingCost + taxAmount; const downloadPDF = () => { const input = quoteRef.current; html2canvas(input).then((canvas) => { const imgData = canvas.toDataURL("image/png"); const pdf = new jsPDF(); const imgProps = pdf.getImageProperties(imgData); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = (imgProps.height * pdfWidth) / imgProps.width; pdf.addImage(imgData, "PNG", 0, 0, pdfWidth, pdfHeight); pdf.save("Visionary_Flow_Quote.pdf"); }); const quoteData = { clientName, signature, signedDate, total: grandTotal, plan: selectedPlan !== null ? plans[selectedPlan].name : "None", includeOrb, taxRate, shippingCost, notes, }; // Save to internal dashboard (mocked for now) fetch("/api/save-quote", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(quoteData), }) .then((res) => res.json()) .then((data) => console.log("Quote saved to admin dashboard:", data)) .catch((err) => console.error("Save error:", err)); // GHL webhook/API push fetch("https://hooks.highlevel.com/your-ghl-endpoint", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(quoteData), }) .then((res) => res.json()) .then((data) => console.log("GHL Response:", data)) .catch((err) => console.error("GHL Error:", err)); // Email confirmation (mocked for now) fetch("/api/send-confirmation-email", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ to: clientName, subject: "Your Visionary Flow Solutions Quote", message: `Hello ${clientName},\n\nThank you for reviewing and signing your quote.\n\nTotal: $${grandTotal.toFixed(2)}\nPlan: ${selectedPlan !== null ? plans[selectedPlan].name : "None"}\n\nVisionary Flow Solutions Team`, }), }) .then((res) => res.json()) .then((data) => console.log("Email confirmation sent:", data)) .catch((err) => console.error("Email Error:", err)); // Stripe redirect (example usage - needs server-side setup) fetch("/create-stripe-session", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ amount: grandTotal, clientName }), }) .then((res) => res.json()) .then((session) => { if (session?.url) { window.location.href = session.url; } }) .catch((err) => console.error("Stripe Error:", err)); }; return (
{/* UI stays the same */}
); }