export function cookingClassesCalculator(form: FormTs) {
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Cooking Classes Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Cuisine Section
const cuisineSection = form.addSubform('cuisine', { title: '๐ณ Cuisine & Style' });
cuisineSection.addRow(row => {
row.addRadioButton('cuisineType', {
label: 'Cuisine Type',
options: [
{ id: 'general', name: 'General Cooking Skills' },
{ id: 'italian', name: 'Italian Cuisine' },
{ id: 'french', name: 'French Cuisine' },
{ id: 'asian', name: 'Asian Cuisine' },
{ id: 'baking', name: 'Baking & Pastry' },
{ id: 'specialty', name: 'Specialty/Fusion' }
],
defaultValue: 'general',
orientation: 'vertical'
});
});
cuisineSection.addRow(row => {
row.addDropdown('classStyle', {
label: 'Class Style',
options: [
{ id: 'hands-on', name: 'Hands-on Cooking' },
{ id: 'demonstration', name: 'Chef Demonstration' },
{ id: 'competition', name: 'Cooking Competition' },
{ id: 'team-building', name: 'Team Building Event' },
{ id: 'date-night', name: 'Date Night/Couples' }
],
defaultValue: 'hands-on'
}, '1fr');
});
// Class Format Section
const formatSection = form.addSubform('format', { title: '๐ฅ Class Format' });
formatSection.addRow(row => {
row.addRadioButton('classType', {
label: 'Class Type',
options: [
{ id: 'private', name: 'Private Lesson (1-2 people)' },
{ id: 'small-group', name: 'Small Group (3-6 people)' },
{ id: 'standard', name: 'Standard Class (7-12 people)' },
{ id: 'large', name: 'Large Class (13-20 people)' }
],
defaultValue: 'small-group',
orientation: 'horizontal'
});
});
formatSection.addRow(row => {
row.addDropdown('duration', {
label: 'Class Duration',
options: [
{ id: '90', name: '1.5 hours' },
{ id: '120', name: '2 hours' },
{ id: '180', name: '3 hours' },
{ id: '240', name: '4 hours (full course)' },
{ id: '360', name: '6 hours (intensive)' }
],
defaultValue: '120',
isRequired: true
}, '1fr');
row.addDropdown('location', {
label: 'Location',
options: [
{ id: 'studio', name: 'Cooking Studio/School' },
{ id: 'home', name: 'In-Home (chef travels)' },
{ id: 'online', name: 'Online/Virtual' },
{ id: 'outdoor', name: 'Outdoor/BBQ' }
],
defaultValue: 'studio'
}, '1fr');
});
// Student Info Section
const studentSection = form.addSubform('student', { title: '๐ค Student Information' });
studentSection.addRow(row => {
row.addDropdown('skillLevel', {
label: 'Skill Level',
options: [
{ id: 'beginner', name: 'Beginner (Little to no experience)' },
{ id: 'home-cook', name: 'Home Cook (Basic skills)' },
{ id: 'intermediate', name: 'Intermediate (Comfortable cooking)' },
{ id: 'advanced', name: 'Advanced (Complex techniques)' },
{ id: 'professional', name: 'Professional Development' }
],
defaultValue: 'home-cook',
isRequired: true
}, '1fr');
row.addDropdown('focus', {
label: 'Learning Focus',
options: [
{ id: 'technique', name: 'Cooking Techniques' },
{ id: 'recipes', name: 'Recipe Mastery' },
{ id: 'meal-prep', name: 'Meal Planning/Prep' },
{ id: 'healthy', name: 'Healthy Cooking' },
{ id: 'entertainment', name: 'Entertainment/Party' }
],
defaultValue: 'technique'
}, '1fr');
});
// Instructor Section
const instructorSection = form.addSubform('instructor', { title: '๐จโ๐ณ Chef/Instructor' });
instructorSection.addRow(row => {
row.addRadioButton('chefLevel', {
label: 'Chef Experience',
options: [
{ id: 'culinary-student', name: 'Culinary Student' },
{ id: 'junior', name: 'Junior Chef (1-5 yrs)' },
{ id: 'experienced', name: 'Experienced Chef (5-15 yrs)' },
{ id: 'executive', name: 'Executive Chef (15+ yrs)' },
{ id: 'celebrity', name: 'Celebrity/Award-Winning Chef' }
],
defaultValue: 'experienced',
orientation: 'vertical'
});
});
// Ingredients Section
const ingredientsSection = form.addSubform('ingredients', { title: '๐ฅ Ingredients & Equipment' });
ingredientsSection.addRow(row => {
row.addRadioButton('ingredientQuality', {
label: 'Ingredient Quality',
options: [
{ id: 'standard', name: 'Standard Quality' },
{ id: 'premium', name: 'Premium/Organic' },
{ id: 'luxury', name: 'Luxury/Specialty' }
],
defaultValue: 'standard',
orientation: 'horizontal'
});
});
ingredientsSection.addRow(row => {
row.addCheckbox('wineParingOption', {
label: 'Wine Pairing Included',
defaultValue: false
}, '1fr');
row.addCheckbox('takeHome', {
label: 'Take-Home Portions',
defaultValue: false
}, '1fr');
});
ingredientsSection.addRow(row => {
row.addCheckbox('apronIncluded', {
label: 'Apron Provided',
defaultValue: true
}, '1fr');
row.addCheckbox('recipeBook', {
label: 'Recipe Cards/Book',
defaultValue: true
}, '1fr');
});
// Package Section
const packageSection = form.addSubform('package', { title: '๐ฆ Package Options' });
packageSection.addRow(row => {
row.addDropdown('paymentPlan', {
label: 'Payment Plan',
options: [
{ id: 'single', name: 'Single Class' },
{ id: '4-pack', name: '4-Class Package (5% off)' },
{ id: '8-pack', name: '8-Class Package (10% off)' },
{ id: '12-pack', name: '12-Class Package (15% off)' },
{ id: 'membership', name: 'Monthly Membership (20% off)' }
],
defaultValue: 'single',
isRequired: true
}, '1fr');
});
// Add-ons Section
const addonsSection = form.addSubform('addons', { title: 'โจ Additional Services' });
addonsSection.addRow(row => {
row.addCheckbox('privateChefDinner', {
label: 'Private Chef Dinner Experience',
defaultValue: false
}, '1fr');
row.addCheckbox('marketTour', {
label: 'Market/Grocery Tour',
defaultValue: false
}, '1fr');
});
addonsSection.addRow(row => {
row.addCheckbox('videoRecording', {
label: 'Video Recording of Class',
defaultValue: false
}, '1fr');
row.addCheckbox('certificate', {
label: 'Completion Certificate',
defaultValue: false
}, '1fr');
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Pricing Section
const pricingSection = form.addSubform('pricing', { title: '๐ฐ Pricing', isCollapsible: false });
const calculatePrice = () => {
const cuisineType = cuisineSection.radioButton('cuisineType')?.value() || 'general';
const classStyle = cuisineSection.dropdown('classStyle')?.value() || 'hands-on';
const classType = formatSection.radioButton('classType')?.value() || 'small-group';
const duration = parseInt(formatSection.dropdown('duration')?.value() || '120');
const location = formatSection.dropdown('location')?.value() || 'studio';
const skillLevel = studentSection.dropdown('skillLevel')?.value() || 'home-cook';
const chefLevel = instructorSection.radioButton('chefLevel')?.value() || 'experienced';
const ingredientQuality = ingredientsSection.radioButton('ingredientQuality')?.value() || 'standard';
const paymentPlan = packageSection.dropdown('paymentPlan')?.value() || 'single';
// Base rate per person per hour
const baseRates: Record<string, number> = {
'culinary-student': 30,
'junior': 45,
'experienced': 70,
'executive': 100,
'celebrity': 175
};
let hourlyRate = baseRates[chefLevel] || 70;
// Cuisine type adjustment
const cuisineMult: Record<string, number> = {
'general': 1.0,
'italian': 1.1,
'french': 1.25,
'asian': 1.15,
'baking': 1.15,
'specialty': 1.3
};
hourlyRate *= cuisineMult[cuisineType] || 1.0;
// Class style adjustment
const styleMult: Record<string, number> = {
'hands-on': 1.0,
'demonstration': 0.7,
'competition': 1.3,
'team-building': 1.4,
'date-night': 1.2
};
hourlyRate *= styleMult[classStyle] || 1.0;
// Duration calculation
const hours = duration / 60;
let classPrice = hourlyRate * hours;
// Class type adjustment (per person)
const classMult: Record<string, number> = {
'private': 2.5,
'small-group': 1.0,
'standard': 0.75,
'large': 0.6
};
classPrice *= classMult[classType] || 1.0;
// Location adjustment
const locationMult: Record<string, number> = {
'studio': 1.0,
'home': 1.4,
'online': 0.6,
'outdoor': 1.2
};
classPrice *= locationMult[location] || 1.0;
// Skill level adjustment
const levelMult: Record<string, number> = {
'beginner': 1.0,
'home-cook': 1.0,
'intermediate': 1.1,
'advanced': 1.2,
'professional': 1.35
};
classPrice *= levelMult[skillLevel] || 1.0;
// Ingredient quality adjustment
let ingredientCost = 0;
const ingredientMult: Record<string, number> = {
'standard': 15,
'premium': 30,
'luxury': 55
};
ingredientCost = ingredientMult[ingredientQuality] || 15;
// Add-ons for ingredients section
if (ingredientsSection.checkbox('wineParingOption')?.value()) ingredientCost += 25;
if (ingredientsSection.checkbox('takeHome')?.value()) ingredientCost += 15;
if (ingredientsSection.checkbox('apronIncluded')?.value()) ingredientCost += 5;
if (ingredientsSection.checkbox('recipeBook')?.value()) ingredientCost += 5;
// Package calculations
const packageDiscount: Record<string, number> = {
'single': 0,
'4-pack': 0.05,
'8-pack': 0.10,
'12-pack': 0.15,
'membership': 0.20
};
const discount = packageDiscount[paymentPlan] || 0;
const packageClasses: Record<string, number> = {
'single': 1,
'4-pack': 4,
'8-pack': 8,
'12-pack': 12,
'membership': 4
};
const numClasses = packageClasses[paymentPlan] || 1;
// Add-ons
let addonsPrice = 0;
if (addonsSection.checkbox('privateChefDinner')?.value()) addonsPrice += 200;
if (addonsSection.checkbox('marketTour')?.value()) addonsPrice += 75;
if (addonsSection.checkbox('videoRecording')?.value()) addonsPrice += 35;
if (addonsSection.checkbox('certificate')?.value()) addonsPrice += 20;
const classWithIngredients = classPrice + ingredientCost;
const packageTotal = (classWithIngredients * numClasses * (1 - discount)) + addonsPrice;
const effectivePerClass = (packageTotal - addonsPrice) / numClasses;
return {
classPrice: Math.round(classPrice),
ingredientCost: Math.round(ingredientCost),
classWithIngredients: Math.round(classWithIngredients),
discount: Math.round(discount * 100),
packageTotal: Math.round(packageTotal),
numClasses,
effectivePerClass: Math.round(effectivePerClass),
addonsPrice: Math.round(addonsPrice),
duration
};
};
pricingSection.addRow(row => {
row.addPriceDisplay('perClass', {
label: 'Per Class',
computedValue: () => calculatePrice().classPrice,
variant: 'default'
}, '1fr');
row.addPriceDisplay('ingredients', {
label: 'Ingredients',
computedValue: () => calculatePrice().ingredientCost,
variant: 'default'
}, '1fr');
});
pricingSection.addRow(row => {
row.addTextPanel('discount', {
computedValue: () => {
const price = calculatePrice();
if (price.discount > 0) {
return `Package Discount: ${price.discount}% off`;
}
return 'No package discount (single class)';
},
customStyles: { 'font-size': '0.95rem', 'color': '#16a34a', 'font-weight': '500' },
isVisible: () => calculatePrice().discount > 0
});
});
// Summary Section
const summarySection = form.addSubform('summary', {
title: '๐งพ Summary',
isCollapsible: false,
sticky: 'bottom'
});
summarySection.addRow(row => {
row.addPriceDisplay('total', {
label: 'Total',
computedValue: () => calculatePrice().packageTotal,
variant: 'large'
}, '1fr');
row.addTextPanel('perClassFinal', {
computedValue: () => {
const price = calculatePrice();
return `$${price.effectivePerClass}/class`;
},
customStyles: { 'font-size': '1rem', 'color': '#64748b', 'text-align': 'center', 'align-self': 'center' }
}, '1fr');
});
summarySection.addRow(row => {
row.addTextPanel('packageInfo', {
computedValue: () => {
const price = calculatePrice();
return `${price.numClasses} class${price.numClasses > 1 ? 'es' : ''} ร ${price.duration} minutes`;
},
customStyles: { 'font-size': '0.9rem', 'color': '#475569', 'text-align': 'center' }
});
});
summarySection.addRow(row => {
row.addTextPanel('note', {
computedValue: () => 'Price per person. Dietary restrictions accommodated. Please inform us of any allergies in advance.',
customStyles: { 'font-size': '0.85rem', 'color': '#64748b', 'text-align': 'center' }
});
});
form.configureSubmitButton({
label: 'Book Cooking Class'
});
}