ROI-Calculator / app.py
aeblymt's picture
Update app.py
d4571df verified
Raw
History Blame Contribute Delete
41.3 kB
import streamlit as st
import openai
import json
import re
from datetime import datetime
import pandas as pd
from io import BytesIO
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.lib import colors
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
# Page config
st.set_page_config(
page_title="AI ROI Calculator - Eau Claire AI",
page_icon="📊",
layout="wide",
initial_sidebar_state="collapsed"
)
# Professional Eau Claire AI Brand CSS Design
st.markdown("""
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
/* Eau Claire AI Brand Colors */
:root {
--primary-blue: #1e3a8a;
--secondary-blue: #3b82f6;
--teal: #0d9488;
--light-teal: #14b8a6;
--grey-dark: #374151;
--grey-medium: #6b7280;
--grey-light: #f3f4f6;
--white: #ffffff;
}
/* Clean background */
.stApp {
background-color: #f8fafc !important;
font-family: 'Inter', sans-serif !important;
}
/* Professional main container */
.main .block-container {
background: var(--white) !important;
border-radius: 12px !important;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08) !important;
border: 1px solid #e2e8f0 !important;
margin: 1.5rem auto !important;
padding: 2.5rem !important;
max-width: 1000px !important;
}
/* Brand-consistent headers */
h1 {
color: var(--primary-blue) !important;
font-size: 2.5rem !important;
font-weight: 700 !important;
text-align: center !important;
margin-bottom: 0.5rem !important;
font-family: 'Inter', sans-serif !important;
}
h2 {
color: var(--grey-dark) !important;
font-weight: 600 !important;
margin-top: 2rem !important;
margin-bottom: 1rem !important;
font-size: 1.5rem !important;
}
h3 {
color: var(--grey-dark) !important;
font-weight: 600 !important;
margin-bottom: 1rem !important;
font-size: 1.25rem !important;
}
/* Professional form inputs with perfect contrast */
.stTextInput input, .stTextArea textarea {
background: var(--white) !important;
border: 2px solid #d1d5db !important;
border-radius: 8px !important;
padding: 12px 16px !important;
color: var(--grey-dark) !important;
font-size: 16px !important;
font-weight: 500 !important;
}
.stTextInput input:focus, .stTextArea textarea:focus {
border-color: var(--secondary-blue) !important;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important;
outline: none !important;
}
/* Number inputs with styled buttons */
.stNumberInput input {
background: var(--white) !important;
border: 2px solid #d1d5db !important;
border-radius: 8px !important;
padding: 12px 16px !important;
color: var(--grey-dark) !important;
font-size: 16px !important;
font-weight: 500 !important;
}
.stNumberInput input:focus {
border-color: var(--secondary-blue) !important;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important;
outline: none !important;
}
/* Fix number input buttons - properly centered */
.stNumberInput > div > div > button {
background: var(--secondary-blue) !important;
color: var(--white) !important;
border: none !important;
width: 32px !important;
height: 32px !important;
border-radius: 6px !important;
font-weight: bold !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-size: 14px !important;
margin: 2px !important;
}
.stNumberInput > div > div > button:hover {
background: var(--primary-blue) !important;
}
.stNumberInput > div {
position: relative !important;
}
.stNumberInput > div > div {
display: flex !important;
align-items: center !important;
}
/* Selectbox styling with visible dropdown arrow */
.stSelectbox > div > div {
background: var(--white) !important;
border: 2px solid #d1d5db !important;
border-radius: 8px !important;
color: var(--grey-dark) !important;
font-weight: 500 !important;
position: relative !important;
}
.stSelectbox > div > div:focus-within {
border-color: var(--secondary-blue) !important;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important;
}
/* Fix dropdown arrow - make it visible */
.stSelectbox > div > div::after {
content: "▼" !important;
position: absolute !important;
right: 12px !important;
top: 50% !important;
transform: translateY(-50%) !important;
color: var(--grey-medium) !important;
font-size: 12px !important;
pointer-events: none !important;
}
/* Dropdown options */
.stSelectbox > div > div > div {
color: var(--grey-dark) !important;
background: var(--white) !important;
}
/* Hide default dropdown arrow */
.stSelectbox select {
appearance: none !important;
-webkit-appearance: none !important;
-moz-appearance: none !important;
background-image: none !important;
}
/* Labels */
.stTextInput label, .stNumberInput label, .stSelectbox label, .stTextArea label {
color: var(--grey-dark) !important;
font-weight: 600 !important;
font-size: 14px !important;
margin-bottom: 8px !important;
}
/* Professional buttons */
.stButton > button {
background: linear-gradient(135deg, var(--secondary-blue) 0%, var(--teal) 100%) !important;
color: var(--white) !important;
border: none !important;
border-radius: 8px !important;
padding: 12px 24px !important;
font-weight: 600 !important;
font-size: 16px !important;
transition: all 0.2s ease !important;
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.2) !important;
}
.stButton > button:hover {
transform: translateY(-1px) !important;
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3) !important;
background: linear-gradient(135deg, var(--primary-blue) 0%, var(--teal) 100%) !important;
}
/* Professional metric cards */
.metric-card {
background: var(--white) !important;
border: 2px solid #e5e7eb !important;
border-radius: 12px !important;
padding: 1.5rem !important;
margin: 1rem 0 !important;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05) !important;
transition: all 0.2s ease !important;
}
.metric-card:hover {
border-color: var(--secondary-blue) !important;
box-shadow: 0 4px 16px rgba(59, 130, 246, 0.1) !important;
transform: translateY(-2px) !important;
}
.metric-value {
font-size: 2.5rem !important;
font-weight: 700 !important;
color: var(--teal) !important;
margin-bottom: 0.5rem !important;
}
.metric-label {
color: var(--grey-medium) !important;
font-size: 1rem !important;
font-weight: 500 !important;
}
/* Clean recommendation boxes */
.recommendation-box {
background: var(--white) !important;
border: 2px solid var(--light-teal) !important;
border-radius: 12px !important;
padding: 1.5rem !important;
margin: 1rem 0 !important;
position: relative !important;
}
.recommendation-box::before {
content: '' !important;
position: absolute !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
height: 4px !important;
background: var(--light-teal) !important;
border-radius: 12px 12px 0 0 !important;
}
.recommendation-box h4 {
color: var(--teal) !important;
font-weight: 600 !important;
margin-bottom: 0.5rem !important;
}
.recommendation-box p {
color: var(--grey-dark) !important;
line-height: 1.5 !important;
}
/* Progress bars */
.stProgress > div > div {
background: linear-gradient(90deg, var(--secondary-blue), var(--teal)) !important;
border-radius: 6px !important;
}
/* Clean footer */
.footer {
background: var(--grey-light) !important;
border-radius: 12px !important;
padding: 1.5rem !important;
margin-top: 2rem !important;
text-align: center !important;
color: var(--grey-medium) !important;
border: 1px solid #e5e7eb !important;
}
/* Messages */
.stSuccess {
background: #f0fdf4 !important;
border: 2px solid #22c55e !important;
color: #166534 !important;
border-radius: 8px !important;
padding: 1rem !important;
}
.stError {
background: #fef2f2 !important;
border: 2px solid #ef4444 !important;
color: #991b1b !important;
border-radius: 8px !important;
padding: 1rem !important;
}
/* Fix checkbox styling */
.stCheckbox > label {
color: var(--grey-dark) !important;
font-weight: 500 !important;
display: flex !important;
align-items: center !important;
gap: 8px !important;
}
.stCheckbox > label > div {
display: flex !important;
align-items: center !important;
}
.stCheckbox input[type="checkbox"] {
appearance: none !important;
width: 20px !important;
height: 20px !important;
border: 2px solid #d1d5db !important;
border-radius: 4px !important;
background: var(--white) !important;
position: relative !important;
cursor: pointer !important;
margin: 0 !important;
}
.stCheckbox input[type="checkbox"]:checked {
background: var(--secondary-blue) !important;
border-color: var(--secondary-blue) !important;
}
.stCheckbox input[type="checkbox"]:checked::after {
content: "✓" !important;
position: absolute !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
color: var(--white) !important;
font-size: 12px !important;
font-weight: bold !important;
}
.stCheckbox input[type="checkbox"]:focus {
outline: none !important;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1) !important;
}
/* All text should be readable */
.stMarkdown p, .stText, div[data-testid="stMarkdownContainer"] p {
color: var(--grey-dark) !important;
line-height: 1.6 !important;
}
/* Remove Streamlit elements */
.stApp > header, .stDeployButton, #MainMenu, footer {
display: none !important;
}
/* Mobile responsive */
@media (max-width: 768px) {
.main .block-container {
margin: 1rem !important;
padding: 1.5rem !important;
}
h1 {
font-size: 2rem !important;
}
.metric-value {
font-size: 2rem !important;
}
}
</style>
""", unsafe_allow_html=True)
# Access control
def check_access():
"""Check if user has valid access key"""
access_key = st.query_params.get('key', None)
valid_key = st.secrets.get("ACCESS_KEY", "a5a474d55b7c79e3")
if access_key != valid_key:
st.error("🚫 Access Restricted")
st.markdown("This tool is exclusively available through **www.eauclaireai.com**")
st.markdown("Please visit our website to access the ROI Calculator.")
st.stop()
# Check access before showing app
check_access()
# Initialize session state
if 'calculations_done' not in st.session_state:
st.session_state.calculations_done = False
if 'ai_recommendations' not in st.session_state:
st.session_state.ai_recommendations = None
def validate_email(email):
"""Validate email format"""
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(pattern, email) is not None
def send_lead_notification(business_info, calculations):
"""Send email notification when new lead completes ROI calculator"""
try:
# Get SendGrid API key from secrets
sg = SendGridAPIClient(api_key=st.secrets["SENDGRID_API_KEY"])
# Prepare email content
subject = f"New ROI Calculator Lead: {business_info['company']}"
# Create formatted task list
tasks_list = "\n".join([f"• {task}" for task in business_info['tasks']])
html_content = f"""
<div style="font-family: Arial, sans-serif; max-width: 600px;">
<h2 style="color: #1f4e79;">New ROI Calculator Submission</h2>
<div style="background: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #2c5aa0; margin-top: 0;">Business Information</h3>
<p><strong>Company:</strong> {business_info['company']}</p>
<p><strong>Industry:</strong> {business_info['industry']}</p>
<p><strong>Employees:</strong> {business_info['employees']}</p>
<p><strong>Email:</strong> {business_info['email']}</p>
<p><strong>Phone:</strong> {business_info.get('phone', 'Not provided')}</p>
<p><strong>Avg Hourly Wage:</strong> ${business_info['avg_wage']}/hour</p>
</div>
<div style="background: #e8f4fd; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #2c5aa0; margin-top: 0;">ROI Analysis Results</h3>
<p><strong>Annual Labor Savings:</strong> ${calculations['annual_labor_savings']:,.0f}</p>
<p><strong>Year 1 Investment:</strong> ${calculations['ai_costs']['total_year_one']:,.0f}</p>
<p><strong>Year 1 Net Savings:</strong> ${calculations['year_one_savings']:,.0f}</p>
<p><strong>Ongoing Annual Savings:</strong> ${calculations['annual_ongoing_savings']:,.0f}</p>
<p><strong>Monthly Savings (Year 2+):</strong> ${calculations['monthly_savings']:,.0f}</p>
<p><strong>Hours Saved Per Week:</strong> {calculations['hours_saved']:.1f}</p>
<p><strong>3-Year ROI:</strong> {calculations['roi_three_year']:.0f}%</p>
<p><strong>Payback Period:</strong> {calculations['payback_months']:.1f} months</p>
</div>
<div style="background: #fff3cd; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #856404; margin-top: 0;">Time-Consuming Tasks</h3>
<div style="white-space: pre-line;">{tasks_list}</div>
</div>
<div style="background: #d1ecf1; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="color: #0c5460; margin-top: 0;">Next Steps</h3>
<p>This lead has shown significant interest in AI implementation with potential ongoing savings of <strong>${calculations['annual_ongoing_savings']:,.0f} annually</strong>.</p>
<p>Consider reaching out within 24 hours while their interest is high.</p>
</div>
<hr style="margin: 30px 0;">
<p style="color: #666; font-size: 14px;">Generated by AI ROI Calculator - Eau Claire AI</p>
</div>
"""
# Create and send email
message = Mail(
from_email='noreply@eauclaireai.com',
to_emails='info@eauclaireai.com',
subject=subject,
html_content=html_content
)
response = sg.send(message)
return True
except Exception as e:
st.error(f"Email notification failed: {str(e)}")
return False
def get_ai_recommendations(industry, company_size, main_tasks, annual_savings):
"""Get AI-powered recommendations from OpenAI"""
try:
client = openai.OpenAI(api_key=st.secrets["OPENAI_API_KEY"])
prompt = f"""You are an AI consultant for Eau Claire AI. Provide personalized recommendations for a business with these details:
- Industry: {industry}
- Company size: {company_size} employees
- Main time-consuming tasks: {main_tasks}
- Potential annual savings: ${annual_savings:,.0f}
Provide 3 specific, actionable AI implementation recommendations that would be most impactful for this business.
Focus on practical, cost-effective solutions that align with Eau Claire AI's approach of "problem-led, not tool-led" implementation.
IMPORTANT: Respond with ONLY valid JSON, no other text. Use this exact structure:
{{
"recommendations": [
{{
"title": "Clear, specific recommendation title",
"description": "2-3 sentence description of the solution",
"impact": "Expected time savings or business impact",
"implementation": "Brief overview of how this would be implemented",
"priority": "High"
}},
{{
"title": "Clear, specific recommendation title",
"description": "2-3 sentence description of the solution",
"impact": "Expected time savings or business impact",
"implementation": "Brief overview of how this would be implemented",
"priority": "Medium"
}},
{{
"title": "Clear, specific recommendation title",
"description": "2-3 sentence description of the solution",
"impact": "Expected time savings or business impact",
"implementation": "Brief overview of how this would be implemented",
"priority": "Low"
}}
],
"next_steps": "2-3 specific next steps they should take",
"timeline": "Realistic implementation timeline"
}}"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
temperature=0.7,
max_tokens=1500
)
content = response.choices[0].message.content.strip()
# Clean up common JSON formatting issues
if content.startswith('```json'):
content = content[7:]
if content.endswith('```'):
content = content[:-3]
content = content.strip()
return json.loads(content)
except json.JSONDecodeError as e:
st.error(f"AI response format error. Please try again.")
return None
except Exception as e:
st.error(f"Error generating recommendations: {str(e)}")
return None
def generate_pdf_report(business_info, calculations, recommendations):
"""Generate PDF report"""
buffer = BytesIO()
doc = SimpleDocTemplate(buffer, pagesize=letter)
styles = getSampleStyleSheet()
story = []
# Header
title_style = ParagraphStyle(
'CustomTitle',
parent=styles['Heading1'],
fontSize=24,
spaceAfter=30,
textColor=colors.HexColor('#1f4e79'),
alignment=1
)
story.append(Paragraph("AI ROI Analysis Report", title_style))
story.append(Paragraph("Eau Claire AI - Your path to AI, made clear.", styles['Normal']))
story.append(Spacer(1, 20))
# Business Information
story.append(Paragraph("Business Information", styles['Heading2']))
business_data = [
['Company', business_info['company']],
['Industry', business_info['industry']],
['Employees', str(business_info['employees'])],
['Contact', business_info['email']]
]
business_table = Table(business_data, colWidths=[2*inch, 3*inch])
business_table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#f0f0f0')),
('TEXTCOLOR', (0, 0), (-1, 0), colors.black),
('ALIGN', (0, 0), (-1, -1), 'LEFT'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, 0), 12),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('BACKGROUND', (0, 1), (-1, -1), colors.white),
('GRID', (0, 0), (-1, -1), 1, colors.black)
]))
story.append(business_table)
story.append(Spacer(1, 20))
# How AI Saves Money - Explanation Section
story.append(Paragraph("How AI Will Save Your Business Money", styles['Heading2']))
# Calculate key metrics for explanation
weekly_hours = calculations['annual_cost'] / 52 / business_info.get('avg_wage', 25)
hours_saved = calculations['hours_saved']
explanation_text = f"""
Based on your current operations, your team spends approximately {weekly_hours:.1f} hours per week on repetitive tasks
that can be significantly automated with AI. Here's how AI will generate savings:
<b>Current Situation:</b><br/>
• Your team dedicates {weekly_hours:.1f} hours weekly to manual, repetitive work<br/>
• This costs your business ${calculations['annual_cost']:,.0f} annually in labor<br/>
• These tasks include: {', '.join(business_info.get('tasks', ['data entry', 'manual processes']))}<br/>
<b>AI Transformation:</b><br/>
• AI can automate approximately 60% of these repetitive tasks<br/>
• This frees up {hours_saved:.1f} hours per week for your team<br/>
• Your staff can focus on higher-value activities like customer service, strategy, and growth<br/>
<b>Investment Requirements:</b><br/>
• Setup & Implementation: ${calculations['ai_costs']['setup']:,.0f}<br/>
• Annual Software Costs: ${calculations['ai_costs']['annual_software']:,.0f}<br/>
• Annual Maintenance: ${calculations['ai_costs']['annual_maintenance']:,.0f}<br/>
• Total Year 1 Investment: ${calculations['ai_costs']['total_year_one']:,.0f}<br/>
<b>Financial Impact:</b><br/>
• Annual labor savings: ${calculations['annual_labor_savings']:,.0f}<br/>
• Year 1 net savings: ${calculations['year_one_savings']:,.0f}<br/>
• Ongoing annual net savings: ${calculations['annual_ongoing_savings']:,.0f}<br/>
• 3-Year Total ROI: {calculations['roi_three_year']:.0f}%<br/>
<b>Conservative Approach:</b><br/>
This analysis uses conservative estimates for both automation rates (60%) and implementation costs
to ensure realistic expectations and successful outcomes.
"""
story.append(Paragraph(explanation_text, styles['Normal']))
story.append(Spacer(1, 20))
# ROI Calculations
story.append(Paragraph("ROI Analysis Summary", styles['Heading2']))
roi_data = [
['Metric', 'Value'],
['Annual Labor Cost for Repetitive Tasks', f"${calculations['annual_cost']:,.0f}"],
['Annual Labor Savings from AI', f"${calculations['annual_labor_savings']:,.0f}"],
['Total Year 1 AI Investment', f"${calculations['ai_costs']['total_year_one']:,.0f}"],
['Year 1 Net Savings', f"${calculations['year_one_savings']:,.0f}"],
['Ongoing Annual Net Savings', f"${calculations['annual_ongoing_savings']:,.0f}"],
['Monthly Savings (Year 2+)', f"${calculations['monthly_savings']:,.0f}"],
['Hours Saved Per Week', f"{calculations['hours_saved']:.1f}"],
['3-Year Total ROI', f"{calculations['roi_three_year']:.0f}%"],
['Payback Period', f"{calculations['payback_months']:.1f} months"]
]
roi_table = Table(roi_data, colWidths=[3*inch, 2*inch])
roi_table.setStyle(TableStyle([
('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#2c5aa0')),
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
('ALIGN', (0, 0), (-1, -1), 'LEFT'),
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, 0), 12),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
('BACKGROUND', (0, 1), (-1, -1), colors.white),
('GRID', (0, 0), (-1, -1), 1, colors.black)
]))
story.append(roi_table)
if recommendations:
story.append(Spacer(1, 20))
story.append(Paragraph("AI Implementation Recommendations", styles['Heading2']))
for i, rec in enumerate(recommendations['recommendations'], 1):
story.append(Paragraph(f"{i}. {rec['title']}", styles['Heading3']))
story.append(Paragraph(rec['description'], styles['Normal']))
story.append(Paragraph(f"<b>Impact:</b> {rec['impact']}", styles['Normal']))
story.append(Paragraph(f"<b>Priority:</b> {rec['priority']}", styles['Normal']))
story.append(Spacer(1, 10))
story.append(Paragraph("Next Steps", styles['Heading3']))
story.append(Paragraph(recommendations['next_steps'], styles['Normal']))
story.append(Paragraph(f"<b>Timeline:</b> {recommendations['timeline']}", styles['Normal']))
# Footer
story.append(Spacer(1, 30))
story.append(Paragraph("Contact Eau Claire AI", styles['Heading3']))
story.append(Paragraph("Ready to implement AI in your business?", styles['Normal']))
story.append(Paragraph("Email: hello@eauclaireai.com", styles['Normal']))
story.append(Paragraph("Website: www.eauclaireai.com", styles['Normal']))
story.append(Paragraph("Your path to AI, made clear.", styles['Italic']))
doc.build(story)
buffer.seek(0)
return buffer
# Header
st.markdown("""
<div class="main-header">
<h1>AI ROI Calculator</h1>
<p>Discover how much time and money AI can save your business</p>
<p><em>Your path to AI, made clear.</em></p>
</div>
""", unsafe_allow_html=True)
# Methodology explanation - clean and professional
st.subheader("How We Calculate Your ROI")
st.markdown("Our calculations are based on conservative, real-world data to give you accurate expectations:")
# Use Streamlit columns for clean layout
col1, col2 = st.columns(2)
with col1:
st.markdown("""
**📊 Your Current Costs**
We calculate your annual labor cost for repetitive tasks using your team size, hourly wages, and time spent on manual work.
**💰 Implementation Costs**
We estimate AI costs based on your business size: software subscriptions, setup, training, and ongoing support.
""")
with col2:
st.markdown("""
**🤖 AI Automation Potential**
Research shows AI can automate 40-70% of repetitive tasks. We use a conservative 60% estimate for reliable projections.
**📈 ROI Calculation**
Annual savings minus total AI costs, divided by investment cost. We include both one-time and recurring expenses.
""")
st.info("**Conservative Approach:** Our estimates err on the side of caution to ensure realistic expectations and successful implementations.")
st.markdown("---")
# Main form
with st.container():
col1, col2 = st.columns([2, 1])
with col1:
st.subheader("Tell us about your business")
# Business information
company_name = st.text_input("Company Name*", placeholder="Your Company Name")
col_a, col_b = st.columns(2)
with col_a:
industry = st.selectbox(
"Industry*",
["", "Real Estate", "Construction", "Healthcare", "Professional Services",
"Retail", "Food & Beverage", "Fitness", "Manufacturing", "Other"]
)
with col_b:
num_employees = st.number_input("Number of Employees*", min_value=1, max_value=10000, value=10)
# Task analysis
st.subheader("Current Operations")
col_c, col_d = st.columns(2)
with col_c:
avg_hourly_wage = st.number_input("Average Hourly Wage ($)*", min_value=10.0, max_value=200.0, value=25.0, step=1.0)
with col_d:
hours_on_repetitive = st.number_input("Hours/Week on Repetitive Tasks*", min_value=0.5, max_value=80.0, value=10.0, step=0.5)
# Task breakdown
st.subheader("What takes up most of your team's time?")
task_options = {
"Data entry and manual record keeping": False,
"Email management and responses": False,
"Scheduling and calendar management": False,
"Report generation and analysis": False,
"Customer service inquiries": False,
"Invoice processing and accounting": False,
"Content creation and writing": False,
"Research and information gathering": False,
"File organization and management": False,
"Quality control and reviewing": False
}
selected_tasks = []
for task, _ in task_options.items():
if st.checkbox(task):
selected_tasks.append(task)
other_tasks = st.text_area("Other time-consuming tasks", placeholder="Describe any other repetitive tasks...")
if other_tasks:
selected_tasks.append(other_tasks)
# Contact information
st.subheader("Get Your Personalized Results")
email = st.text_input("Email Address*", placeholder="your.email@company.com")
phone = st.text_input("Phone Number (Optional)", placeholder="(555) 123-4567")
# Calculate button
calculate_button = st.button("Calculate My AI ROI", use_container_width=True)
with col2:
st.info("""
### What you'll get:
✅ **Personalized ROI Analysis**
See exactly how much time and money AI could save your business
✅ **Custom Recommendations**
AI-powered suggestions specific to your industry and needs
✅ **Implementation Roadmap**
Clear next steps to get started
✅ **Detailed PDF Report**
Professional analysis you can share with your team
---
**Powered by Eau Claire AI**
*Your path to AI, made clear.*
""")
# Validation and calculations
if calculate_button:
# Validate required fields
errors = []
if not company_name.strip():
errors.append("Company name is required")
if not industry:
errors.append("Please select your industry")
if not email.strip():
errors.append("Email address is required")
elif not validate_email(email):
errors.append("Please enter a valid email address")
if not selected_tasks:
errors.append("Please select at least one time-consuming task")
if errors:
for error in errors:
st.error(error)
else:
with st.spinner("Calculating your AI ROI and generating personalized recommendations..."):
# Calculate current costs
annual_hours_repetitive = hours_on_repetitive * 52
annual_cost_repetitive = annual_hours_repetitive * avg_hourly_wage
# Conservative automation estimates
automation_percentage = 0.6 # 60% automation potential
annual_labor_savings = annual_cost_repetitive * automation_percentage
hours_saved_weekly = hours_on_repetitive * automation_percentage
# Realistic AI Implementation Costs based on business size
def calculate_ai_costs(num_employees, selected_tasks):
# Base costs by company size - realistic market rates
if num_employees <= 10:
setup_cost = 3000 # Small business setup - basic automation
monthly_software = 200 # Basic AI tools (ChatGPT, Zapier, etc.)
elif num_employees <= 50:
setup_cost = 6000 # Medium business setup
monthly_software = 500 # More comprehensive tools
elif num_employees <= 200:
setup_cost = 12000 # Large business setup
monthly_software = 1200 # Enterprise tools
else:
setup_cost = 20000 # Enterprise setup
monthly_software = 2500 # Full enterprise suite
# Adjust based on complexity (number of task types)
complexity_multiplier = min(1.5, 1 + (len(selected_tasks) * 0.1))
setup_cost *= complexity_multiplier
monthly_software *= complexity_multiplier
# Annual ongoing costs
annual_software = monthly_software * 12
annual_maintenance = setup_cost * 0.15 # 15% of setup for maintenance
return {
'setup': setup_cost,
'annual_software': annual_software,
'annual_maintenance': annual_maintenance,
'total_year_one': setup_cost + annual_software + annual_maintenance,
'annual_ongoing': annual_software + annual_maintenance
}
ai_costs = calculate_ai_costs(num_employees, selected_tasks)
# Calculate net benefits
year_one_savings = annual_labor_savings - ai_costs['total_year_one']
annual_ongoing_savings = annual_labor_savings - ai_costs['annual_ongoing']
monthly_savings = annual_ongoing_savings / 12
# ROI calculations - fixed logic
monthly_net_savings = annual_ongoing_savings / 12
payback_months = ai_costs['setup'] / monthly_net_savings if monthly_net_savings > 0 else 0
# More intuitive ROI: Total profit over 3 years divided by initial investment
three_year_total_profit = (annual_ongoing_savings * 2) + year_one_savings # Year 1 (may be negative) + Years 2&3
roi_three_year = (three_year_total_profit / ai_costs['setup']) * 100 if ai_costs['setup'] > 0 else 0
# Annual ROI based on ongoing savings vs ongoing costs
roi_ongoing = (annual_ongoing_savings / ai_costs['annual_ongoing']) * 100 if ai_costs['annual_ongoing'] > 0 else 0
calculations = {
'annual_cost': annual_cost_repetitive,
'annual_labor_savings': annual_labor_savings,
'annual_ongoing_savings': annual_ongoing_savings,
'monthly_savings': monthly_savings,
'hours_saved': hours_saved_weekly,
'ai_costs': ai_costs,
'payback_months': payback_months,
'roi_three_year': roi_three_year,
'roi_ongoing': roi_ongoing,
'year_one_savings': year_one_savings,
'three_year_total_profit': three_year_total_profit
}
# Get AI recommendations
main_tasks_text = ", ".join(selected_tasks[:3]) # Top 3 tasks
recommendations = get_ai_recommendations(industry, num_employees, main_tasks_text, annual_labor_savings)
st.session_state.calculations_done = True
st.session_state.calculations = calculations
st.session_state.ai_recommendations = recommendations
st.session_state.business_info = {
'company': company_name,
'industry': industry,
'employees': num_employees,
'email': email,
'phone': phone,
'tasks': selected_tasks,
'avg_wage': avg_hourly_wage
}
# Send email notification
send_lead_notification(st.session_state.business_info, st.session_state.calculations)
# Display results
if st.session_state.calculations_done:
st.success("Your AI ROI Analysis is Complete!")
calc = st.session_state.calculations
# Key Metrics
col1, col2, col3, col4 = st.columns(4)
with col1:
st.markdown(f"""
<div class="metric-card">
<div class="metric-value">${calc['annual_ongoing_savings']:,.0f}</div>
<div class="metric-label">Annual Net Savings</div>
</div>
""", unsafe_allow_html=True)
with col2:
st.markdown(f"""
<div class="metric-card">
<div class="metric-value">{calc['hours_saved']:.1f}</div>
<div class="metric-label">Hours Saved Per Week</div>
</div>
""", unsafe_allow_html=True)
with col3:
st.markdown(f"""
<div class="metric-card">
<div class="metric-value">{calc['roi_three_year']:.0f}%</div>
<div class="metric-label">3-Year ROI</div>
</div>
""", unsafe_allow_html=True)
with col4:
st.markdown(f"""
<div class="metric-card">
<div class="metric-value">{calc['payback_months']:.1f}</div>
<div class="metric-label">Payback (Months)</div>
</div>
""", unsafe_allow_html=True)
# Cost Breakdown Section
st.subheader("Investment Breakdown")
col1, col2 = st.columns(2)
with col1:
st.markdown("**Annual Labor Savings from AI:**")
st.success(f"${calc['annual_labor_savings']:,.0f}")
st.markdown("**AI Implementation Costs:**")
st.info(f"""
- **Setup & Training:** ${calc['ai_costs']['setup']:,.0f}
- **Annual Software:** ${calc['ai_costs']['annual_software']:,.0f}
- **Annual Maintenance:** ${calc['ai_costs']['annual_maintenance']:,.0f}
- **Total Year 1:** ${calc['ai_costs']['total_year_one']:,.0f}
""")
with col2:
st.markdown("**Net Financial Impact:**")
year_one_color = "success" if calc['year_one_savings'] > 0 else "warning"
getattr(st, year_one_color)(f"**Year 1 Net Savings:** ${calc['year_one_savings']:,.0f}")
st.success(f"**Ongoing Annual Savings:** ${calc['annual_ongoing_savings']:,.0f}")
st.info(f"**Monthly Savings (Year 2+):** ${calc['monthly_savings']:,.0f}")
# AI Recommendations
if st.session_state.ai_recommendations:
st.subheader("Your Personalized AI Recommendations")
for i, rec in enumerate(st.session_state.ai_recommendations['recommendations'], 1):
priority_color = {"High": "#dc3545", "Medium": "#ffc107", "Low": "#28a745"}
color = priority_color.get(rec['priority'], "#6c757d")
st.markdown(f"""
<div class="recommendation-box">
<h4 style="margin-top: 0; color: #1f4e79;">{i}. {rec['title']}
<span style="background: {color}; color: white; padding: 2px 8px; border-radius: 12px; font-size: 0.8em; margin-left: 10px;">{rec['priority']}</span></h4>
<p><strong>Description:</strong> {rec['description']}</p>
<p><strong>Expected Impact:</strong> {rec['impact']}</p>
<p><strong>Implementation:</strong> {rec['implementation']}</p>
</div>
""", unsafe_allow_html=True)
# Next steps
st.subheader("Recommended Next Steps")
st.info(st.session_state.ai_recommendations['next_steps'])
st.info(f"**Timeline:** {st.session_state.ai_recommendations['timeline']}")
# Download report
st.subheader("Download Your Report")
if st.button("Generate PDF Report", use_container_width=True):
with st.spinner("Generating your personalized PDF report..."):
pdf_buffer = generate_pdf_report(
st.session_state.business_info,
st.session_state.calculations,
st.session_state.ai_recommendations
)
st.download_button(
label="Download AI ROI Report",
data=pdf_buffer,
file_name=f"AI_ROI_Report_{st.session_state.business_info['company'].replace(' ', '_')}_{datetime.now().strftime('%Y%m%d')}.pdf",
mime="application/pdf",
use_container_width=True
)
# Call to action
st.markdown("""
<div class="footer">
<h3>Ready to Transform Your Business with AI?</h3>
<p>Let's discuss how Eau Claire AI can help you implement these recommendations and start saving time and money.</p>
<p><strong>Schedule a free consultation:</strong> hello@eauclaireai.com</p>
<p><strong>Website:</strong> www.eauclaireai.com</p>
<p><em>Your path to AI, made clear.</em></p>
</div>
""", unsafe_allow_html=True)
# Reset button
if st.session_state.calculations_done:
if st.button("Calculate for Another Business", use_container_width=True):
st.session_state.calculations_done = False
st.session_state.ai_recommendations = None
st.rerun()