export function drivingSchoolCalculator(form: FormTs) {
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Driving School Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// License Type Section
const licenseSection = form.addSubform('license', { title: '๐ License Type' });
licenseSection.addRow(row => {
row.addRadioButton('licenseType', {
label: 'License Category',
options: [
{ id: 'learner', name: 'Learner Permit (First-time)' },
{ id: 'standard', name: 'Standard Driver License' },
{ id: 'refresher', name: 'Refresher Course' },
{ id: 'senior', name: 'Senior Refresher' },
{ id: 'motorcycle', name: 'Motorcycle License' },
{ id: 'commercial', name: 'Commercial (CDL)' }
],
defaultValue: 'standard',
orientation: 'vertical'
});
});
licenseSection.addRow(row => {
row.addDropdown('transmission', {
label: 'Transmission Type',
options: [
{ id: 'automatic', name: 'Automatic' },
{ id: 'manual', name: 'Manual/Stick Shift' }
],
defaultValue: 'automatic',
isVisible: () => licenseSection.radioButton('licenseType')?.value() !== 'motorcycle'
}, '1fr');
});
// Student Info Section
const studentSection = form.addSubform('student', { title: '๐ค Student Information' });
studentSection.addRow(row => {
row.addDropdown('ageGroup', {
label: 'Age Group',
options: [
{ id: 'teen', name: 'Teen (15-17 years)' },
{ id: 'young-adult', name: 'Young Adult (18-25 years)' },
{ id: 'adult', name: 'Adult (26-59 years)' },
{ id: 'senior', name: 'Senior (60+ years)' }
],
defaultValue: 'young-adult',
isRequired: true
}, '1fr');
row.addDropdown('experience', {
label: 'Driving Experience',
options: [
{ id: 'none', name: 'No Experience' },
{ id: 'some', name: 'Some Practice (under 10 hrs)' },
{ id: 'moderate', name: 'Moderate (10-30 hrs)' },
{ id: 'experienced', name: 'Experienced (needs brush-up)' }
],
defaultValue: 'none',
isRequired: true
}, '1fr');
});
studentSection.addRow(row => {
row.addCheckbox('nervousDriver', {
label: 'Nervous/Anxious Driver',
defaultValue: false
}, '1fr');
row.addCheckbox('foreignLicense', {
label: 'Converting Foreign License',
defaultValue: false
}, '1fr');
});
// Lesson Package Section
const packageSection = form.addSubform('package', { title: '๐ฆ Lesson Package' });
packageSection.addRow(row => {
row.addRadioButton('lessonPackage', {
label: 'Package Type',
options: [
{ id: 'single', name: 'Single Lesson' },
{ id: '5-lesson', name: '5-Lesson Package (5% off)' },
{ id: '10-lesson', name: '10-Lesson Package (10% off)' },
{ id: '15-lesson', name: '15-Lesson Package (15% off)' },
{ id: '20-lesson', name: '20-Lesson Package (20% off)' },
{ id: 'complete', name: 'Complete Course (25% off)' }
],
defaultValue: '10-lesson',
orientation: 'vertical'
});
});
packageSection.addRow(row => {
row.addDropdown('lessonDuration', {
label: 'Lesson Duration',
options: [
{ id: '60', name: '1 hour' },
{ id: '90', name: '1.5 hours' },
{ id: '120', name: '2 hours' }
],
defaultValue: '60',
isRequired: true
}, '1fr');
row.addDropdown('frequency', {
label: 'Lessons per Week',
options: [
{ id: '1', name: 'Once a week' },
{ id: '2', name: 'Twice a week' },
{ id: '3', name: 'Three times a week' },
{ id: 'intensive', name: 'Intensive (daily)' }
],
defaultValue: '2'
}, '1fr');
});
// Vehicle Section
const vehicleSection = form.addSubform('vehicle', { title: '๐ Vehicle Options' });
vehicleSection.addRow(row => {
row.addRadioButton('vehicleType', {
label: 'Training Vehicle',
options: [
{ id: 'sedan', name: 'Standard Sedan' },
{ id: 'suv', name: 'SUV/Crossover' },
{ id: 'hybrid', name: 'Hybrid/Electric' },
{ id: 'student', name: 'Student\'s Own Vehicle' }
],
defaultValue: 'sedan',
orientation: 'horizontal',
isVisible: () => licenseSection.radioButton('licenseType')?.value() !== 'motorcycle'
});
});
vehicleSection.addRow(row => {
row.addCheckbox('dualControls', {
label: 'Dual Control Vehicle',
defaultValue: true,
isVisible: () => vehicleSection.radioButton('vehicleType')?.value() !== 'student'
}, '1fr');
row.addCheckbox('dashCam', {
label: 'In-Car Camera Recording',
defaultValue: false
}, '1fr');
});
// Instructor Section
const instructorSection = form.addSubform('instructor', { title: '๐จโ๐ซ Instructor' });
instructorSection.addRow(row => {
row.addRadioButton('instructorLevel', {
label: 'Instructor Experience',
options: [
{ id: 'junior', name: 'Junior Instructor (1-3 yrs)' },
{ id: 'standard', name: 'Standard Instructor (3-10 yrs)' },
{ id: 'senior', name: 'Senior Instructor (10+ yrs)' },
{ id: 'master', name: 'Master Instructor/Examiner' }
],
defaultValue: 'standard',
orientation: 'vertical'
});
});
instructorSection.addRow(row => {
row.addDropdown('language', {
label: 'Instruction Language',
options: [
{ id: 'english', name: 'English' },
{ id: 'spanish', name: 'Spanish' },
{ id: 'chinese', name: 'Chinese' },
{ id: 'other', name: 'Other Language' }
],
defaultValue: 'english'
}, '1fr');
});
// Additional Services Section
const servicesSection = form.addSubform('services', { title: 'โจ Additional Services' });
servicesSection.addRow(row => {
row.addCheckbox('pickup', {
label: 'Home/Work Pickup',
defaultValue: true
}, '1fr');
row.addCheckbox('testPrep', {
label: 'Road Test Preparation',
defaultValue: false
}, '1fr');
});
servicesSection.addRow(row => {
row.addCheckbox('testVehicle', {
label: 'Vehicle for Road Test',
defaultValue: false
}, '1fr');
row.addCheckbox('defensiveDriving', {
label: 'Defensive Driving Course',
defaultValue: false
}, '1fr');
});
servicesSection.addRow(row => {
row.addCheckbox('parallelParking', {
label: 'Extra Parallel Parking Practice',
defaultValue: false
}, '1fr');
row.addCheckbox('highwayDriving', {
label: 'Highway Driving Practice',
defaultValue: false
}, '1fr');
});
servicesSection.addRow(row => {
row.addCheckbox('nightDriving', {
label: 'Night Driving Practice',
defaultValue: false
}, '1fr');
row.addCheckbox('classroom', {
label: 'Classroom Instruction',
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 licenseType = licenseSection.radioButton('licenseType')?.value() || 'standard';
const transmission = licenseSection.dropdown('transmission')?.value() || 'automatic';
const experience = studentSection.dropdown('experience')?.value() || 'none';
const lessonPackage = packageSection.radioButton('lessonPackage')?.value() || '10-lesson';
const duration = parseInt(packageSection.dropdown('lessonDuration')?.value() || '60');
const vehicleType = vehicleSection.radioButton('vehicleType')?.value() || 'sedan';
const instructorLevel = instructorSection.radioButton('instructorLevel')?.value() || 'standard';
// Base rate per hour
const baseRates: Record<string, number> = {
'junior': 50,
'standard': 65,
'senior': 80,
'master': 100
};
let hourlyRate = baseRates[instructorLevel] || 65;
// License type adjustment
const licenseMult: Record<string, number> = {
'learner': 1.0,
'standard': 1.0,
'refresher': 0.9,
'senior': 1.1,
'motorcycle': 1.3,
'commercial': 1.8
};
hourlyRate *= licenseMult[licenseType] || 1.0;
// Transmission adjustment
if (transmission === 'manual') {
hourlyRate *= 1.15;
}
// Duration calculation (slight discount for longer lessons)
const hours = duration / 60;
let lessonPrice = hourlyRate * hours;
if (duration === 90) lessonPrice *= 0.95; // 5% better value
if (duration === 120) lessonPrice *= 0.9; // 10% better value
// Vehicle type adjustment
const vehicleMult: Record<string, number> = {
'sedan': 1.0,
'suv': 1.1,
'hybrid': 1.15,
'student': 0.85
};
lessonPrice *= vehicleMult[vehicleType] || 1.0;
// Package calculations
const packageDiscount: Record<string, number> = {
'single': 0,
'5-lesson': 0.05,
'10-lesson': 0.10,
'15-lesson': 0.15,
'20-lesson': 0.20,
'complete': 0.25
};
const discount = packageDiscount[lessonPackage] || 0;
const packageLessons: Record<string, number> = {
'single': 1,
'5-lesson': 5,
'10-lesson': 10,
'15-lesson': 15,
'20-lesson': 20,
'complete': 30
};
const numLessons = packageLessons[lessonPackage] || 1;
// Additional services
let servicesPrice = 0;
if (servicesSection.checkbox('pickup')?.value()) servicesPrice += 5 * numLessons; // Per lesson
if (servicesSection.checkbox('testPrep')?.value()) servicesPrice += 75;
if (servicesSection.checkbox('testVehicle')?.value()) servicesPrice += 100;
if (servicesSection.checkbox('defensiveDriving')?.value()) servicesPrice += 150;
if (servicesSection.checkbox('parallelParking')?.value()) servicesPrice += 50;
if (servicesSection.checkbox('highwayDriving')?.value()) servicesPrice += 75;
if (servicesSection.checkbox('nightDriving')?.value()) servicesPrice += 50;
if (servicesSection.checkbox('classroom')?.value()) servicesPrice += 200;
// Nervous driver surcharge (extra patience/time)
if (studentSection.checkbox('nervousDriver')?.value()) {
lessonPrice *= 1.1;
}
// Dual controls
if (vehicleSection.checkbox('dualControls')?.value() && vehicleType !== 'student') {
// Already included in base price, no additional charge
}
// Dash cam
if (vehicleSection.checkbox('dashCam')?.value()) {
servicesPrice += 10 * numLessons;
}
const packageTotal = (lessonPrice * numLessons * (1 - discount)) + servicesPrice;
const effectivePerLesson = (packageTotal - servicesPrice) / numLessons;
return {
lessonPrice: Math.round(lessonPrice),
discount: Math.round(discount * 100),
packageTotal: Math.round(packageTotal),
numLessons,
effectivePerLesson: Math.round(effectivePerLesson),
servicesPrice: Math.round(servicesPrice),
duration
};
};
pricingSection.addRow(row => {
row.addPriceDisplay('perLesson', {
label: 'Per Lesson',
computedValue: () => calculatePrice().lessonPrice,
variant: 'default'
}, '1fr');
row.addTextPanel('duration', {
computedValue: () => `(${calculatePrice().duration} min)`,
customStyles: { 'font-size': '0.9rem', 'color': '#64748b', 'align-self': 'center' }
}, '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 lesson)';
},
customStyles: { 'font-size': '0.95rem', 'color': '#16a34a', 'font-weight': '500' },
isVisible: () => calculatePrice().discount > 0
});
});
pricingSection.addRow(row => {
row.addPriceDisplay('services', {
label: 'Additional Services',
computedValue: () => calculatePrice().servicesPrice,
variant: 'default',
isVisible: () => calculatePrice().servicesPrice > 0
}, '1fr');
});
// Summary Section
const summarySection = form.addSubform('summary', {
title: '๐งพ Summary',
isCollapsible: false,
sticky: 'bottom'
});
summarySection.addRow(row => {
row.addPriceDisplay('total', {
label: 'Package Total',
computedValue: () => calculatePrice().packageTotal,
variant: 'large'
}, '1fr');
row.addTextPanel('perLessonFinal', {
computedValue: () => {
const price = calculatePrice();
return `$${price.effectivePerLesson}/lesson`;
},
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.numLessons} lesson${price.numLessons > 1 ? 's' : ''} ร ${price.duration} minutes`;
},
customStyles: { 'font-size': '0.9rem', 'color': '#475569', 'text-align': 'center' }
});
});
summarySection.addRow(row => {
row.addTextPanel('note', {
computedValue: () => 'Road test fees paid separately to DMV. Prices may vary based on location and scheduling.',
customStyles: { 'font-size': '0.85rem', 'color': '#64748b', 'text-align': 'center' }
});
});
form.configureSubmitButton({
label: 'Book Driving Lesson'
});
}