export function golfLessonsCalculator(form: FormTs) {
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Golf Lessons Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Lesson Type Section
const lessonSection = form.addSubform('lesson', { title: 'โณ Lesson Type' });
lessonSection.addRow(row => {
row.addRadioButton('lessonType', {
label: 'Type of Lesson',
options: [
{ id: 'private', name: 'Private (1-on-1)' },
{ id: 'semi-private', name: 'Semi-Private (2-3 golfers)' },
{ id: 'group', name: 'Group Clinic (4-8 golfers)' },
{ id: 'playing', name: 'Playing Lesson (On-Course)' },
{ id: 'camp', name: 'Golf Camp/School' },
{ id: 'fitting', name: 'Club Fitting Session' }
],
defaultValue: 'private',
orientation: 'vertical',
isRequired: true
});
});
lessonSection.addRow(row => {
row.addDropdown('skillLevel', {
label: 'Current Skill Level',
options: [
{ id: 'never', name: 'Never Played' },
{ id: 'beginner', name: 'Beginner (100+ strokes)' },
{ id: 'high-handicap', name: 'High Handicap (20-30)' },
{ id: 'mid-handicap', name: 'Mid Handicap (10-20)' },
{ id: 'low-handicap', name: 'Low Handicap (0-10)' },
{ id: 'scratch', name: 'Scratch/Plus Handicap' }
],
defaultValue: 'beginner',
isRequired: true
}, '1fr');
row.addDropdown('ageGroup', {
label: 'Age Group',
options: [
{ id: 'junior', name: 'Junior (7-12)' },
{ id: 'teen', name: 'Teen (13-17)' },
{ id: 'adult', name: 'Adult (18-54)' },
{ id: 'senior', name: 'Senior (55+)' }
],
defaultValue: 'adult'
}, '1fr');
});
// Session Details Section
const sessionSection = form.addSubform('session', { title: 'โฑ๏ธ Session Details' });
sessionSection.addRow(row => {
row.addDropdown('duration', {
label: 'Lesson Duration',
options: [
{ id: '30', name: '30 Minutes' },
{ id: '45', name: '45 Minutes' },
{ id: '60', name: '1 Hour' },
{ id: '90', name: '1.5 Hours' },
{ id: '120', name: '2 Hours' },
{ id: '180', name: '3 Hours (Half Round)' },
{ id: '240', name: '4 Hours (Full Round)' }
],
defaultValue: '60',
isRequired: true
}, '1fr');
row.addDropdown('instructorLevel', {
label: 'Instructor Level',
options: [
{ id: 'apprentice', name: 'Apprentice Instructor' },
{ id: 'pga', name: 'PGA Professional' },
{ id: 'senior', name: 'Senior PGA Pro' },
{ id: 'master', name: 'Master Professional' },
{ id: 'tour', name: 'Tour Professional/Coach' }
],
defaultValue: 'pga'
}, '1fr');
});
sessionSection.addRow(row => {
row.addDropdown('facility', {
label: 'Facility Type',
options: [
{ id: 'driving-range', name: 'Driving Range' },
{ id: 'public-course', name: 'Public Course' },
{ id: 'private-club', name: 'Private Club' },
{ id: 'indoor', name: 'Indoor Facility/Simulator' },
{ id: 'resort', name: 'Resort/Golf Academy' }
],
defaultValue: 'driving-range'
}, '1fr');
row.addInteger('golfers', {
label: 'Number of Golfers',
min: 2,
max: 8,
defaultValue: 2,
isVisible: () => ['semi-private', 'group'].includes(lessonSection.radioButton('lessonType')?.value() || '')
}, '1fr');
});
// Focus Areas Section
const focusSection = form.addSubform('focus', { title: '๐ฏ Focus Areas' });
focusSection.addRow(row => {
row.addDropdown('primaryFocus', {
label: 'Primary Focus',
options: [
{ id: 'full-game', name: 'Full Game Assessment' },
{ id: 'driver', name: 'Driver/Long Game' },
{ id: 'irons', name: 'Iron Play' },
{ id: 'short-game', name: 'Short Game (100 yards in)' },
{ id: 'putting', name: 'Putting' },
{ id: 'course-management', name: 'Course Management' },
{ id: 'bunker', name: 'Bunker Play' },
{ id: 'specialty', name: 'Specialty Shots' }
],
defaultValue: 'full-game'
}, '1fr');
});
// Camp Options (conditional)
const campSection = form.addSubform('camp', {
title: '๐๏ธ Golf School Details',
isVisible: () => lessonSection.radioButton('lessonType')?.value() === 'camp'
});
campSection.addRow(row => {
row.addDropdown('campType', {
label: 'Program Type',
options: [
{ id: 'half-day', name: 'Half Day (3-4 hours)' },
{ id: 'full-day', name: 'Full Day (6-8 hours)' },
{ id: 'weekend', name: 'Weekend Intensive' },
{ id: 'week', name: 'Week-Long School' },
{ id: 'junior-camp', name: 'Junior Camp' }
],
defaultValue: 'full-day'
}, '1fr');
row.addInteger('campDays', {
label: 'Number of Days',
min: 1,
max: 7,
defaultValue: 3
}, '1fr');
});
// Package Section
const packageSection = form.addSubform('package', { title: '๐ฆ Packages' });
packageSection.addRow(row => {
row.addDropdown('package', {
label: 'Lesson Package',
options: [
{ id: 'single', name: 'Single Lesson' },
{ id: '3-pack', name: '3 Lessons (5% off)' },
{ id: '5-pack', name: '5 Lessons (10% off)' },
{ id: '10-pack', name: '10 Lessons (15% off)' },
{ id: 'monthly', name: 'Monthly Program' }
],
defaultValue: 'single'
}, '1fr');
});
// Add-ons Section
const addonsSection = form.addSubform('addons', { title: 'โจ Add-ons & Technology' });
addonsSection.addRow(row => {
row.addCheckbox('videoAnalysis', {
label: 'Video Analysis (+$30)',
defaultValue: false
}, '1fr');
row.addCheckbox('trackman', {
label: 'TrackMan/Launch Monitor (+$50)',
defaultValue: false
}, '1fr');
});
addonsSection.addRow(row => {
row.addCheckbox('clubRental', {
label: 'Club Rental (+$25)',
defaultValue: false
}, '1fr');
row.addCheckbox('rangeBalls', {
label: 'Range Balls Included (+$15)',
defaultValue: false
}, '1fr');
});
addonsSection.addRow(row => {
row.addCheckbox('golfCart', {
label: 'Golf Cart (+$30)',
defaultValue: false,
isVisible: () => lessonSection.radioButton('lessonType')?.value() === 'playing'
}, '1fr');
row.addCheckbox('greenFees', {
label: 'Green Fees Included (+varies)',
defaultValue: false,
isVisible: () => lessonSection.radioButton('lessonType')?.value() === 'playing'
}, '1fr');
});
addonsSection.addRow(row => {
row.addCheckbox('customPlan', {
label: 'Custom Practice Plan (+$40)',
defaultValue: false
}, '1fr');
row.addCheckbox('fitnessAssessment', {
label: 'Golf Fitness Assessment (+$75)',
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 lessonType = lessonSection.radioButton('lessonType')?.value() || 'private';
const skillLevel = lessonSection.dropdown('skillLevel')?.value() || 'beginner';
const duration = parseInt(sessionSection.dropdown('duration')?.value() || '60');
const instructorLevel = sessionSection.dropdown('instructorLevel')?.value() || 'pga';
const facility = sessionSection.dropdown('facility')?.value() || 'driving-range';
const packageType = packageSection.dropdown('package')?.value() || 'single';
const golfers = sessionSection.integer('golfers')?.value() || 2;
// Base rates per hour by lesson type
const lessonRates: Record<string, number> = {
'private': 100,
'semi-private': 70,
'group': 40,
'playing': 150,
'camp': 0,
'fitting': 150
};
let baseRate = lessonRates[lessonType] || 100;
// Instructor level multiplier
const instructorMult: Record<string, number> = {
'apprentice': 0.7,
'pga': 1.0,
'senior': 1.3,
'master': 1.6,
'tour': 2.5
};
baseRate *= instructorMult[instructorLevel] || 1.0;
// Facility adjustment
const facilityMult: Record<string, number> = {
'driving-range': 1.0,
'public-course': 1.1,
'private-club': 1.4,
'indoor': 1.2,
'resort': 1.5
};
baseRate *= facilityMult[facility] || 1.0;
// Skill level adjustment (advanced players often need specialized coaching)
const skillMult: Record<string, number> = {
'never': 1.0,
'beginner': 1.0,
'high-handicap': 1.0,
'mid-handicap': 1.05,
'low-handicap': 1.15,
'scratch': 1.25
};
baseRate *= skillMult[skillLevel] || 1.0;
// Duration calculation
let lessonPrice = baseRate * (duration / 60);
// Camp/School pricing
if (lessonType === 'camp') {
const campType = campSection.dropdown('campType')?.value() || 'full-day';
const days = campSection.integer('campDays')?.value() || 3;
const campRates: Record<string, number> = {
'half-day': 175,
'full-day': 300,
'weekend': 500,
'week': 350,
'junior-camp': 125
};
lessonPrice = (campRates[campType] ?? 0) * days;
}
// Fitting session is typically flat rate
if (lessonType === 'fitting') {
lessonPrice = 150 * (duration / 60);
}
// Add-ons
let addons = 0;
if (addonsSection.checkbox('videoAnalysis')?.value()) addons += 30;
if (addonsSection.checkbox('trackman')?.value()) addons += 50;
if (addonsSection.checkbox('clubRental')?.value()) addons += 25;
if (addonsSection.checkbox('rangeBalls')?.value()) addons += 15;
if (addonsSection.checkbox('golfCart')?.value()) addons += 30;
if (addonsSection.checkbox('greenFees')?.value()) addons += 75;
if (addonsSection.checkbox('customPlan')?.value()) addons += 40;
if (addonsSection.checkbox('fitnessAssessment')?.value()) addons += 75;
lessonPrice += addons;
// Package discounts
const packageDiscounts: Record<string, number> = {
'single': 0,
'3-pack': 0.05,
'5-pack': 0.10,
'10-pack': 0.15,
'monthly': 0.20
};
const discount = packageDiscounts[packageType] || 0;
const packageQuantities: Record<string, number> = {
'single': 1,
'3-pack': 3,
'5-pack': 5,
'10-pack': 10,
'monthly': 4
};
const sessions = packageQuantities[packageType] || 1;
const discountedPrice = lessonPrice * (1 - discount);
const packageTotal = discountedPrice * sessions;
const monthlyEstimate = discountedPrice * 4;
return {
perLesson: Math.round(lessonPrice),
discountedLesson: Math.round(discountedPrice),
packageTotal: Math.round(packageTotal),
monthlyEstimate: Math.round(monthlyEstimate),
discount: Math.round(discount * 100),
sessions,
addons: Math.round(addons),
duration
};
};
pricingSection.addRow(row => {
row.addPriceDisplay('perLesson', {
label: () => `Per Lesson (${calculatePrice().duration} min)`,
computedValue: () => calculatePrice().perLesson,
variant: 'default'
}, '1fr');
row.addPriceDisplay('discounted', {
label: () => `After ${calculatePrice().discount}% Discount`,
computedValue: () => calculatePrice().discountedLesson,
variant: 'success',
isVisible: () => calculatePrice().discount > 0
}, '1fr');
});
pricingSection.addRow(row => {
row.addPriceDisplay('addons', {
label: 'Add-ons & Technology',
computedValue: () => calculatePrice().addons,
variant: 'default',
isVisible: () => calculatePrice().addons > 0
});
});
// Summary Section
const summarySection = form.addSubform('summary', {
title: '๐งพ Summary',
isCollapsible: false,
sticky: 'bottom'
});
summarySection.addRow(row => {
row.addPriceDisplay('total', {
label: () => calculatePrice().sessions > 1 ? `Package Total (${calculatePrice().sessions} lessons)` : 'Lesson Total',
computedValue: () => calculatePrice().packageTotal,
variant: 'large'
}, '1fr');
row.addPriceDisplay('monthly', {
label: 'Monthly Estimate (4 lessons)',
computedValue: () => calculatePrice().monthlyEstimate,
variant: 'default',
isVisible: () => calculatePrice().sessions === 1
}, '1fr');
});
summarySection.addRow(row => {
row.addTextPanel('note', {
computedValue: () => 'Range fees and green fees may be additional. Equipment not included unless specified.',
customStyles: { 'font-size': '0.85rem', 'color': '#64748b', 'text-align': 'center' }
});
});
form.configureSubmitButton({
label: 'Book Golf Lesson'
});
}