import { useState, useEffect, useRef } from "react";
// ─── DOMAIN CONFIG ────────────────────────────────────────────────────────────
const AFFILIATE_PORTAL_URL = "https://join.businessfundingnow.com";
const ADMIN_PORTAL_URL = "https://affiliateadmin.businessfundingnow.com";
const REFERRAL_BASE_URL = "https://apply.businessfundingnow.com";
// ─── CONSTANTS ────────────────────────────────────────────────────────────────
const TIERS = [
{ name: "Bronze Broker", min: 0, max: 49999, rate: 0.02, color: "#CD7F32", bg: "#2a1a0a" },
{ name: "Silver Broker", min: 50000, max: 249999, rate: 0.025, color: "#C0C0C0", bg: "#1a1a1a" },
{ name: "Gold Broker", min: 250000, max: 999999, rate: 0.03, color: "#FFD700", bg: "#1a1500" },
{ name: "Platinum Broker", min: 1000000, max: Infinity, rate: 0.04, color: "#E5E4E2", bg: "#0f0f14" },
];
const STAGES = ["Lead Captured", "Application Submitted", "Under Review", "Docs Requested", "Approved", "Funded", "Declined"];
const TRAINING_MODULES = [
{
id: "m1", title: "Getting Started", icon: "🚀",
lessons: [
{ id: "l-101", title: "Welcome to BFN Edge Affiliate Program", duration: "8 min" },
{ id: "l-102", title: "How the Platform Works", duration: "12 min" },
{ id: "l-103", title: "Your Affiliate Dashboard Tour", duration: "10 min" },
{ id: "l-104", title: "Setting Up Your Profile", duration: "6 min" },
]
},
{
id: "m2", title: "Understanding Business Funding", icon: "💼",
lessons: [
{ id: "l-201", title: "Types of Business Funding Products", duration: "15 min" },
{ id: "l-202", title: "Qualifying Criteria for Clients", duration: "11 min" },
{ id: "l-203", title: "The Funding Process Explained", duration: "14 min" },
{ id: "l-204", title: "Common Client Questions & Answers", duration: "9 min" },
]
},
{
id: "m3", title: "Sales & Referral Strategies", icon: "📈",
lessons: [
{ id: "l-301", title: "Identifying Ideal Referral Clients", duration: "13 min" },
{ id: "l-302", title: "Effective Outreach Scripts", duration: "10 min" },
{ id: "l-303", title: "Leveraging Your Network", duration: "8 min" },
{ id: "l-304", title: "Tracking & Optimizing Your Funnel", duration: "12 min" },
]
},
{
id: "m4", title: "Compliance & Best Practices", icon: "⚖️",
lessons: [
{ id: "l-401", title: "FTC & Disclosure Requirements", duration: "11 min" },
{ id: "l-402", title: "What You Can and Cannot Promise", duration: "9 min" },
{ id: "l-403", title: "Data Privacy & Client Confidentiality", duration: "7 min" },
{ id: "l-404", title: "Certification & Next Steps", duration: "5 min" },
]
},
];
// ─── MOCK DATA ─────────────────────────────────────────────────────────────────
const MOCK_AFFILIATES = [
{ id: "a1", name: "Sarah Chen", email: "sarah@example.com", phone: "+1-555-0101", company: "Chen Advisory", tier: "Gold Broker", status: "Active", affiliate_code: "SARAH-BFN", total_earned: 18420, pending_comm: 2100, commission_rate: 0.03, created_at: "2024-11-15", referral_method: "LinkedIn", ghl_contact_id: "ghl_001" },
{ id: "a2", name: "Marcus Williams", email: "marcus@fundingpro.com", phone: "+1-555-0202", company: "Funding Pro LLC", tier: "Platinum Broker", status: "Active", affiliate_code: "MARCUS-BFN", total_earned: 62800, pending_comm: 5400, commission_rate: 0.04, created_at: "2024-09-03", referral_method: "Referral", ghl_contact_id: "ghl_002" },
{ id: "a3", name: "Priya Patel", email: "priya@pateladvisors.com", phone: "+1-555-0303", company: "Patel Advisors", tier: "Silver Broker", status: "Active", affiliate_code: "PRIYA-BFN", total_earned: 9650, pending_comm: 850, commission_rate: 0.025, created_at: "2025-01-20", referral_method: "Website", ghl_contact_id: "ghl_003" },
{ id: "a4", name: "James Okonkwo", email: "james@bizbroker.net", phone: "+1-555-0404", company: "BizBroker Net", tier: "Bronze Broker", status: "Pending", affiliate_code: null, total_earned: 0, pending_comm: 0, commission_rate: 0.02, created_at: "2025-06-01", referral_method: "Google", ghl_contact_id: null },
{ id: "a5", name: "Lisa Nguyen", email: "lisa@capitalconnect.io", phone: "+1-555-0505", company: "Capital Connect", tier: "Bronze Broker", status: "Pending", affiliate_code: null, total_earned: 0, pending_comm: 0, commission_rate: 0.02, created_at: "2025-06-02", referral_method: "Instagram", ghl_contact_id: null },
];
const MOCK_DEALS = [
{ id: "d1", affiliate_id: "a1", business_name: "Green Leaf Café", loan_amount: 75000, stage: "Funded", commission: 2250, commission_paid: true, paid_at: "2025-05-10", created_at: "2025-04-01" },
{ id: "d2", affiliate_id: "a1", business_name: "TechForge Solutions", loan_amount: 140000, stage: "Approved", commission: 4200, commission_paid: false, created_at: "2025-05-15" },
{ id: "d3", affiliate_id: "a2", business_name: "Sunrise Logistics", loan_amount: 320000, stage: "Funded", commission: 12800, commission_paid: true, paid_at: "2025-04-28", created_at: "2025-03-10" },
{ id: "d4", affiliate_id: "a2", business_name: "Pacific Dental Group", loan_amount: 185000, stage: "Under Review", commission: 7400, commission_paid: false, created_at: "2025-05-20" },
{ id: "d5", affiliate_id: "a3", business_name: "Bloom Boutique", loan_amount: 45000, stage: "Application Submitted", commission: 1125, commission_paid: false, created_at: "2025-06-01" },
];
const MOCK_LINKS = [
{ id: "lk1", affiliate_id: "a1", code: "SARAH-BFN", label: "Primary Link", clicks: 342, conversions: 8, active: true },
{ id: "lk2", affiliate_id: "a1", code: "SARAH-BFN-002", label: "LinkedIn Campaign", clicks: 128, conversions: 3, active: true },
{ id: "lk3", affiliate_id: "a2", code: "MARCUS-BFN", label: "Primary Link", clicks: 891, conversions: 21, active: true },
];
// ─── UTILS ────────────────────────────────────────────────────────────────────
const fmt = (n) => n?.toLocaleString("en-US", { style: "currency", currency: "USD", minimumFractionDigits: 0 }) ?? "$0";
const fmtNum = (n) => n?.toLocaleString() ?? "0";
function getTier(earned) {
return TIERS.find(t => earned >= t.min && earned <= t.max) || TIERS[0];
}
function getStageColor(stage) {
const map = {
"Lead Captured": "#64748b", "Application Submitted": "#3b82f6",
"Under Review": "#f59e0b", "Docs Requested": "#8b5cf6",
"Approved": "#10b981", "Funded": "#22c55e", "Declined": "#ef4444"
};
return map[stage] || "#64748b";
}
function StatusBadge({ status }) {
const colors = { Active: "#22c55e", Pending: "#f59e0b", Suspended: "#ef4444", Rejected: "#64748b" };
return (
{status.toUpperCase()}
);
}
// ─── AI CHAT WIDGET ──────────────────────────────────────────────────────────
function AIChat({ affiliate, onClose }) {
const [messages, setMessages] = useState([
{ role: "assistant", content: `Hey ${affiliate?.name?.split(" ")[0] || "there"}! 👋 I'm your BFN Edge AI assistant. Ask me anything about your affiliate account, commission rates, how to qualify clients, or tips to boost your referrals!` }
]);
const [input, setInput] = useState("");
const [loading, setLoading] = useState(false);
const bottomRef = useRef(null);
useEffect(() => { bottomRef.current?.scrollIntoView({ behavior: "smooth" }); }, [messages]);
const send = async () => {
if (!input.trim() || loading) return;
const userMsg = input.trim();
setInput("");
setMessages(m => [...m, { role: "user", content: userMsg }]);
setLoading(true);
const context = affiliate ? `Affiliate context: Name: ${affiliate.name}, Tier: ${affiliate.tier}, Total Earned: ${fmt(affiliate.total_earned)}, Commission Rate: ${(affiliate.commission_rate * 100).toFixed(1)}%, Status: ${affiliate.status}.` : "";
try {
const res = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "claude-sonnet-4-20250514",
max_tokens: 1000,
system: `You are a helpful assistant for BFN Edge Affiliate Platform — a business funding referral program. ${context} Help affiliates understand their commissions (2-4% based on tier), how to qualify clients, referral strategies, and platform features. Be concise, friendly, and professional. Use $ formatting for amounts.`,
messages: [...messages.filter(m => m.role !== "assistant" || messages.indexOf(m) > 0), { role: "user", content: userMsg }].map(m => ({ role: m.role, content: m.content }))
})
});
const data = await res.json();
const reply = data.content?.[0]?.text || "I couldn't get a response. Please try again.";
setMessages(m => [...m, { role: "assistant", content: reply }]);
} catch {
setMessages(m => [...m, { role: "assistant", content: "Connection error. Please try again." }]);
}
setLoading(false);
};
return (
✦
BFN AI Assistant
● Online
{messages.map((m, i) => (
))}
{loading && (
)}
setInput(e.target.value)}
onKeyDown={e => e.key === "Enter" && send()}
placeholder="Ask anything..." style={{ flex: 1, background: "#161e2d", border: "1px solid #1e2a3a", borderRadius: 10, color: "#e2e8f0", padding: "9px 14px", fontSize: 13, outline: "none" }}
/>
);
}
// ─── SIGN-UP PAGE ─────────────────────────────────────────────────────────────
function SignUpPage({ onSubmit, onBack }) {
const [form, setForm] = useState({ name: "", email: "", phone: "", company: "", website: "", referralMethod: "", volume: "", bio: "" });
const [submitted, setSubmitted] = useState(false);
const [loading, setLoading] = useState(false);
const handleSubmit = async () => {
if (!form.name || !form.email) return;
setLoading(true);
await new Promise(r => setTimeout(r, 900));
setSubmitted(true);
setLoading(false);
onSubmit?.(form);
};
const F = ({ label, field, type = "text", placeholder, options }) => (
{options ? (
) : (
setForm({ ...form, [field]: e.target.value })} placeholder={placeholder} style={inputStyle} />
)}
);
if (submitted) return (
🎉
Application Submitted!
Thanks, {form.name}! Your application is under review. We'll email you at {form.email} within 24 hours.
);
return (
{/* Left panel */}
✦
BFN EDGE
AFFILIATE NETWORK
Earn up to 4% on every funded deal
Join hundreds of brokers and advisors earning recurring commissions by connecting businesses with the funding they need.
{TIERS.map(t => (
{t.name} — {(t.rate * 100).toFixed(1)}% commission
))}
{/* Right panel - form */}
Join the Affiliate Program
Complete the form below. Approval takes less than 24 hours.
);
}
// ─── AFFILIATE PORTAL ─────────────────────────────────────────────────────────
function AffiliatePortal({ affiliateId, onLogout }) {
const [tab, setTab] = useState("dashboard");
const [showChat, setShowChat] = useState(false);
const affiliate = MOCK_AFFILIATES.find(a => a.id === affiliateId) || MOCK_AFFILIATES[0];
const deals = MOCK_DEALS.filter(d => d.affiliate_id === affiliate.id);
const links = MOCK_LINKS.filter(l => l.affiliate_id === affiliate.id);
const [completedLessons, setCompletedLessons] = useState(new Set(["l-101", "l-102", "l-201"]));
const tier = getTier(affiliate.total_earned);
const allLessons = TRAINING_MODULES.flatMap(m => m.lessons);
const progress = Math.round((completedLessons.size / allLessons.length) * 100);
const navItems = [
{ id: "dashboard", icon: "◈", label: "Dashboard" },
{ id: "deals", icon: "⬡", label: "My Deals" },
{ id: "links", icon: "⌖", label: "My Links" },
{ id: "training", icon: "◉", label: "Training" },
{ id: "commissions", icon: "◎", label: "Commissions" },
];
return (
{/* Sidebar */}
{affiliate.name.split(" ")[0]}
{tier.name}
{progress}% training complete
{/* Main content */}
{navItems.find(n => n.id === tab)?.label}
Welcome back, {affiliate.name.split(" ")[0]}!
{tab === "dashboard" &&
}
{tab === "deals" &&
}
{tab === "links" &&
}
{tab === "training" &&
}
{tab === "commissions" &&
}
{showChat &&
setShowChat(false)} />}
);
}
function PortalDashboard({ affiliate, deals, links, completedLessons }) {
const tier = getTier(affiliate.total_earned);
const funded = deals.filter(d => d.stage === "Funded");
const totalVolume = funded.reduce((s, d) => s + d.loan_amount, 0);
const allLessons = TRAINING_MODULES.flatMap(m => m.lessons);
return (
{/* Tier banner */}
CURRENT TIER
{tier.name}
{(tier.rate * 100).toFixed(1)}% commission rate on all funded deals
AFFILIATE CODE
{affiliate.affiliate_code || "PENDING"}
{/* Stats */}
{[
{ label: "Total Earned", value: fmt(affiliate.total_earned), sub: "All time", accent: "#22c55e" },
{ label: "Pending Commission", value: fmt(affiliate.pending_comm), sub: "Awaiting payment", accent: "#f59e0b" },
{ label: "Total Funded Volume", value: fmt(totalVolume), sub: `${funded.length} deals funded`, accent: "#3b82f6" },
{ label: "Training Progress", value: `${Math.round((completedLessons.size / allLessons.length) * 100)}%`, sub: `${completedLessons.size}/${allLessons.length} lessons done`, accent: "#8b5cf6" },
].map(stat => (
{stat.label.toUpperCase()}
{stat.value}
{stat.sub}
))}
{/* Recent deals */}
Recent Deals
{deals.slice(0, 4).map(deal => (
{deal.business_name}
{deal.loan_amount ? fmt(deal.loan_amount) + " loan" : "—"}
{deal.stage}
{fmt(deal.commission)}
))}
{/* Referral link */}
);
}
function PortalDeals({ deals, affiliate }) {
return (
{deals.length === 0 ? (
No deals yet. Share your referral link to get started!
) : deals.map(deal => (
{deal.business_name}
Submitted {deal.created_at}
{deal.stage}
LOAN AMOUNT
{fmt(deal.loan_amount)}
COMMISSION
{fmt(deal.commission)}
STATUS
{deal.commission_paid ? "Paid" : "Pending"}
{/* Stage progress bar */}
{STAGES.filter(s => s !== "Declined").map((s, i) => {
const activeIdx = STAGES.indexOf(deal.stage);
const thisIdx = STAGES.indexOf(s);
return
;
})}
))}
);
}
function PortalLinks({ links, affiliate }) {
const [newLabel, setNewLabel] = useState("");
const [localLinks, setLocalLinks] = useState(links);
const addLink = () => {
if (!newLabel) return;
setLocalLinks([...localLinks, { id: `lk${Date.now()}`, affiliate_id: affiliate.id, code: `${affiliate.affiliate_code?.split("-")[0]}-BFN-${String(localLinks.length + 1).padStart(3, "0")}`, label: newLabel, clicks: 0, conversions: 0, active: true }]);
setNewLabel("");
};
return (
setNewLabel(e.target.value)} placeholder="Link label (e.g. LinkedIn Campaign)" style={{ ...inputStyle, flex: 1 }} />
{localLinks.map(link => (
{link.label}
CLICKS
{fmtNum(link.clicks)}
CONVERSIONS
{link.conversions}
CVR
{link.clicks ? ((link.conversions / link.clicks) * 100).toFixed(1) + "%" : "—"}
))}
);
}
function PortalTraining({ completedLessons, setCompletedLessons }) {
const [activeLesson, setActiveLesson] = useState(null);
return (
{TRAINING_MODULES.map(mod => (
{mod.icon}
{mod.title}
{mod.lessons.filter(l => completedLessons.has(l.id)).length}/{mod.lessons.length} complete
{mod.lessons.map(lesson => {
const done = completedLessons.has(lesson.id);
return (
{lesson.title}
{lesson.duration}
);
})}
))}
{activeLesson && (
{activeLesson.title}
▶
Video player — connect GHL embed URL
Duration: {activeLesson.duration}
)}
);
}
function PortalCommissions({ deals, affiliate }) {
const paid = deals.filter(d => d.commission_paid);
const pending = deals.filter(d => !d.commission_paid && d.stage === "Funded");
const paidTotal = paid.reduce((s, d) => s + d.commission, 0);
return (
{[
{ label: "Total Paid Out", value: fmt(paidTotal), color: "#22c55e" },
{ label: "Pending Payment", value: fmt(affiliate.pending_comm), color: "#f59e0b" },
{ label: "Payout Method", value: affiliate.payout_method || "ACH Direct", color: "#3b82f6" },
].map(s => (
{s.label.toUpperCase()}
{s.value}
))}
Commission History
{deals.map(deal => (
{deal.business_name}
{deal.stage} · {deal.created_at}
{fmt(deal.commission)}
{deal.commission_paid ? "✓ Paid " + deal.paid_at : "Pending"}
))}
);
}
// ─── ADMIN DASHBOARD ──────────────────────────────────────────────────────────
function AdminDashboard({ onLogout }) {
const [tab, setTab] = useState("overview");
const [affiliates, setAffiliates] = useState(MOCK_AFFILIATES);
const [deals] = useState(MOCK_DEALS);
const [search, setSearch] = useState("");
const [showChat, setShowChat] = useState(false);
const [aiAnalysis, setAiAnalysis] = useState("");
const [aiLoading, setAiLoading] = useState(false);
const pending = affiliates.filter(a => a.status === "Pending");
const active = affiliates.filter(a => a.status === "Active");
const totalFunded = deals.filter(d => d.stage === "Funded").reduce((s, d) => s + d.loan_amount, 0);
const totalComm = deals.reduce((s, d) => s + d.commission, 0);
const approve = (id) => setAffiliates(prev => prev.map(a => a.id === id ? { ...a, status: "Active", affiliate_code: `${a.name.split(" ")[0].toUpperCase().slice(0, 8)}-BFN` } : a));
const reject = (id) => setAffiliates(prev => prev.map(a => a.id === id ? { ...a, status: "Rejected" } : a));
const getAiInsights = async () => {
setAiLoading(true);
const summary = `Active affiliates: ${active.length}. Pending: ${pending.length}. Total funded volume: ${fmt(totalFunded)}. Total commissions: ${fmt(totalComm)}. Top earner: ${active.sort((a, b) => b.total_earned - a.total_earned)[0]?.name}.`;
try {
const res = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "claude-sonnet-4-20250514",
max_tokens: 1000,
messages: [{
role: "user",
content: `You're an analyst for BFN Edge Affiliate Program. Analyze this data and provide 3-4 actionable insights: ${summary}. Focus on growth opportunities, retention, and performance optimization. Be concise with bullet points.`
}]
})
});
const data = await res.json();
setAiAnalysis(data.content?.[0]?.text || "No insights available.");
} catch { setAiAnalysis("Failed to load insights."); }
setAiLoading(false);
};
const navItems = [
{ id: "overview", icon: "◈", label: "Overview" },
{ id: "affiliates", icon: "⬡", label: "Affiliates" },
{ id: "deals", icon: "⌖", label: "All Deals" },
{ id: "commissions", icon: "◎", label: "Commissions" },
{ id: "automations", icon: "⟳", label: "Automations" },
];
const filtered = affiliates.filter(a => !search || a.name.toLowerCase().includes(search.toLowerCase()) || a.email.toLowerCase().includes(search.toLowerCase()));
return (
{/* Sidebar */}
{pending.length > 0 && (
⚡ {pending.length} pending approval{pending.length > 1 ? "s" : ""}
)}
{/* Main */}
{navItems.find(n => n.id === tab)?.label}
Admin · Business Funding Now
{aiAnalysis && (
✦ AI INSIGHTS
{aiAnalysis}
)}
{tab === "overview" &&
}
{tab === "affiliates" &&
}
{tab === "deals" &&
}
{tab === "commissions" &&
}
{tab === "automations" &&
}
{showChat &&
setShowChat(false)} />}
);
}
function AdminOverview({ affiliates, deals, approve, reject, totalFunded, totalComm }) {
const pending = affiliates.filter(a => a.status === "Pending");
const active = affiliates.filter(a => a.status === "Active");
const funded = deals.filter(d => d.stage === "Funded");
return (
{[
{ label: "Active Affiliates", value: active.length, accent: "#22c55e", icon: "⬡" },
{ label: "Total Funded Volume", value: fmt(totalFunded), accent: "#3b82f6", icon: "◈" },
{ label: "Total Commissions", value: fmt(totalComm), accent: "#f59e0b", icon: "◎" },
{ label: "Pending Approvals", value: pending.length, accent: "#ef4444", icon: "⚡" },
].map(s => (
{s.label.toUpperCase()}
{s.icon}
{s.value}
))}
{pending.length > 0 && (
Pending Approvals
{pending.length} WAITING
{pending.map(a => (
{a.name}
{a.email} · {a.company} · via {a.referral_method}
Applied {a.created_at}
))}
)}
Top Performers
{affiliates.filter(a => a.status === "Active").sort((a, b) => b.total_earned - a.total_earned).slice(0, 4).map((a, i) => (
{i + 1}
{fmt(a.total_earned)}
))}
Deal Pipeline
{STAGES.slice(0, 6).map(stage => {
const count = deals.filter(d => d.stage === stage).length;
return (
);
})}
);
}
function AdminAffiliates({ affiliates, search, setSearch, approve, reject }) {
const [selected, setSelected] = useState(null);
return (
setSearch(e.target.value)} placeholder="Search by name or email…" style={{ ...inputStyle, maxWidth: 360 }} />
{["Affiliate", "Company", "Tier", "Earned", "Status", "Actions"].map(h => (
{h.toUpperCase()}
))}
{affiliates.map(a => (
setSelected(a)} style={{ display: "grid", gridTemplateColumns: "2fr 1.5fr 1fr 1fr 1fr auto", padding: "14px 20px", borderBottom: "1px solid #0a1525", cursor: "pointer", transition: "background 0.15s" }}
onMouseEnter={e => e.currentTarget.style.background = "#0a1525"} onMouseLeave={e => e.currentTarget.style.background = "transparent"}>
{a.company || "—"}
{a.tier}
{fmt(a.total_earned)}
e.stopPropagation()}>
{a.status === "Pending" && <>
>}
))}
{selected && (
{selected.name}
{[
["Email", selected.email], ["Phone", selected.phone], ["Company", selected.company],
["Tier", selected.tier], ["Status", selected.status], ["Affiliate Code", selected.affiliate_code || "Not assigned"],
["Commission Rate", (selected.commission_rate * 100).toFixed(1) + "%"], ["Total Earned", fmt(selected.total_earned)],
["Pending Commission", fmt(selected.pending_comm)], ["Referral Method", selected.referral_method],
["Joined", selected.created_at],
].map(([k, v]) => (
{k}
{v}
))}
{selected.status === "Pending" && (
)}
)}
);
}
function AdminDeals({ deals, affiliates }) {
return (
{["Business", "Affiliate", "Loan Amount", "Commission", "Stage"].map(h => (
{h.toUpperCase()}
))}
{deals.map(deal => {
const aff = affiliates.find(a => a.id === deal.affiliate_id);
return (
{deal.business_name}
{deal.created_at}
{aff?.name || "—"}
{fmt(deal.loan_amount)}
{fmt(deal.commission)}
{deal.commission_paid ? "Paid" : "Pending"}
{deal.stage}
);
})}
);
}
function AdminCommissions({ deals, affiliates }) {
const unpaid = deals.filter(d => d.stage === "Funded" && !d.commission_paid);
const paid = deals.filter(d => d.commission_paid);
const totalDue = unpaid.reduce((s, d) => s + d.commission, 0);
return (
COMMISSIONS DUE
{fmt(totalDue)}
{unpaid.length} payout{unpaid.length !== 1 ? "s" : ""} pending
TOTAL PAID OUT
{fmt(paid.reduce((s, d) => s + d.commission, 0))}
{paid.length} commissions paid
AVG COMMISSION
{fmt(deals.length ? deals.reduce((s, d) => s + d.commission, 0) / deals.length : 0)}
per deal
{unpaid.length > 0 && (
Pending Payouts
{unpaid.map(deal => {
const aff = affiliates.find(a => a.id === deal.affiliate_id);
return (
{deal.business_name}
To: {aff?.name} · {aff?.payout_method || "ACH Direct"}
{fmt(deal.commission)}
);
})}
)}
);
}
function AdminAutomations() {
const automations = [
{ id: 1, name: "Affiliate Onboarding Sequence", trigger: "Tag: affiliate-active added", steps: [`Send welcome email with affiliate link`, `Send SMS: Congrats + portal link → ${AFFILIATE_PORTAL_URL}`, "Wait 2 days → Send 'First referral?' email", "Wait 5 days → Send training tip email"], status: "Active" },
{ id: 2, name: "Deal Stage Notification", trigger: "Opportunity stage changes in BFN pipeline", steps: [`Fire outbound webhook to ${ADMIN_PORTAL_URL}/api/affiliate/webhook`, "If Funded → Add tag: commission-pending", "Notify admin of funded deal"], status: "Active" },
{ id: 3, name: "Affiliate Certification", trigger: "Tag: affiliate-certified added", steps: ["Send certification congratulations email", "Send SMS: Badge notification", "Update custom field: certified = true"], status: "Active" },
{ id: 4, name: "Commission Paid Notification", trigger: "Commission marked as paid in dashboard", steps: ["Send payment confirmation email to affiliate", "Update Supabase commission_paid = true"], status: "Active" },
];
const notifications = [
{ event: "New affiliate applies", channels: ["Admin email", "Admin SMS"], template: "🔔 New Affiliate Application — {name}" },
{ event: "Application confirmed", channels: ["Applicant email"], template: "✅ We received your BFN Edge Affiliate Application!" },
{ event: "Affiliate approved", channels: ["Affiliate email", "Affiliate SMS"], template: "🎉 You're approved! Your BFN Edge Affiliate Account is Live" },
{ event: "Deal stage updated", channels: ["Affiliate email"], template: "📊 Deal Update: {business} → {stage}" },
{ event: "Deal funded", channels: ["Affiliate email", "Admin email"], template: "💰 Commission Earned! {business} has been funded" },
{ event: "Commission paid", channels: ["Affiliate email"], template: "✅ Your BFN Commission Has Been Paid" },
];
return (
{automations.map(a => (
⚡ {a.trigger}
{a.steps.map((step, i) => (
))}
))}
Notification Templates
{notifications.map((n, i) => (
{n.event}
{n.channels.map(ch => {ch})}
{n.template}
))}
);
}
// ─── SHARED STYLES ────────────────────────────────────────────────────────────
const inputStyle = {
background: "#0d1a2e", border: "1px solid #1e2a3a", borderRadius: 10,
color: "#e2e8f0", padding: "10px 14px", fontSize: 13, outline: "none", width: "100%", boxSizing: "border-box"
};
const btnPrimary = {
background: "linear-gradient(135deg, #1a6b3c, #22c55e)", border: "none", borderRadius: 10,
color: "#fff", padding: "10px 20px", cursor: "pointer", fontWeight: 700, fontSize: 14
};
const btnSecondary = {
background: "#0d1a2e", border: "1px solid #1e2a3a", borderRadius: 10,
color: "#94a3b8", padding: "10px 16px", cursor: "pointer", fontWeight: 600, fontSize: 13
};
// ─── LOGIN PAGE ───────────────────────────────────────────────────────────────
function LoginPage({ onLogin }) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false);
const handleLogin = async (role) => {
setLoading(true);
await new Promise(r => setTimeout(r, 700));
setLoading(false);
onLogin(role);
};
return (
✦
BFN Edge
Sign in to your account
);
}
// ─── HOME / LANDING ───────────────────────────────────────────────────────────
function HomePage({ onJoin, onLogin }) {
return (
EARN 2–4% COMMISSION
Turn Your Network Into
Recurring Revenue
Refer businesses that need funding. Earn commissions when they get funded. Track everything in real time.
{TIERS.map(t => (
{t.name}
{(t.rate * 100).toFixed(1)}%
{t.max === Infinity ? `${fmt(t.min)}+ funded` : `Up to ${fmt(t.max)} funded`}
))}
);
}
// ─── ROOT APP ─────────────────────────────────────────────────────────────────
export default function App() {
const [view, setView] = useState("home"); // home | join | login | affiliate | admin
return (
<>
{view === "home" && setView("join")} onLogin={() => setView("login")} />}
{view === "join" && setView("home")} onSubmit={() => {}} />}
{view === "login" && setView(role === "admin" ? "admin" : "affiliate")} />}
{view === "affiliate" && setView("home")} />}
{view === "admin" && setView("home")} />}
>
);
}