Email: dine@skimprivatedining.com
MealPrepConsultationsfirstName (Text)
lastName (Text)
email (Text)
phone (Text)
streetAddress (Text)
city (Text)
state (Text)
zipCode (Text)
unit (Text)
householdSize (Number)
location (Text)
mealPlan (Text)
serviceDay (Text)
preparationMethod (Text)
containerPreference (Text)
favoriteRestaurants (Long Text)
favoriteDishes (Long Text)
avoidFoods (Long Text)
dietaryPreferences (Tags)
additionalInfo (Long Text)
enhancements (Tags)
consultationDate (Date)
consultationTime (Text)
communicationMethod (Text)
weeklyMeals (Text)consultationHandler.jsw// backend/consultationHandler.jsw
import wixData from 'wix-data';
import { sendEmail } from 'wix-email-backend';
// MAIN FUNCTION - Processes the entire consultation form
export async function processConsultation(formData) {
try {
// Save to database
const consultation = await wixData.insert('MealPrepConsultations', {
...formData,
createdDate: new Date(),
status: 'pending'
});
// Send emails
const emailsSent = await sendConsultationEmails(formData);
return {
success: true,
consultationId: consultation._id,
emailsSent: emailsSent
};
} catch (error) {
console.error('Consultation processing error:', error);
return {
success: false,
error: error.message
};
}
}
// SEND EMAILS TO BOTH CUSTOMER AND CHEF
async function sendConsultationEmails(formData) {
const chefEmail = 'dine@skimprivatedining.com';
// Format the date and time nicely
const consultDate = new Date(formData.consultationDate);
const formattedDate = consultDate.toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
// Generate calendar files
const icsContent = generateCalendarInvite(formData, consultDate);
try {
// EMAIL TO CUSTOMER
const customerSubject = `Confirmed: Your S.KIM Meal Prep Consultation - ${formattedDate}`;
const customerBody = `
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: 'Helvetica Neue', Arial, sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 0; }
.email-container { max-width: 600px; margin: 0 auto; }
.header { background: linear-gradient(135deg, #627a6a 0%, #4f6357 100%); color: white; padding: 40px 30px; text-align: center; }
.header h1 { margin: 0; font-size: 28px; font-weight: 300; letter-spacing: 1px; }
.content { padding: 40px 30px; background: #ffffff; }
.greeting { font-size: 20px; color: #627a6a; margin-bottom: 20px; }
.details-box { background: #f8f9fa; border-left: 4px solid #627a6a; padding: 25px; margin: 30px 0; }
.details-box h3 { margin-top: 0; color: #627a6a; }
.detail-item { margin: 12px 0; }
.detail-label { font-weight: 600; color: #555; }
.button { display: inline-block; padding: 14px 30px; background: #627a6a; color: white; text-decoration: none; margin: 20px 0; }
.next-steps { background: #f0f8f0; padding: 25px; margin: 30px 0; border-radius: 5px; }
.footer { text-align: center; padding: 30px; color: #888; font-size: 14px; background: #f8f9fa; }
</style>
</head>
<body>
<div class="email-container">
<div class="header">
<h1>Your Consultation is Confirmed!</h1>
</div>
<div class="content">
<div class="greeting">Hi ${formData.firstName},</div>
<p>Thank you for choosing S.KIM Meal Prep! I'm looking forward to our conversation about creating your perfect weekly meal plan.</p>
<div class="details-box">
<h3>📅 Your Consultation Details</h3>
<div class="detail-item">
<span class="detail-label">Date:</span> ${formattedDate}
</div>
<div class="detail-item">
<span class="detail-label">Time:</span> ${formData.consultationTime} PT
</div>
<div class="detail-item">
<span class="detail-label">Duration:</span> 15-20 minutes
</div>
<div class="detail-item">
<span class="detail-label">Method:</span> ${formData.communicationMethod === 'zoom' ? '💻 Zoom Video Call' : '📞 Phone Call'}
</div>
${formData.communicationMethod === 'phone' ? `
<div class="detail-item">
<span class="detail-label">Phone:</span> I'll call you at ${formData.phone}
</div>
` : ''}
</div>
<div class="next-steps">
<h3>What Happens Next?</h3>
<ol>
<li><strong>Our Call:</strong> We'll discuss your preferences, dietary needs, and weekly schedule</li>
<li><strong>Custom Proposal:</strong> Within 2 hours after our call, you'll receive a detailed proposal</li>
<li><strong>Your First Week:</strong> Once approved, we'll schedule your first week of meal prep!</li>
</ol>
</div>
<p><strong>Your Selections:</strong></p>
<ul>
<li>Household size: ${formData.householdSize} ${formData.householdSize === 1 ? 'person' : 'people'}</li>
<li>Meal plan: ${formData.weeklyMeals}</li>
<li>Preferred service day: ${formData.serviceDay}</li>
</ul>
<p style="margin-top: 30px;">If you need to reschedule, please reply to this email at least 2 hours before our scheduled time.</p>
<p>Looking forward to creating delicious, healthy meals for you!</p>
<p>Best,<br>
<strong>Chef S.KIM</strong></p>
</div>
<div class="footer">
S.KIM Private Dining & Meal Prep<br>
dine@skimprivatedining.com<br>
© ${new Date().getFullYear()} All rights reserved
</div>
</div>
</body>
</html>
`;
// EMAIL TO CHEF
const chefSubject = `NEW Consultation: ${formData.firstName} ${formData.lastName} - ${formattedDate} at ${formData.consultationTime}`;
const chefBody = `
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; line-height: 1.5; color: #333; }
.container { max-width: 700px; margin: 0 auto; padding: 20px; }
.header { background: #2c3e50; color: white; padding: 20px; margin: -20px -20px 20px; }
.section { background: #f5f5f5; padding: 20px; margin: 20px 0; border-left: 4px solid #3498db; }
.label { font-weight: bold; color: #2c3e50; display: inline-block; width: 150px; }
.value { color: #555; }
.highlight { background: #fffacd; padding: 15px; margin: 20px 0; border: 1px solid #f0e68c; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
td { padding: 8px; border-bottom: 1px solid #ddd; }
.important { color: #e74c3c; font-weight: bold; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h2 style="margin: 0;">New Meal Prep Consultation Scheduled</h2>
</div>
<div class="highlight">
<h3 style="margin-top: 0;">📞 Consultation Details</h3>
<table>
<tr><td class="label">Date:</td><td class="important">${formattedDate}</td></tr>
<tr><td class="label">Time:</td><td class="important">${formData.consultationTime} PT</td></tr>
<tr><td class="label">Method:</td><td>${formData.communicationMethod === 'zoom' ? 'Zoom Call' : 'Phone Call'}</td></tr>
<tr><td class="label">Phone:</td><td>${formData.phone}</td></tr>
</table>
</div>
<div class="section">
<h3>👤 Client Information</h3>
<table>
<tr><td class="label">Name:</td><td>${formData.firstName} ${formData.lastName}</td></tr>
<tr><td class="label">Email:</td><td><a href="mailto:${formData.email}">${formData.email}</a></td></tr>
<tr><td class="label">Phone:</td><td>${formData.phone}</td></tr>
<tr><td class="label">Address:</td><td>${formData.streetAddress} ${formData.unit || ''}<br>${formData.city}, ${formData.state} ${formData.zipCode}</td></tr>
</table>
</div>
<div class="section">
<h3>🍽️ Service Preferences</h3>
<table>
<tr><td class="label">Household Size:</td><td><strong>${formData.householdSize} ${formData.householdSize === 1 ? 'person' : 'people'}</strong></td></tr>
<tr><td class="label">Location:</td><td>${formData.location}</td></tr>
<tr><td class="label">Meal Plan:</td><td><strong>${formData.weeklyMeals}</strong></td></tr>
<tr><td class="label">Service Day:</td><td>${formData.serviceDay}</td></tr>
<tr><td class="label">Preparation:</td><td>${formData.preparationMethod}</td></tr>
<tr><td class="label">Containers:</td><td>${formData.containerPreference}</td></tr>
</table>
</div>
<div class="section">
<h3>🥗 Dietary Information</h3>
<table>
<tr><td class="label">Dietary Needs:</td><td>${formData.dietaryPreferences.length > 0 ? formData.dietaryPreferences.join(', ') : 'None specified'}</td></tr>
<tr><td class="label">Favorite Restaurants:</td><td>${formData.favoriteRestaurants || 'Not specified'}</td></tr>
<tr><td class="label">Favorite Dishes:</td><td>${formData.favoriteDishes || 'Not specified'}</td></tr>
<tr><td class="label">Avoid:</td><td class="important">${formData.avoidFoods || 'Nothing specified'}</td></tr>
<tr><td class="label">Additional Info:</td><td>${formData.additionalInfo || 'None'}</td></tr>
</table>
</div>
${formData.enhancements.length > 0 ? `
<div class="section">
<h3>✨ Enhancement Interests</h3>
<ul>
${formData.enhancements.map(e => `<li>${e}</li>`).join('')}
</ul>
</div>
` : ''}
<div style="background: #e8f5e9; padding: 20px; margin: 20px 0; text-align: center;">
<p style="margin: 0;"><strong>Calendar invite attached</strong> - Add to your calendar now!</p>
</div>
</div>
</body>
</html>
`;
// Send both emails
await sendEmail('dine@skimprivatedining.com', {
subject: customerSubject,
body: customerBody,
attachments: [{
fileName: 'consultation.ics',
content: Buffer.from(icsContent).toString('base64')
}]
});
await sendEmail(chefEmail, {
subject: chefSubject,
body: chefBody,
attachments: [{
fileName: 'consultation.ics',
content: Buffer.from(icsContent).toString('base64')
}]
});
return true;
} catch (error) {
console.error('Email sending error:', error);
return false;
}
}
// GENERATE CALENDAR INVITE FILE
function generateCalendarInvite(formData, consultDate) {
// Parse time
const [time, period] = formData.consultationTime.split(' ');
const [hours, minutes] = time.split(':');
let hour = parseInt(hours);
if (period === 'PM' && hour !== 12) hour += 12;
if (period === 'AM' && hour === 12) hour = 0;
// Set start time
const startDate = new Date(consultDate);
startDate.setHours(hour, parseInt(minutes), 0, 0);
// Set end time (20 minutes later)
const endDate = new Date(startDate);
endDate.setMinutes(endDate.getMinutes() + 20);
// Format dates for ICS
const formatDate = (date) => {
return date.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
};
const method = formData.communicationMethod === 'zoom' ? 'Zoom Call' : `Phone Call at ${formData.phone}`;
return `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//S.KIM Meal Prep//EN
METHOD:REQUEST
BEGIN:VEVENT
UID:${Date.now()}@skimprivatedining.com
DTSTAMP:${formatDate(new Date())}
DTSTART:${formatDate(startDate)}
DTEND:${formatDate(endDate)}
SUMMARY:S.KIM Meal Prep Consultation - ${formData.firstName} ${formData.lastName}
DESCRIPTION:Meal prep consultation to discuss preferences and create custom proposal.\\n\\nClient: ${formData.firstName} ${formData.lastName}\\nPhone: ${formData.phone}\\nEmail: ${formData.email}\\nHousehold: ${formData.householdSize} people\\nMeal Plan: ${formData.weeklyMeals}
LOCATION:${method}
ORGANIZER;CN=S.KIM Meal Prep:mailto:dine@skimprivatedining.com
ATTENDEE;CN=${formData.firstName} ${formData.lastName};RSVP=TRUE:mailto:${formData.email}
STATUS:CONFIRMED
END:VEVENT
END:VCALENDAR`;
}consultationModalIMPORTANT: Add these elements in ORDER and give them the EXACT IDs listed:
closeButton) - Top right X buttonprogressBar) - Strip element
progress1, progress2, progress3, progress4, progress5)step1Container) - Visiblestep2Container) - Hiddenstep3Container) - Hiddenstep4Container) - Hiddenstep5Container) - HiddenStep 1 Elements:
householdRepeater) - For 1-6+ people selectionlocationRepeater) - For Primary/Vacation selectionmealPlanRepeater) - For meal plan optionsportionPreview) - Hidden by defaultStep 2 Elements:
serviceDayRepeater) - For day selectionprepMethodRepeater) - For preparation methodcontainerRepeater) - For container preferenceStep 3 Elements:
favoriteRestaurants) - Text inputfavoriteDishes) - Text inputavoidFoods) - Text inputdietaryCheckboxes) with options:
additionalInfo) - Multi-lineStep 4 Elements:
enhancementCheckboxes) with options:
Step 5 Elements:
firstName) - RequiredlastName) - RequiredemailInput) - Required, Email typephoneInput) - Required, Phone typestreetAddress) - RequiredcityInput) - RequiredstateDropdown) - Default: CAzipCode) - RequiredunitInput) - OptionalconsultationDate) - RequiredtimeSlotRepeater) - Time slotscommunicationButtons) - Phone/Zoom selectionbackButton) - Initially hiddennextButton) - Text: "Continue"// Lightbox Code - consultationModal
import wixWindow from 'wix-window';
import { processConsultation } from 'backend/consultationHandler';
// Form data storage
let currentStep = 1;
const totalSteps = 5;
let formData = {
householdSize: 0,
location: '',
mealPlan: '',
serviceDay: '',
preparationMethod: '',
containerPreference: '',
favoriteRestaurants: '',
favoriteDishes: '',
avoidFoods: '',
dietaryPreferences: [],
additionalInfo: '',
enhancements: [],
firstName: '',
lastName: '',
email: '',
phone: '',
streetAddress: '',
city: '',
state: 'CA',
zipCode: '',
unit: '',
consultationDate: null,
consultationTime: '',
communicationMethod: '',
weeklyMeals: ''
};
$w.onReady(function () {
setupModal();
setupEventHandlers();
updateUI();
});
function setupModal() {
// Configure date picker
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
$w('#consultationDate').minDate = tomorrow;
const maxDate = new Date();
maxDate.setDate(maxDate.getDate() + 14);
$w('#consultationDate').maxDate = maxDate;
// Setup repeater data
setupRepeaters();
}
function setupRepeaters() {
// Household size options
$w('#householdRepeater').data = [
{ _id: '1', label: '1', sublabel: 'Person', value: 1 },
{ _id: '2', label: '2', sublabel: 'People', value: 2 },
{ _id: '3', label: '3', sublabel: 'People', value: 3 },
{ _id: '4', label: '4', sublabel: 'People', value: 4 },
{ _id: '5', label: '5', sublabel: 'People', value: 5 },
{ _id: '6', label: '6+', sublabel: 'People', value: 6 }
];
// Location options
$w('#locationRepeater').data = [
{ _id: '1', label: 'Primary Residence', value: 'primary' },
{ _id: '2', label: 'Beachfront Vacation Rental', value: 'vacation' }
];
// Meal plan options
$w('#mealPlanRepeater').data = [
{ _id: '1', label: 'Dinner Only', sublabel: '4 different dinners each week', value: 'dinner' },
{ _id: '2', label: 'Lunch & Dinner', sublabel: '4 lunches + 4 dinners each week', value: 'both' },
{ _id: '3', label: 'Lunch Only', sublabel: '4 different lunches each week', value: 'lunch' },
{ _id: '4', label: 'Custom Plan', sublabel: "Let's discuss your needs", value: 'custom' }
];
// Service day options
$w('#serviceDayRepeater').data = [
{ _id: '1', label: 'Sunday', sublabel: 'Start the week prepared', value: 'Sunday' },
{ _id: '2', label: 'Monday', sublabel: 'Fresh week beginning', value: 'Monday' },
{ _id: '3', label: 'Tuesday', sublabel: 'Midweek delivery', value: 'Tuesday' },
{ _id: '4', label: 'Flexible', sublabel: "We'll coordinate weekly", value: 'Flexible' }
];
// Preparation method options
$w('#prepMethodRepeater').data = [
{ _id: '1', label: 'Cook in Your Kitchen', sublabel: 'I prepare everything fresh in your home', value: 'in-home' },
{ _id: '2', label: 'Ready-to-Heat Delivery', sublabel: 'Meals delivered fully prepared', value: 'delivery' },
{ _id: '3', label: "Let's Discuss", sublabel: 'Flexible based on your needs', value: 'flexible' }
];
// Container options
$w('#containerRepeater').data = [
{ _id: '1', label: 'Use Your Containers', sublabel: 'Eco-friendly option', value: 'client-containers' },
{ _id: '2', label: 'I Provide Containers', sublabel: 'BPA-free, reusable containers', value: 'chef-containers' }
];
// Time slots
const timeSlots = [];
const times = ['7:00 AM', '8:00 AM', '9:00 AM', '10:00 AM', '11:00 AM', '12:00 PM',
'1:00 PM', '2:00 PM', '3:00 PM', '4:00 PM', '5:00 PM', '6:00 PM'];
times.forEach((time, index) => {
timeSlots.push({ _id: `time${index}`, label: time, value: time });
});
$w('#timeSlotRepeater').data = timeSlots;
}
function setupEventHandlers() {
// Navigation
$w('#nextButton').onClick(() => handleNext());
$w('#backButton').onClick(() => handleBack());
$w('#closeButton').onClick(() => wixWindow.lightbox.close());
// Step 1 - Household size
$w('#householdRepeater').onItemReady(($item, itemData) => {
$item('#optionBox').onClick(() => {
formData.householdSize = itemData.value;
selectRepeaterItem('#householdRepeater', itemData._id);
updatePortionPreview();
});
});
// Step 1 - Location
$w('#locationRepeater').onItemReady(($item, itemData) => {
$item('#optionBox').onClick(() => {
formData.location = itemData.value;
selectRepeaterItem('#locationRepeater', itemData._id);
});
});
// Step 1 - Meal plan
$w('#mealPlanRepeater').onItemReady(($item, itemData) => {
$item('#optionBox').onClick(() => {
formData.mealPlan = itemData.value;
selectRepeaterItem('#mealPlanRepeater', itemData._id);
updatePortionPreview();
});
});
// Step 2 - Service day
$w('#serviceDayRepeater').onItemReady(($item, itemData) => {
$item('#optionBox').onClick(() => {
formData.serviceDay = itemData.value;
selectRepeaterItem('#serviceDayRepeater', itemData._id);
});
});
// Step 2 - Prep method
$w('#prepMethodRepeater').onItemReady(($item, itemData) => {
$item('#optionBox').onClick(() => {
formData.preparationMethod = itemData.value;
selectRepeaterItem('#prepMethodRepeater', itemData._id);
});
});
// Step 2 - Containers
$w('#containerRepeater').onItemReady(($item, itemData) => {
$item('#optionBox').onClick(() => {
formData.containerPreference = itemData.value;
selectRepeaterItem('#containerRepeater', itemData._id);
});
});
// Step 5 - Time slots
$w('#timeSlotRepeater').onItemReady(($item, itemData) => {
$item('#timeBox').onClick(() => {
formData.consultationTime = itemData.value;
selectRepeaterItem('#timeSlotRepeater', itemData._id);
});
});
// Communication method
if ($w('#phoneButton')) {
$w('#phoneButton').onClick(() => {
formData.communicationMethod = 'phone';
$w('#phoneButton').style.backgroundColor = '#627a6a';
$w('#zoomButton').style.backgroundColor = '#ffffff';
});
}
if ($w('#zoomButton')) {
$w('#zoomButton').onClick(() => {
formData.communicationMethod = 'zoom';
$w('#zoomButton').style.backgroundColor = '#627a6a';
$w('#phoneButton').style.backgroundColor = '#ffffff';
});
}
}
function selectRepeaterItem(repeaterId, selectedId) {
const repeater = $w(repeaterId);
repeater.forEachItem(($item, itemData) => {
if (itemData._id === selectedId) {
$item('#optionBox').style.backgroundColor = '#f5f9f5';
$item('#optionBox').style.borderColor = '#627a6a';
} else {
$item('#optionBox').style.backgroundColor = '#ffffff';
$item('#optionBox').style.borderColor = '#e8e8e8';
}
});
}
function updatePortionPreview() {
if (formData.householdSize > 0 && formData.mealPlan) {
let weeklyMeals = '';
const size = formData.householdSize;
switch(formData.mealPlan) {
case 'dinner':
weeklyMeals = `${size * 4} dinner portions weekly (4 dinners × ${size} ${size === 1 ? 'person' : 'people'})`;
break;
case 'both':
weeklyMeals = `${size * 8} total portions weekly (4 lunches + 4 dinners × ${size} ${size === 1 ? 'person' : 'people'})`;
break;
case 'lunch':
weeklyMeals = `${size * 4} lunch portions weekly (4 lunches × ${size} ${size === 1 ? 'person' : 'people'})`;
break;
case 'custom':
weeklyMeals = 'Custom meal plan - details to be discussed';
break;
}
formData.weeklyMeals = weeklyMeals;
$w('#portionPreview').text = `Your selection: ${weeklyMeals}`;
$w('#portionPreview').show();
}
}
async function handleNext() {
if (currentStep < totalSteps) {
if (validateCurrentStep()) {
currentStep++;
updateUI();
}
} else {
await submitForm();
}
}
function handleBack() {
if (currentStep > 1) {
currentStep--;
updateUI();
}
}
function validateCurrentStep() {
switch(currentStep) {
case 1:
if (!formData.householdSize || !formData.location || !formData.mealPlan) {
showError('Please make all selections before continuing');
return false;
}
break;
case 2:
if (!formData.serviceDay || !formData.preparationMethod || !formData.containerPreference) {
showError('Please make all selections before continuing');
return false;
}
break;
case 5:
// Collect form data before validation
collectStep5Data();
if (!formData.firstName || !formData.lastName || !formData.email ||
!formData.phone || !formData.streetAddress || !formData.city ||
!formData.zipCode || !formData.consultationDate ||
!formData.consultationTime || !formData.communicationMethod) {
showError('Please fill in all required fields');
return false;
}
break;
}
return true;
}
function collectStep3Data() {
formData.favoriteRestaurants = $w('#favoriteRestaurants').value || '';
formData.favoriteDishes = $w('#favoriteDishes').value || '';
formData.avoidFoods = $w('#avoidFoods').value || '';
formData.additionalInfo = $w('#additionalInfo').value || '';
formData.dietaryPreferences = $w('#dietaryCheckboxes').value || [];
}
function collectStep4Data() {
formData.enhancements = $w('#enhancementCheckboxes').value || [];
}
function collectStep5Data() {
formData.firstName = $w('#firstName').value;
formData.lastName = $w('#lastName').value;
formData.email = $w('#emailInput').value;
formData.phone = $w('#phoneInput').value;
formData.streetAddress = $w('#streetAddress').value;
formData.city = $w('#cityInput').value;
formData.state = $w('#stateDropdown').value || 'CA';
formData.zipCode = $w('#zipCode').value;
formData.unit = $w('#unitInput').value || '';
formData.consultationDate = $w('#consultationDate').value;
}
async function submitForm() {
try {
// Disable submit button
$w('#nextButton').disable();
$w('#nextButton').label = 'Scheduling...';
// Collect all remaining data
collectStep3Data();
collectStep4Data();
collectStep5Data();
// Validate final data
if (!validateCurrentStep()) {
$w('#nextButton').enable();
$w('#nextButton').label = 'Schedule Consultation';
return;
}
// Process consultation
const result = await processConsultation(formData);
if (result.success) {
// Show success message
$w('#successMessage').show();
$w('#step5Container').hide();
$w('#nextButton').hide();
$w('#backButton').hide();
// Close after 3 seconds
setTimeout(() => {
wixWindow.lightbox.close();
}, 3000);
} else {
showError('There was an error scheduling your consultation. Please try again.');
$w('#nextButton').enable();
$w('#nextButton').label = 'Schedule Consultation';
}
} catch (error) {
console.error('Submission error:', error);
showError('There was an error. Please try again or contact us directly.');
$w('#nextButton').enable();
$w('#nextButton').label = 'Schedule Consultation';
}
}
function updateUI() {
// Hide all steps
for (let i = 1; i <= totalSteps; i++) {
$w(`#step${i}Container`).hide();
}
// Show current step
$w(`#step${currentStep}Container`).show();
// Update progress bar
for (let i = 1; i <= totalSteps; i++) {
const progressElement = $w(`#progress${i}`);
if (i <= currentStep) {
progressElement.style.backgroundColor = '#627a6a';
} else {
progressElement.style.backgroundColor = '#e8e8e8';
}
}
// Update buttons
if (currentStep === 1) {
$w('#backButton').hide();
} else {
$w('#backButton').show();
}
if (currentStep === totalSteps) {
$w('#nextButton').label = 'Schedule Consultation';
} else {
$w('#nextButton').label = 'Continue';
}
// Clear any error messages
if ($w('#errorMessage')) {
$w('#errorMessage').hide();
}
}
function showError(message) {
if ($w('#errorMessage')) {
$w('#errorMessage').text = message;
$w('#errorMessage').show();
} else {
// If no error element, use console
console.error(message);
}
}successMessage)On your main page, add this code to open the modal:
// Page code where your button is
import wixWindow from 'wix-window';
$w.onReady(function () {
$w('#consultButton').onClick(() => {
wixWindow.openLightbox('consultationModal');
});
});