Files
bussines_case_automation/index.html
andrei 0e2e1bddba Add xlsxwriter-based Excel generation scripts with openpyxl implementation
- Created create_excel_xlsxwriter.py and update_excel_xlsxwriter.py
- Uses openpyxl exclusively to preserve Excel formatting and formulas
- Updated server.js to use new xlsxwriter scripts for form submissions
- Maintains all original functionality while ensuring proper Excel file handling

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-22 13:53:06 +00:00

1607 lines
88 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Retail Media Business Case</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
/* Progress bar container */
.progress-container {
position: relative;
margin-bottom: 2.5rem;
padding-top: 8px;
}
/* Step labels styling */
.step-label {
position: relative;
transition: all 0.3s ease;
font-size: 0.75rem;
font-weight: 500;
color: #6B7280; /* Gray-500 */
cursor: default;
margin-top: 24px;
}
.step-label.active {
color: #eb742e; /* Orange brand color */
font-weight: 600;
}
/* Progress bar container */
.progress-track {
position: relative;
height: 6px;
width: 100%;
margin: 14px 0;
}
/* Progress bar styling */
#progressBar {
position: absolute;
left: 0;
top: 0;
transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1);
height: 6px;
background: linear-gradient(90deg, #f59e0b, #eb742e);
box-shadow: 0 1px 2px rgba(235, 116, 46, 0.3);
border-radius: 3px;
}
/* Progress bar background */
.progress-bg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 6px;
background-color: #e5e7eb;
border-radius: 3px;
}
/* Percentage indicator */
.progress-percent {
font-weight: 600;
color: #eb742e;
}
/* Step indicators */
.step-indicator {
position: absolute;
width: 16px;
height: 16px;
background-color: #e5e7eb; /* Gray-200 */
border: 2px solid #ffffff; /* White border */
border-radius: 50%;
top: 50%;
transform: translate(-50%, -50%);
transition: all 0.3s ease;
z-index: 10;
}
.step-indicator.active {
background-color: #eb742e; /* Orange brand color */
border-color: #ffffff;
width: 20px;
height: 20px;
box-shadow: 0 0 0 3px rgba(235, 116, 46, 0.2);
}
</style>
</head>
<body class="bg-white min-h-screen flex items-center justify-center py-8">
<div class="w-full max-w-[600px] mx-auto px-4 sm:px-6">
<div class="text-center mb-6">
<h1 class="text-4xl font-bold text-black mb-2">Retail Media Business Case</h1>
<p class="text-base text-gray-600">Complete the form below, and our retail media specialists will reach out soon.</p>
</div>
<!-- Progress Bar -->
<div class="progress-container mb-8">
<div class="flex justify-between items-center mb-3">
<span class="text-sm font-medium text-gray-600">Step <span id="currentStep">1</span> of 6</span>
<span class="text-sm progress-percent"><span id="progressPercent">16.67</span>%</span>
</div>
<div class="progress-track">
<!-- Progress bar background -->
<div class="progress-bg"></div>
<!-- Active progress bar -->
<div id="progressBar" style="width: 0%"></div>
<!-- Step indicators with first at 0% and last at 100% -->
<div class="step-indicator active" style="left: 0%"></div>
<div class="step-indicator" style="left: 20%"></div>
<div class="step-indicator" style="left: 40%"></div>
<div class="step-indicator" style="left: 60%"></div>
<div class="step-indicator" style="left: 80%"></div>
<div class="step-indicator" style="left: 100%"></div>
</div>
<!-- Step labels -->
<div class="flex justify-between">
<span class="step-label active" data-step="1" style="width: 16.66%; text-align: center;">Contact</span>
<span class="step-label" data-step="2" style="width: 16.66%; text-align: center;">Store Details</span>
<span class="step-label" data-step="3" style="width: 16.66%; text-align: center;">In-Store</span>
<span class="step-label" data-step="4" style="width: 16.66%; text-align: center;">On-Site</span>
<span class="step-label" data-step="5" style="width: 16.66%; text-align: center;">Off-Site</span>
<span class="step-label" data-step="6" style="width: 16.66%; text-align: center;">Business Case</span>
</div>
</div>
<div class="bg-gray-50 p-8 rounded-lg shadow-sm">
<form id="retailForm" class="space-y-6">
<!-- Step 1: Contact Information -->
<div id="step1" class="step-content">
<h2 class="text-xl font-bold text-gray-700 mb-5">Contact Information</h2>
<div class="space-y-5">
<!-- First Name -->
<div>
<label for="firstName" class="block text-base font-medium text-gray-700 mb-1">First Name</label>
<input type="text" id="firstName" name="firstName" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
<!-- Last Name -->
<div>
<label for="lastName" class="block text-base font-medium text-gray-700 mb-1">Last Name</label>
<input type="text" id="lastName" name="lastName" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
<!-- Company -->
<div>
<label for="company" class="block text-base font-medium text-gray-700 mb-1">Company Name</label>
<input type="text" id="company" name="company" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
<!-- Country -->
<div>
<label for="country" class="block text-base font-medium text-gray-700 mb-1">Country</label>
<input type="text" id="country" name="country" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
<!-- Email -->
<div>
<label for="email" class="block text-base font-medium text-gray-700 mb-1">Business Email Address</label>
<input type="email" id="email" name="email" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
<!-- Phone -->
<div>
<label for="phone" class="block text-base font-medium text-gray-700 mb-1">Phone Number</label>
<input type="tel" id="phone" name="phone" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
</div>
<!-- Step 2: Store Details -->
<div id="step2" class="step-content hidden">
<h2 class="text-xl font-bold text-gray-700 mb-5">Store Details</h2>
<div class="space-y-5">
<!-- Store Name -->
<div>
<label for="storeName" class="block text-base font-medium text-gray-700 mb-1">Enter your retail store/s name</label>
<input type="text" id="storeName" name="storeName" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
<!-- Starting Date -->
<div>
<label for="startingDate" class="block text-base font-medium text-gray-700 mb-1">Starting Date</label>
<input type="date" id="startingDate" name="startingDate" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
<!-- Duration -->
<div>
<label for="duration" class="block text-base font-medium text-gray-700 mb-1">Planning Duration Time (months - recommended 36)</label>
<input type="number" id="duration" name="duration" value="36" min="1" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
</div>
<!-- Step 3: In-Store Information -->
<div id="step3" class="step-content hidden">
<h2 class="text-xl font-bold text-gray-700 mb-5">In-Store Information</h2>
<div class="space-y-5">
<!-- Store open days -->
<div>
<label for="openDays" class="block text-base font-medium text-gray-700 mb-1">Stores open days/month</label>
<input type="number" id="openDays" name="openDays" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
<!-- Store Types Dropdown -->
<div>
<label class="block text-base font-medium text-gray-700 mb-1">Store Types <span class="text-orange-500">*</span></label>
<div class="relative">
<div class="p-3 border border-gray-300 rounded-lg bg-white cursor-pointer" id="storeTypeDropdownToggle">
<div class="flex justify-between items-center">
<div class="flex flex-wrap gap-2" id="storeTypeSelectedOptions">
<!-- Selected options will appear here as pills -->
</div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
</svg>
</div>
</div>
<!-- Dropdown content -->
<div id="storeTypeDropdownContent" class="absolute z-10 mt-1 w-full bg-white border border-gray-200 rounded-lg shadow-lg hidden">
<div class="relative">
<button type="button" onclick="closeDropdown('storeTypeDropdownContent')" class="absolute top-2 right-2 text-gray-500 hover:text-gray-700 focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
<div class="p-2">
<div id="convenience-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectStoreTypeOption('convenience', 'Convenience', 'bg-[#eb742e] text-white')">
<span class="text-sm text-gray-700">Convenience</span>
</div>
<div id="minimarket-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectStoreTypeOption('minimarket', 'Minimarket', 'bg-[#ec8038] text-white')">
<span class="text-sm text-gray-700">Minimarket</span>
</div>
<div id="supermarket-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectStoreTypeOption('supermarket', 'Supermarket', 'bg-[#f08343] text-white')">
<span class="text-sm text-gray-700">Supermarket</span>
</div>
<div id="hypermarket-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectStoreTypeOption('hypermarket', 'Hypermarket', 'bg-[#f49258] text-white')">
<span class="text-sm text-gray-700">Hypermarket</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Store Type specific sections will appear here -->
<div id="storeTypeDetailsSections" class="space-y-6">
<!-- Dynamically generated sections will be inserted here -->
</div>
</div>
</div>
<!-- Step 4: On-Site Channel -->
<div id="step4" class="step-content hidden">
<h2 class="text-xl font-bold text-gray-700 mb-5">On-Site Channel</h2>
<div class="space-y-5">
<div>
<label class="block text-base font-medium text-gray-700 mb-1">Please select the on-site channels you are currently using <span class="text-orange-500">*</span></label>
<div class="relative">
<div class="p-3 border border-gray-200 rounded-lg bg-white cursor-pointer" id="onSiteDropdownToggle">
<div class="flex justify-between items-center">
<div class="flex flex-wrap gap-2" id="onSiteSelectedOptions">
<!-- Selected options will appear here as pills -->
</div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
</svg>
</div>
</div>
<!-- Dropdown content -->
<div id="onSiteDropdownContent" class="absolute z-10 mt-1 w-full bg-white border border-gray-200 rounded-lg shadow-lg hidden">
<div class="relative">
<button type="button" onclick="closeDropdown('onSiteDropdownContent')" class="absolute top-2 right-2 text-gray-500 hover:text-gray-700 focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
<div class="p-2">
<div id="website-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectOnSiteOption('website', 'Website', 'bg-[#eb742e] text-white')">
<span class="text-sm text-gray-700">Website</span>
</div>
<div id="app-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectOnSiteOption('app', 'Mobile App', 'bg-[#f08343] text-white')">
<span class="text-sm text-gray-700">Mobile App</span>
</div>
<div id="loyalty-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectOnSiteOption('loyalty', 'Loyalty Program', 'bg-[#f49258] text-white')">
<span class="text-sm text-gray-700">Loyalty Program</span>
</div>
<div id="none-onsite-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectNoneOption('onsite')">
<span class="text-sm text-gray-700">None</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Website Questions (Hidden by default) -->
<div id="websiteQuestions" class="space-y-4 hidden">
<div>
<label for="websiteVisitors" class="block text-base font-medium text-gray-700 mb-1">How many unique monthly visitors does your website receive on average? <span class="text-orange-500">*</span></label>
<input type="number" id="websiteVisitors" name="websiteVisitors"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
<!-- Mobile App Questions (Hidden by default) -->
<div id="appQuestions" class="space-y-4 hidden">
<div>
<label for="appUsers" class="block text-base font-medium text-gray-700 mb-1">What is the average number of active monthly users on your mobile app? <span class="text-orange-500">*</span></label>
<input type="number" id="appUsers" name="appUsers"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
<!-- Loyalty Program Questions (Hidden by default) -->
<div id="loyaltyQuestions" class="space-y-4 hidden">
<div>
<label for="loyaltyUsers" class="block text-base font-medium text-gray-700 mb-1">How many users are actively engaging with your loyalty program on a monthly basis? <span class="text-orange-500">*</span></label>
<input type="number" id="loyaltyUsers" name="loyaltyUsers"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
</div>
</div>
<!-- Step 5: Off-Site Channel -->
<div id="step5" class="step-content hidden">
<h2 class="text-xl font-bold text-gray-700 mb-5">Off-Site Channel</h2>
<div class="space-y-5">
<div>
<label class="block text-base font-medium text-gray-700 mb-1">Please select the off-site channels you are currently using <span class="text-orange-500">*</span></label>
<div class="relative">
<div class="p-3 border border-gray-200 rounded-lg bg-white cursor-pointer" id="offSiteDropdownToggle">
<div class="flex justify-between items-center">
<div class="flex flex-wrap gap-2" id="offSiteSelectedOptions">
<!-- Selected options will appear here as pills -->
</div>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
</svg>
</div>
</div>
<!-- Dropdown content -->
<div id="offSiteDropdownContent" class="absolute z-10 mt-1 w-full bg-white border border-gray-200 rounded-lg shadow-lg hidden">
<div class="relative">
<button type="button" onclick="closeDropdown('offSiteDropdownContent')" class="absolute top-2 right-2 text-gray-500 hover:text-gray-700 focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
<div class="p-2">
<div id="facebook-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectOffSiteOption('facebook', 'Facebook Business', 'bg-[#f8a16d] text-white')">
<span class="text-sm text-gray-700">Facebook Business</span>
</div>
<div id="instagram-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectOffSiteOption('instagram', 'Instagram Business', 'bg-[#fbaf82] text-white')">
<span class="text-sm text-gray-700">Instagram Business</span>
</div>
<div id="google-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectOffSiteOption('google', 'Google Business Profile', 'bg-[#fdbd98] text-white')">
<span class="text-sm text-gray-700">Google Business Profile</span>
</div>
<div id="email-marketing-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectOffSiteOption('email-marketing', 'Email', 'bg-[#feccae] text-white')">
<span class="text-sm text-gray-700">Email</span>
</div>
<div id="sms-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectOffSiteOption('sms', 'SMS', 'bg-[#ffdac4] text-white')">
<span class="text-sm text-gray-700">SMS</span>
</div>
<div id="whatsapp-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectOffSiteOption('whatsapp', 'WhatsApp', 'bg-[#eb742e] text-white')">
<span class="text-sm text-gray-700">WhatsApp</span>
</div>
<div id="none-offsite-option" class="py-1 px-3 hover:bg-gray-50 rounded-md cursor-pointer flex items-center" onclick="selectNoneOption('offsite')">
<span class="text-sm text-gray-700">None</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Facebook Questions (Hidden by default) -->
<div id="facebookQuestions" class="space-y-4 hidden">
<div>
<label for="facebookFollowers" class="block text-base font-medium text-gray-700 mb-1">What is your current number of monthly followers or reach on your Facebook Business page? <span class="text-orange-500">*</span></label>
<input type="number" id="facebookFollowers" name="facebookFollowers"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
<!-- Instagram Questions (Hidden by default) -->
<div id="instagramQuestions" class="space-y-4 hidden">
<div>
<label for="instagramFollowers" class="block text-base font-medium text-gray-700 mb-1">How many monthly followers or active users do you have on your Instagram Business account? <span class="text-orange-500">*</span></label>
<input type="number" id="instagramFollowers" name="instagramFollowers"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
<!-- Google Questions (Hidden by default) -->
<div id="googleQuestions" class="space-y-4 hidden">
<div>
<label for="googleViews" class="block text-base font-medium text-gray-700 mb-1">How many monthly views or interactions does your Google Business Profile receive? <span class="text-orange-500">*</span></label>
<input type="number" id="googleViews" name="googleViews"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
<!-- Email Marketing Questions (Hidden by default) -->
<div id="emailMarketingQuestions" class="space-y-4 hidden">
<div>
<label for="emailSubscribers" class="block text-base font-medium text-gray-700 mb-1">How many active email subscribers do you engage with on a monthly basis? <span class="text-orange-500">*</span></label>
<input type="number" id="emailSubscribers" name="emailSubscribers"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
<!-- SMS Questions (Hidden by default) -->
<div id="smsQuestions" class="space-y-4 hidden">
<div>
<label for="smsUsers" class="block text-base font-medium text-gray-700 mb-1">How many users receive your SMS campaigns each month? <span class="text-orange-500">*</span></label>
<input type="number" id="smsUsers" name="smsUsers"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
<!-- WhatsApp Questions (Hidden by default) -->
<div id="whatsappQuestions" class="space-y-4 hidden">
<div>
<label for="whatsappContacts" class="block text-base font-medium text-gray-700 mb-1">How many monthly subscribers or active contacts do you have on WhatsApp? <span class="text-orange-500">*</span></label>
<input type="number" id="whatsappContacts" name="whatsappContacts"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
</div>
</div>
<!-- Step 6: Business Case Generation -->
<div id="step6" class="step-content hidden">
<h2 class="text-xl font-bold text-gray-700 mb-5">Business Case Generation</h2>
<div class="space-y-5">
<p class="text-gray-600">Thank you for providing all the necessary information. Click the button below to generate your retail media business case.</p>
<div class="bg-gray-100 p-4 rounded-lg">
<p class="text-sm text-gray-500">Your business case will include:</p>
<ul class="list-disc pl-5 mt-2 text-sm text-gray-600">
<li>Personalized retail media recommendations</li>
<li>Potential reach and impression estimates</li>
<li>Channel optimization suggestions</li>
<li>Implementation guidance</li>
</ul>
</div>
</div>
</div>
<!-- Navigation Buttons -->
<div class="flex justify-between pt-6 mt-6">
<button type="button" id="prevBtn" class="px-6 py-2 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 font-medium hidden">
Previous
</button>
<div class="flex-grow"></div>
<button type="button" id="nextBtn" class="px-6 py-2 bg-gradient-to-r from-yellow-400 to-orange-500 text-white rounded-md hover:from-yellow-500 hover:to-orange-600 font-medium">
Continue
</button>
<button type="button" id="submitBtn" class="px-10 py-3 bg-gradient-to-r from-yellow-400 to-orange-500 text-white rounded-[10px] hover:from-yellow-500 hover:to-orange-600 font-bold text-lg uppercase tracking-wide transition-all shadow-md hover:shadow-lg hidden">
SUBMIT
</button>
</div>
</form>
</div>
</div>
<script>
// Multi-step form navigation
let currentStep = 1;
const totalSteps = 6;
// Elements
const prevBtn = document.getElementById('prevBtn');
const nextBtn = document.getElementById('nextBtn');
const submitBtn = document.getElementById('submitBtn');
const progressBar = document.getElementById('progressBar');
const currentStepEl = document.getElementById('currentStep');
const progressPercentEl = document.getElementById('progressPercent');
const stepLabels = document.querySelectorAll('.step-label');
// Initialize
updateProgressBar();
// Event listeners for navigation buttons
prevBtn.addEventListener('click', goToPreviousStep);
nextBtn.addEventListener('click', goToNextStep);
// Direct event listener for submit button
submitBtn.addEventListener('click', function(e) {
console.log('Submit button clicked directly');
e.preventDefault(); // Prevent default to handle it manually
// Manually trigger form submission
const form = document.getElementById('retailForm');
// Validate the final step
if (!validateStep(6)) {
console.log('Form validation failed from submit button click');
return;
}
console.log('Form validation passed from submit button click');
// Disable the button to prevent double submission
submitBtn.disabled = true;
submitBtn.textContent = 'SUBMITTING...';
// Gather form data
const formData = new FormData(form);
const formObject = {};
// Convert FormData to an object
formData.forEach((value, key) => {
if (formObject[key]) {
if (!Array.isArray(formObject[key])) {
formObject[key] = [formObject[key]];
}
formObject[key].push(value);
} else {
formObject[key] = value;
}
});
// Send the data to the server
console.log('Manually sending data to server:', formObject);
fetch('/calculate', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formObject)
})
.then(response => {
console.log('Server response from manual submission:', response);
return response.json();
})
.then(data => {
console.log('Response data from manual submission:', data);
if (data.success) {
// Redirect to the thank you page
window.location.href = '/thank-you.html';
} else {
alert('Error: ' + data.message);
// Reset submit button
submitBtn.disabled = false;
submitBtn.textContent = 'SUBMIT';
}
})
.catch(error => {
console.error('Error submitting form manually:', error);
alert('An error occurred while processing your submission. Please try again.');
// Reset submit button
submitBtn.disabled = false;
submitBtn.textContent = 'SUBMIT';
console.log('Error details from manual submission:', error);
});
});
function goToNextStep() {
// Validate current step
if (!validateStep(currentStep)) {
return;
}
// Hide current step
document.getElementById(`step${currentStep}`).classList.add('hidden');
// Show next step
currentStep++;
document.getElementById(`step${currentStep}`).classList.remove('hidden');
// Update UI
updateNavigationButtons();
updateProgressBar();
}
function goToPreviousStep() {
// Hide current step
document.getElementById(`step${currentStep}`).classList.add('hidden');
// Show previous step
currentStep--;
document.getElementById(`step${currentStep}`).classList.remove('hidden');
// Update UI
updateNavigationButtons();
updateProgressBar();
}
function updateNavigationButtons() {
// Show/hide previous button
if (currentStep > 1) {
prevBtn.classList.remove('hidden');
} else {
prevBtn.classList.add('hidden');
}
// Show continue or submit button
if (currentStep === totalSteps) {
nextBtn.classList.add('hidden');
submitBtn.classList.remove('hidden');
} else {
nextBtn.classList.remove('hidden');
submitBtn.classList.add('hidden');
}
}
function updateProgressBar() {
// Get the positions for each step
const stepPositions = [0, 20, 40, 60, 80, 100];
// Set the progress bar width to the current step's position
const progressWidth = stepPositions[currentStep - 1];
progressBar.style.width = `${progressWidth}%`;
currentStepEl.textContent = currentStep;
progressPercentEl.textContent = Math.round((currentStep / totalSteps) * 100);
// Update step labels and indicators
stepLabels.forEach(label => {
const step = parseInt(label.getAttribute('data-step'));
if (step <= currentStep) {
label.classList.add('active');
} else {
label.classList.remove('active');
}
});
// Update step indicators
const stepIndicators = document.querySelectorAll('.step-indicator');
stepIndicators.forEach((indicator, index) => {
if (index + 1 <= currentStep) {
indicator.classList.add('active');
} else {
indicator.classList.remove('active');
}
});
}
function validateStep(step) {
console.log(`Validating step ${step}`);
// Special case for step 6 (final step) which has no required fields
if (step === 6) {
console.log('Step 6 validation - always valid as it has no required fields');
return true;
}
// Get all required inputs in the current step
const currentStepEl = document.getElementById(`step${step}`);
const requiredInputs = currentStepEl.querySelectorAll('input[required]:not([disabled]), select[required]:not([disabled])');
console.log(`Found ${requiredInputs.length} required inputs in step ${step}`);
// Check if all required fields are filled
let isValid = true;
requiredInputs.forEach(input => {
console.log(`Checking required input: ${input.name || input.id}, value: ${input.value}, type: ${input.type}`);
if (!input.value) {
isValid = false;
input.classList.add('border-red-500');
console.log(`Invalid input: ${input.name || input.id} - no value`);
// Add event listener to remove error styling when user starts typing
input.addEventListener('input', function() {
this.classList.remove('border-red-500');
}, { once: true });
}
});
// Special validation for store type dropdown in step 3
if (step === 3) {
// Check if store type checkboxes exist
const convCheckbox = document.getElementById('convenience');
const superCheckbox = document.getElementById('supermarket');
const hyperCheckbox = document.getElementById('hypermarket');
console.log('Store type checkboxes status:');
console.log(`- convenience: ${convCheckbox ? (convCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
console.log(`- supermarket: ${superCheckbox ? (superCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
console.log(`- hypermarket: ${hyperCheckbox ? (hyperCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
// Validate store type dropdown selection
const storeTypeSelected =
(convCheckbox && convCheckbox.checked) ||
(superCheckbox && superCheckbox.checked) ||
(hyperCheckbox && hyperCheckbox.checked);
if (!storeTypeSelected) {
isValid = false;
document.getElementById('storeTypeDropdownToggle').classList.add('border-red-500');
console.log('No store type selected - validation failed');
// Add event listener to remove error styling when dropdown is clicked
document.getElementById('storeTypeDropdownToggle').addEventListener('click', function() {
this.classList.remove('border-red-500');
}, { once: true });
}
}
// Special validation for dropdowns in steps 4 and 5
if (step === 4) {
// Check if at least one on-site channel is selected or none is selected
const websiteCheckbox = document.getElementById('website');
const appCheckbox = document.getElementById('app');
const loyaltyCheckbox = document.getElementById('loyalty');
const noneOnsite = document.querySelector('.pill-none-onsite');
console.log('On-site channel checkboxes status:');
console.log(`- website: ${websiteCheckbox ? (websiteCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
console.log(`- app: ${appCheckbox ? (appCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
console.log(`- loyalty: ${loyaltyCheckbox ? (loyaltyCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
console.log(`- none pill: ${noneOnsite ? 'present' : 'not present'}`);
const onSiteSelected =
(websiteCheckbox && websiteCheckbox.checked) ||
(appCheckbox && appCheckbox.checked) ||
(loyaltyCheckbox && loyaltyCheckbox.checked) ||
noneOnsite;
if (!onSiteSelected) {
isValid = false;
document.getElementById('onSiteDropdownToggle').classList.add('border-red-500');
console.log('No on-site channel selected - validation failed');
}
}
if (step === 5) {
// Check if at least one off-site channel is selected or none is selected
const fbCheckbox = document.getElementById('facebook');
const igCheckbox = document.getElementById('instagram');
const googleCheckbox = document.getElementById('google');
const emailCheckbox = document.getElementById('email-marketing');
const smsCheckbox = document.getElementById('sms');
const waCheckbox = document.getElementById('whatsapp');
const noneOffsite = document.querySelector('.pill-none-offsite');
console.log('Off-site channel checkboxes status:');
console.log(`- facebook: ${fbCheckbox ? (fbCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
console.log(`- instagram: ${igCheckbox ? (igCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
console.log(`- google: ${googleCheckbox ? (googleCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
console.log(`- email: ${emailCheckbox ? (emailCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
console.log(`- sms: ${smsCheckbox ? (smsCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
console.log(`- whatsapp: ${waCheckbox ? (waCheckbox.checked ? 'checked' : 'unchecked') : 'not found'}`);
console.log(`- none pill: ${noneOffsite ? 'present' : 'not present'}`);
const offSiteSelected =
(fbCheckbox && fbCheckbox.checked) ||
(igCheckbox && igCheckbox.checked) ||
(googleCheckbox && googleCheckbox.checked) ||
(emailCheckbox && emailCheckbox.checked) ||
(smsCheckbox && smsCheckbox.checked) ||
(waCheckbox && waCheckbox.checked) ||
noneOffsite;
if (!offSiteSelected) {
isValid = false;
document.getElementById('offSiteDropdownToggle').classList.add('border-red-500');
console.log('No off-site channel selected - validation failed');
}
}
console.log(`Step ${step} validation result: ${isValid ? 'VALID' : 'INVALID'}`);
if (!isValid) {
// Show error message
alert('Please fill in all required fields before proceeding.');
}
return isValid;
}
// Toggle dropdown visibility
document.getElementById('onSiteDropdownToggle').addEventListener('click', function() {
const dropdown = document.getElementById('onSiteDropdownContent');
dropdown.classList.toggle('hidden');
});
document.getElementById('offSiteDropdownToggle').addEventListener('click', function() {
const dropdown = document.getElementById('offSiteDropdownContent');
dropdown.classList.toggle('hidden');
});
document.getElementById('storeTypeDropdownToggle').addEventListener('click', function() {
const dropdown = document.getElementById('storeTypeDropdownContent');
dropdown.classList.toggle('hidden');
});
// Close dropdowns when clicking outside
document.addEventListener('click', function(event) {
const onSiteDropdown = document.getElementById('onSiteDropdownContent');
const offSiteDropdown = document.getElementById('offSiteDropdownContent');
const storeTypeDropdown = document.getElementById('storeTypeDropdownContent');
const onSiteToggle = document.getElementById('onSiteDropdownToggle');
const offSiteToggle = document.getElementById('offSiteDropdownToggle');
const storeTypeToggle = document.getElementById('storeTypeDropdownToggle');
if (!onSiteToggle.contains(event.target) && !onSiteDropdown.contains(event.target)) {
onSiteDropdown.classList.add('hidden');
}
if (!offSiteToggle.contains(event.target) && !offSiteDropdown.contains(event.target)) {
offSiteDropdown.classList.add('hidden');
}
if (!storeTypeToggle.contains(event.target) && !storeTypeDropdown.contains(event.target)) {
storeTypeDropdown.classList.add('hidden');
}
});
// Add hidden checkboxes for form submission if they don't exist
function ensureCheckboxExists(id, name, value) {
if (!document.getElementById(id)) {
console.log(`Creating hidden checkbox: ${id}, ${name}, ${value}`);
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.id = id;
checkbox.name = name;
checkbox.value = value;
checkbox.style.display = 'none';
document.getElementById('retailForm').appendChild(checkbox);
} else {
console.log(`Checkbox already exists: ${id}`);
}
}
// Ensure all checkboxes exist
ensureCheckboxExists('website', 'onSiteChannels', 'Website');
ensureCheckboxExists('app', 'onSiteChannels', 'Mobile App');
ensureCheckboxExists('loyalty', 'onSiteChannels', 'Loyalty Program');
ensureCheckboxExists('facebook', 'offSiteChannels', 'Facebook Business');
ensureCheckboxExists('instagram', 'offSiteChannels', 'Instagram Business');
ensureCheckboxExists('google', 'offSiteChannels', 'Google Business Profile');
ensureCheckboxExists('email-marketing', 'offSiteChannels', 'Email');
ensureCheckboxExists('sms', 'offSiteChannels', 'SMS');
ensureCheckboxExists('whatsapp', 'offSiteChannels', 'WhatsApp');
// Ensure store type checkboxes exist
ensureCheckboxExists('convenience', 'storeTypes', 'Convenience');
ensureCheckboxExists('minimarket', 'storeTypes', 'Minimarket');
ensureCheckboxExists('supermarket', 'storeTypes', 'Supermarket');
ensureCheckboxExists('hypermarket', 'storeTypes', 'Hypermarket');
function toggleScreenQuestions(show) {
const screenQuestions = document.getElementById('screenQuestions');
const screenCount = document.getElementById('screenCount');
const screenPercentage = document.getElementById('screenPercentage');
if (show) {
screenQuestions.classList.remove('hidden');
screenCount.required = true;
screenPercentage.required = true;
} else {
screenQuestions.classList.add('hidden');
screenCount.required = false;
screenPercentage.required = false;
// Clear values when hidden
screenCount.value = '';
screenPercentage.value = '';
}
}
function toggleRadioQuestions(show) {
const radioQuestions = document.getElementById('radioQuestions');
const radioPercentage = document.getElementById('radioPercentage');
if (show) {
radioQuestions.classList.remove('hidden');
radioPercentage.required = true;
} else {
radioQuestions.classList.add('hidden');
radioPercentage.required = false;
// Clear value when hidden
radioPercentage.value = '';
}
}
// On-site option selection
function selectOnSiteOption(id, text, colorClass) {
// Hide the option in the dropdown
document.getElementById(`${id}-option`).classList.add('hidden');
// Create and add pill to the input
const selectedContainer = document.getElementById('onSiteSelectedOptions');
const pill = document.createElement('div');
pill.className = `${colorClass} py-1 px-3 rounded-full flex items-center pill-${id}`;
pill.innerHTML = `
<span class="mr-1">${text}</span>
<button type="button" onclick="removeOnSiteOption('${id}', '${text}', '${colorClass}')" class="ml-1 focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
`;
selectedContainer.appendChild(pill);
// Set the hidden checkbox to checked
const checkbox = document.getElementById(id);
checkbox.checked = true;
// Show the related questions
if (id === 'website') {
document.getElementById('websiteQuestions').classList.remove('hidden');
document.getElementById('websiteVisitors').required = true;
} else if (id === 'app') {
document.getElementById('appQuestions').classList.remove('hidden');
document.getElementById('appUsers').required = true;
} else if (id === 'loyalty') {
document.getElementById('loyaltyQuestions').classList.remove('hidden');
document.getElementById('loyaltyUsers').required = true;
}
// Close the dropdown
document.getElementById('onSiteDropdownContent').classList.add('hidden');
}
// Remove on-site option
function removeOnSiteOption(id, text, colorClass) {
// Remove the pill
const pillToRemove = document.querySelector(`.pill-${id}`);
if (pillToRemove) {
document.getElementById('onSiteSelectedOptions').removeChild(pillToRemove);
}
// Show the option in the dropdown again
document.getElementById(`${id}-option`).classList.remove('hidden');
// Set the hidden checkbox to unchecked
const checkbox = document.getElementById(id);
checkbox.checked = false;
// Hide the related questions
if (id === 'website') {
document.getElementById('websiteQuestions').classList.add('hidden');
document.getElementById('websiteVisitors').required = false;
document.getElementById('websiteVisitors').value = '';
} else if (id === 'app') {
document.getElementById('appQuestions').classList.add('hidden');
document.getElementById('appUsers').required = false;
document.getElementById('appUsers').value = '';
} else if (id === 'loyalty') {
document.getElementById('loyaltyQuestions').classList.add('hidden');
document.getElementById('loyaltyUsers').required = false;
document.getElementById('loyaltyUsers').value = '';
}
// Stop propagation to prevent dropdown from toggling
event.stopPropagation();
}
// Off-site option selection
function selectOffSiteOption(id, text, colorClass) {
// Hide the option in the dropdown
document.getElementById(`${id}-option`).classList.add('hidden');
// Create and add pill to the input
const selectedContainer = document.getElementById('offSiteSelectedOptions');
const pill = document.createElement('div');
pill.className = `${colorClass} py-1 px-3 rounded-full flex items-center pill-${id}`;
pill.innerHTML = `
<span class="mr-1">${text}</span>
<button type="button" onclick="removeOffSiteOption('${id}', '${text}', '${colorClass}')" class="ml-1 focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
`;
selectedContainer.appendChild(pill);
// Set the hidden checkbox to checked
const checkbox = document.getElementById(id);
checkbox.checked = true;
// Show the related questions
if (id === 'facebook') {
document.getElementById('facebookQuestions').classList.remove('hidden');
document.getElementById('facebookFollowers').required = true;
} else if (id === 'instagram') {
document.getElementById('instagramQuestions').classList.remove('hidden');
document.getElementById('instagramFollowers').required = true;
} else if (id === 'google') {
document.getElementById('googleQuestions').classList.remove('hidden');
document.getElementById('googleViews').required = true;
} else if (id === 'email-marketing') {
document.getElementById('emailMarketingQuestions').classList.remove('hidden');
document.getElementById('emailSubscribers').required = true;
} else if (id === 'sms') {
document.getElementById('smsQuestions').classList.remove('hidden');
document.getElementById('smsUsers').required = true;
} else if (id === 'whatsapp') {
document.getElementById('whatsappQuestions').classList.remove('hidden');
document.getElementById('whatsappContacts').required = true;
}
// Close the dropdown
document.getElementById('offSiteDropdownContent').classList.add('hidden');
}
// Remove off-site option
function removeOffSiteOption(id, text, colorClass) {
// Remove the pill
const pillToRemove = document.querySelector(`.pill-${id}`);
if (pillToRemove) {
document.getElementById('offSiteSelectedOptions').removeChild(pillToRemove);
}
// Show the option in the dropdown again
document.getElementById(`${id}-option`).classList.remove('hidden');
// Set the hidden checkbox to unchecked
const checkbox = document.getElementById(id);
checkbox.checked = false;
// Hide the related questions
if (id === 'facebook') {
document.getElementById('facebookQuestions').classList.add('hidden');
document.getElementById('facebookFollowers').required = false;
document.getElementById('facebookFollowers').value = '';
} else if (id === 'instagram') {
document.getElementById('instagramQuestions').classList.add('hidden');
document.getElementById('instagramFollowers').required = false;
document.getElementById('instagramFollowers').value = '';
} else if (id === 'google') {
document.getElementById('googleQuestions').classList.add('hidden');
document.getElementById('googleViews').required = false;
document.getElementById('googleViews').value = '';
} else if (id === 'email-marketing') {
document.getElementById('emailMarketingQuestions').classList.add('hidden');
document.getElementById('emailSubscribers').required = false;
document.getElementById('emailSubscribers').value = '';
} else if (id === 'sms') {
document.getElementById('smsQuestions').classList.add('hidden');
document.getElementById('smsUsers').required = false;
document.getElementById('smsUsers').value = '';
} else if (id === 'whatsapp') {
document.getElementById('whatsappQuestions').classList.add('hidden');
document.getElementById('whatsappContacts').required = false;
document.getElementById('whatsappContacts').value = '';
}
// Stop propagation to prevent dropdown from toggling
event.stopPropagation();
}
// Function to handle "None" selection
function selectNoneOption(section) {
if (section === 'onsite') {
// Clear all on-site selections
const selectedContainer = document.getElementById('onSiteSelectedOptions');
selectedContainer.innerHTML = '';
// Show all options except "None"
document.getElementById('website-option').classList.remove('hidden');
document.getElementById('app-option').classList.remove('hidden');
document.getElementById('loyalty-option').classList.remove('hidden');
// Uncheck all checkboxes
document.getElementById('website').checked = false;
document.getElementById('app').checked = false;
document.getElementById('loyalty').checked = false;
// Add "None" pill
const pill = document.createElement('div');
pill.className = 'bg-gray-200 text-gray-700 py-1 px-3 rounded-full flex items-center pill-none-onsite';
pill.innerHTML = `
<span class="mr-1">None</span>
<button type="button" onclick="removeNoneOption('onsite')" class="ml-1 focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
`;
selectedContainer.appendChild(pill);
// Hide "None" option from dropdown
document.getElementById('none-onsite-option').classList.add('hidden');
// Hide all conditional questions and set required=false
const websiteQuestions = document.getElementById('websiteQuestions');
const appQuestions = document.getElementById('appQuestions');
const loyaltyQuestions = document.getElementById('loyaltyQuestions');
const websiteVisitors = document.getElementById('websiteVisitors');
const appUsers = document.getElementById('appUsers');
const loyaltyUsers = document.getElementById('loyaltyUsers');
websiteQuestions.classList.add('hidden');
appQuestions.classList.add('hidden');
loyaltyQuestions.classList.add('hidden');
websiteVisitors.required = false;
appUsers.required = false;
loyaltyUsers.required = false;
websiteVisitors.value = '';
appUsers.value = '';
loyaltyUsers.value = '';
// Close the dropdown
document.getElementById('onSiteDropdownContent').classList.add('hidden');
} else if (section === 'offsite') {
// Clear all off-site selections
const selectedContainer = document.getElementById('offSiteSelectedOptions');
selectedContainer.innerHTML = '';
// Show all options except "None"
document.getElementById('facebook-option').classList.remove('hidden');
document.getElementById('instagram-option').classList.remove('hidden');
document.getElementById('google-option').classList.remove('hidden');
document.getElementById('email-marketing-option').classList.remove('hidden');
document.getElementById('sms-option').classList.remove('hidden');
document.getElementById('whatsapp-option').classList.remove('hidden');
// Uncheck all checkboxes
document.getElementById('facebook').checked = false;
document.getElementById('instagram').checked = false;
document.getElementById('google').checked = false;
document.getElementById('email-marketing').checked = false;
document.getElementById('sms').checked = false;
document.getElementById('whatsapp').checked = false;
// Add "None" pill
const pill = document.createElement('div');
pill.className = 'bg-gray-200 text-gray-700 py-1 px-3 rounded-full flex items-center pill-none-offsite';
pill.innerHTML = `
<span class="mr-1">None</span>
<button type="button" onclick="removeNoneOption('offsite')" class="ml-1 focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
`;
selectedContainer.appendChild(pill);
// Hide "None" option from dropdown
document.getElementById('none-offsite-option').classList.add('hidden');
// Hide all conditional questions and set required=false
const questions = [
'facebookQuestions', 'instagramQuestions', 'googleQuestions',
'emailMarketingQuestions', 'smsQuestions', 'whatsappQuestions'
];
const inputs = [
'facebookFollowers', 'instagramFollowers', 'googleViews',
'emailSubscribers', 'smsUsers', 'whatsappContacts'
];
questions.forEach((id, index) => {
const element = document.getElementById(id);
const input = document.getElementById(inputs[index]);
element.classList.add('hidden');
input.required = false;
input.value = '';
});
// Close the dropdown
document.getElementById('offSiteDropdownContent').classList.add('hidden');
}
}
// Function to remove "None" selection
function removeNoneOption(section) {
if (section === 'onsite') {
// Remove the pill
const pillToRemove = document.querySelector('.pill-none-onsite');
if (pillToRemove) {
document.getElementById('onSiteSelectedOptions').removeChild(pillToRemove);
}
// Show the "None" option in dropdown
document.getElementById('none-onsite-option').classList.remove('hidden');
// Stop propagation
event.stopPropagation();
} else if (section === 'offsite') {
// Remove the pill
const pillToRemove = document.querySelector('.pill-none-offsite');
if (pillToRemove) {
document.getElementById('offSiteSelectedOptions').removeChild(pillToRemove);
}
// Show the "None" option in dropdown
document.getElementById('none-offsite-option').classList.remove('hidden');
// Stop propagation
event.stopPropagation();
}
}
// Form submission handler
document.getElementById('retailForm').addEventListener('submit', function(e) {
e.preventDefault();
console.log('Form submitted');
// Always validate the final step (6)
if (!validateStep(6)) {
console.log('Form validation failed');
return;
}
console.log('Form validation passed');
// Disable all hidden input fields to prevent validation errors
const hiddenContainers = [
'websiteQuestions',
'appQuestions',
'loyaltyQuestions',
'facebookQuestions',
'instagramQuestions',
'googleQuestions',
'emailMarketingQuestions',
'smsQuestions',
'whatsappQuestions'
];
// Also check for store type specific sections
const storeTypes = ['convenience', 'minimarket', 'supermarket', 'hypermarket'];
storeTypes.forEach(type => {
// Make sure the checkbox element exists
const checkbox = document.getElementById(type);
if (!checkbox) {
console.log(`Checkbox ${type} not found`);
return;
}
if (!checkbox.checked) {
console.log(`Store type ${type} not checked`);
// If store type not selected, disable all its inputs
const section = document.getElementById(`${type}-section`);
if (section) {
section.querySelectorAll('input').forEach(input => {
input.disabled = true;
console.log(`Disabled input in ${type} section:`, input.name);
});
} else {
console.log(`Section ${type}-section not found`);
}
} else {
console.log(`Store type ${type} is checked`);
// If store type is selected but screen/radio questions are hidden
const screenQuestions = document.getElementById(`${type}-screen-questions`);
const radioQuestions = document.getElementById(`${type}-radio-questions`);
if (screenQuestions && screenQuestions.classList.contains('hidden')) {
screenQuestions.querySelectorAll('input').forEach(input => {
input.disabled = true;
console.log(`Disabled screen input in ${type}:`, input.name);
});
}
if (radioQuestions && radioQuestions.classList.contains('hidden')) {
radioQuestions.querySelectorAll('input').forEach(input => {
input.disabled = true;
console.log(`Disabled radio input in ${type}:`, input.name);
});
}
}
});
// Disable all inputs in hidden containers
hiddenContainers.forEach(containerId => {
const container = document.getElementById(containerId);
if (container && container.classList.contains('hidden')) {
container.querySelectorAll('input').forEach(input => {
input.disabled = true;
});
}
});
// Show loading state
submitBtn.disabled = true;
submitBtn.textContent = 'SUBMITTING...';
// Gather form data
const formData = new FormData(this);
const formObject = {};
// Convert FormData to an object
formData.forEach((value, key) => {
// Handle multi-select checkboxes (onSiteChannels, offSiteChannels)
if (formObject[key]) {
if (!Array.isArray(formObject[key])) {
formObject[key] = [formObject[key]];
}
formObject[key].push(value);
} else {
formObject[key] = value;
}
});
// Send the data to the server
console.log('Sending data to server:', formObject);
fetch('/calculate', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formObject)
})
.then(response => {
console.log('Server response:', response);
return response.json();
})
.then(data => {
console.log('Response data:', data);
if (data.success) {
// Re-enable all fields before redirecting (just in case the user navigates back)
hiddenContainers.forEach(containerId => {
const container = document.getElementById(containerId);
if (container) {
container.querySelectorAll('input').forEach(input => {
input.disabled = false;
});
}
});
// Re-enable store type fields
storeTypes.forEach(type => {
const section = document.getElementById(`${type}-section`);
if (section) {
section.querySelectorAll('input').forEach(input => {
input.disabled = false;
console.log(`Re-enabled input in ${type} section:`, input.name);
});
}
});
// Redirect to the thank you page
window.location.href = '/thank-you.html';
} else {
alert('Error: ' + data.message);
// Reset submit button
submitBtn.disabled = false;
submitBtn.textContent = 'SUBMIT';
}
})
.catch(error => {
console.error('Error submitting form:', error);
alert('An error occurred while processing your submission. Please try again.');
// Reset submit button
submitBtn.disabled = false;
submitBtn.textContent = 'SUBMIT';
console.log('Error details:', error);
// Re-enable all fields in case of error
hiddenContainers.forEach(containerId => {
const container = document.getElementById(containerId);
if (container) {
container.querySelectorAll('input').forEach(input => {
input.disabled = false;
});
}
});
// Re-enable store type fields in case of error
storeTypes.forEach(type => {
const section = document.getElementById(`${type}-section`);
if (section) {
section.querySelectorAll('input').forEach(input => {
input.disabled = false;
console.log(`Re-enabled input after error in ${type} section:`, input.name);
});
}
});
});
});
// Function to close dropdown
function closeDropdown(id) {
document.getElementById(id).classList.add('hidden');
}
// Store Type selection functions
function selectStoreTypeOption(id, text, colorClass) {
// Hide the option in the dropdown
document.getElementById(`${id}-option`).classList.add('hidden');
// Create and add pill to the input
const selectedContainer = document.getElementById('storeTypeSelectedOptions');
const pill = document.createElement('div');
pill.className = `${colorClass} py-1 px-3 rounded-full flex items-center pill-${id}`;
pill.innerHTML = `
<span class="mr-1">${text}</span>
<button type="button" onclick="removeStoreTypeOption('${id}', '${text}', '${colorClass}')" class="ml-1 focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
`;
selectedContainer.appendChild(pill);
// Set the hidden checkbox to checked
const checkbox = document.getElementById(id);
if (checkbox) {
checkbox.checked = true;
console.log(`Set checkbox ${id} to checked`);
} else {
console.error(`Checkbox ${id} not found`);
// Try to create it if it doesn't exist
ensureCheckboxExists(id, 'storeTypes', text);
const newCheckbox = document.getElementById(id);
if (newCheckbox) {
newCheckbox.checked = true;
console.log(`Created and checked checkbox ${id}`);
}
}
// Create the store type details section
createStoreTypeSection(id, text);
// Close the dropdown
document.getElementById('storeTypeDropdownContent').classList.add('hidden');
}
// Remove store type option
function removeStoreTypeOption(id, text, colorClass) {
// Remove the pill
const pillToRemove = document.querySelector(`.pill-${id}`);
if (pillToRemove) {
document.getElementById('storeTypeSelectedOptions').removeChild(pillToRemove);
}
// Show the option in the dropdown again
document.getElementById(`${id}-option`).classList.remove('hidden');
// Set the hidden checkbox to unchecked
const checkbox = document.getElementById(id);
if (checkbox) {
checkbox.checked = false;
console.log(`Set checkbox ${id} to unchecked`);
} else {
console.error(`Checkbox ${id} not found when trying to uncheck`);
}
// Remove the store type details section
removeStoreTypeSection(id);
// Stop propagation to prevent dropdown from toggling
event.stopPropagation();
}
// Create store type section with all required fields
function createStoreTypeSection(id, text) {
const sectionId = `${id}-section`;
// Check if section already exists
if (document.getElementById(sectionId)) {
return;
}
const section = document.createElement('div');
section.id = sectionId;
section.className = 'p-4 border border-gray-200 rounded-lg mt-4';
section.innerHTML = `
<h3 class="text-lg font-semibold text-gray-700 mb-3">${text} Details</h3>
<div class="space-y-4">
<!-- Number of stores -->
<div>
<label for="${id}-stores" class="block text-base font-medium text-gray-700 mb-1">Number of stores</label>
<input type="number" id="${id}-stores" name="${id}_stores" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
<!-- Monthly transactions -->
<div>
<label for="${id}-transactions" class="block text-base font-medium text-gray-700 mb-1">Monthly transactions</label>
<input type="number" id="${id}-transactions" name="${id}_transactions" required
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
<!-- Digital Screens -->
<div>
<label class="block text-base font-medium text-gray-700 mb-1">Digital screens</label>
<div class="space-y-1">
<div class="flex items-center">
<input type="radio" id="${id}-screens-yes" name="${id}_screens" value="Yes" required
class="h-4 w-4 text-orange-500 focus:ring-orange-500" onchange="toggleStoreTypeScreens('${id}', true)">
<label for="${id}-screens-yes" class="ml-2 text-sm text-gray-700">Yes</label>
</div>
<div class="flex items-center">
<input type="radio" id="${id}-screens-no" name="${id}_screens" value="No"
class="h-4 w-4 text-orange-500 focus:ring-orange-500" onchange="toggleStoreTypeScreens('${id}', false)">
<label for="${id}-screens-no" class="ml-2 text-sm text-gray-700">No</label>
</div>
</div>
</div>
<!-- Screen Questions (Hidden by default) -->
<div id="${id}-screen-questions" class="space-y-4 hidden">
<div>
<label for="${id}-screen-count" class="block text-base font-medium text-gray-700 mb-1">Number of screens per store</label>
<input type="number" id="${id}-screen-count" name="${id}_screen_count"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
<div>
<label for="${id}-screen-percentage" class="block text-base font-medium text-gray-700 mb-1">Number of stores with digital screens</label>
<input type="number" id="${id}-screen-percentage" name="${id}_screen_percentage" min="0" max="100"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
<!-- Radio -->
<div>
<label class="block text-base font-medium text-gray-700 mb-1">In-store radio</label>
<div class="space-y-1">
<div class="flex items-center">
<input type="radio" id="${id}-radio-yes" name="${id}_radio" value="Yes" required
class="h-4 w-4 text-orange-500 focus:ring-orange-500" onchange="toggleStoreTypeRadio('${id}', true)">
<label for="${id}-radio-yes" class="ml-2 text-sm text-gray-700">Yes</label>
</div>
<div class="flex items-center">
<input type="radio" id="${id}-radio-no" name="${id}_radio" value="No"
class="h-4 w-4 text-orange-500 focus:ring-orange-500" onchange="toggleStoreTypeRadio('${id}', false)">
<label for="${id}-radio-no" class="ml-2 text-sm text-gray-700">No</label>
</div>
</div>
</div>
<!-- Radio Questions (Hidden by default) -->
<div id="${id}-radio-questions" class="space-y-4 hidden">
<div>
<label for="${id}-radio-percentage" class="block text-base font-medium text-gray-700 mb-1">Number of stores with radio</label>
<input type="number" id="${id}-radio-percentage" name="${id}_radio_percentage" min="0" max="100"
class="w-full p-3 border border-gray-300 bg-white rounded-md focus:outline-none focus:ring-1 focus:ring-[#eb742e] focus:border-[#eb742e]">
</div>
</div>
</div>
`;
document.getElementById('storeTypeDetailsSections').appendChild(section);
}
// Remove store type section
function removeStoreTypeSection(id) {
const section = document.getElementById(`${id}-section`);
if (section) {
document.getElementById('storeTypeDetailsSections').removeChild(section);
}
}
// Toggle store type screen questions
function toggleStoreTypeScreens(id, show) {
const screenQuestions = document.getElementById(`${id}-screen-questions`);
const screenCount = document.getElementById(`${id}-screen-count`);
const screenPercentage = document.getElementById(`${id}-screen-percentage`);
if (show) {
screenQuestions.classList.remove('hidden');
screenCount.required = true;
screenPercentage.required = true;
} else {
screenQuestions.classList.add('hidden');
screenCount.required = false;
screenPercentage.required = false;
// Clear values when hidden
screenCount.value = '';
screenPercentage.value = '';
}
}
// Toggle store type radio questions
function toggleStoreTypeRadio(id, show) {
const radioQuestions = document.getElementById(`${id}-radio-questions`);
const radioPercentage = document.getElementById(`${id}-radio-percentage`);
if (show) {
radioQuestions.classList.remove('hidden');
radioPercentage.required = true;
} else {
radioQuestions.classList.add('hidden');
radioPercentage.required = false;
// Clear value when hidden
radioPercentage.value = '';
}
}
</script>
</body>
</html>