export function artLessonsCalculator(form: FormTs) {
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Art Lessons Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Art Medium Section
const mediumSection = form.addSubform('medium', { title: '๐จ Art Medium' });
mediumSection.addRow(row => {
row.addRadioButton('artType', {
label: 'Primary Medium',
options: [
{ id: 'drawing', name: 'Drawing (Pencil, Charcoal)' },
{ id: 'painting', name: 'Painting (Oil, Acrylic, Watercolor)' },
{ id: 'sculpture', name: 'Sculpture & 3D Art' },
{ id: 'digital', name: 'Digital Art' },
{ id: 'mixed', name: 'Mixed Media' }
],
defaultValue: 'drawing',
orientation: 'vertical'
});
});
mediumSection.addRow(row => {
row.addDropdown('paintingType', {
label: 'Painting Type',
options: [
{ id: 'watercolor', name: 'Watercolor' },
{ id: 'acrylic', name: 'Acrylic' },
{ id: 'oil', name: 'Oil Painting' },
{ id: 'gouache', name: 'Gouache' },
{ id: 'pastel', name: 'Pastel' }
],
defaultValue: 'acrylic',
isVisible: () => mediumSection.radioButton('artType')?.value() === 'painting'
}, '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-on-1)' },
{ id: 'semi-private', name: 'Semi-Private (2-3 students)' },
{ id: 'small-group', name: 'Small Group (4-6 students)' },
{ id: 'large-group', name: 'Large Group (7-12 students)' }
],
defaultValue: 'private',
orientation: 'horizontal'
});
});
formatSection.addRow(row => {
row.addDropdown('duration', {
label: 'Lesson Duration',
options: [
{ id: '60', name: '1 hour' },
{ id: '90', name: '1.5 hours' },
{ id: '120', name: '2 hours' },
{ id: '180', name: '3 hours (workshop)' }
],
defaultValue: '90',
isRequired: true
}, '1fr');
row.addDropdown('frequency', {
label: 'Frequency',
options: [
{ id: 'single', name: 'Single Session' },
{ id: 'weekly', name: 'Weekly' },
{ id: 'biweekly', name: 'Bi-weekly' },
{ id: 'monthly', name: 'Monthly' }
],
defaultValue: 'weekly'
}, '1fr');
});
formatSection.addRow(row => {
row.addDropdown('location', {
label: 'Location',
options: [
{ id: 'studio', name: 'Art Studio/School' },
{ id: 'home', name: 'In-Home (teacher travels)' },
{ id: 'online', name: 'Online/Virtual' },
{ id: 'plein-air', name: 'Outdoor/Plein Air' }
],
defaultValue: 'studio'
}, '1fr');
});
// Student Info Section
const studentSection = form.addSubform('student', { title: '๐ค Student Information' });
studentSection.addRow(row => {
row.addDropdown('ageGroup', {
label: 'Age Group',
options: [
{ id: 'child', name: 'Child (6-12 years)' },
{ id: 'teen', name: 'Teen (13-17 years)' },
{ id: 'adult', name: 'Adult (18-59 years)' },
{ id: 'senior', name: 'Senior (60+ years)' }
],
defaultValue: 'adult',
isRequired: true
}, '1fr');
row.addDropdown('skillLevel', {
label: 'Skill Level',
options: [
{ id: 'beginner', name: 'Beginner (0-1 years)' },
{ id: 'elementary', name: 'Elementary (1-2 years)' },
{ id: 'intermediate', name: 'Intermediate (2-4 years)' },
{ id: 'advanced', name: 'Advanced (4+ years)' },
{ id: 'professional', name: 'Professional/Portfolio' }
],
defaultValue: 'beginner',
isRequired: true
}, '1fr');
});
studentSection.addRow(row => {
row.addDropdown('goals', {
label: 'Learning Goals',
options: [
{ id: 'hobby', name: 'Hobby/Recreation' },
{ id: 'skill-building', name: 'Skill Development' },
{ id: 'portfolio', name: 'Portfolio Building' },
{ id: 'competition', name: 'Competition/Exhibition' },
{ id: 'therapy', name: 'Art Therapy' }
],
defaultValue: 'hobby'
}, '1fr');
});
// Instructor Section
const instructorSection = form.addSubform('instructor', { title: '๐ฉโ๐จ Instructor Level' });
instructorSection.addRow(row => {
row.addRadioButton('teacherLevel', {
label: 'Instructor Experience',
options: [
{ id: 'student', name: 'Art Student/Assistant' },
{ id: 'junior', name: 'Junior Instructor (1-5 yrs)' },
{ id: 'experienced', name: 'Experienced Artist (5-15 yrs)' },
{ id: 'master', name: 'Master Artist (15+ yrs)' },
{ id: 'renowned', name: 'Renowned/Gallery Artist' }
],
defaultValue: 'experienced',
orientation: 'vertical'
});
});
// Materials Section
const materialsSection = form.addSubform('materials', { title: '๐๏ธ Materials & Supplies' });
materialsSection.addRow(row => {
row.addRadioButton('materialsIncluded', {
label: 'Materials Provision',
options: [
{ id: 'included', name: 'All materials included' },
{ id: 'basic', name: 'Basic materials included' },
{ id: 'student', name: 'Student brings own materials' }
],
defaultValue: 'basic',
orientation: 'horizontal'
});
});
materialsSection.addRow(row => {
row.addCheckbox('canvas', {
label: 'Canvas/Paper',
defaultValue: false,
isVisible: () => materialsSection.radioButton('materialsIncluded')?.value() !== 'student'
}, '1fr');
row.addCheckbox('paints', {
label: 'Paints/Pigments',
defaultValue: false,
isVisible: () => materialsSection.radioButton('materialsIncluded')?.value() !== 'student' &&
(mediumSection.radioButton('artType')?.value() === 'painting' || mediumSection.radioButton('artType')?.value() === 'mixed')
}, '1fr');
});
materialsSection.addRow(row => {
row.addCheckbox('brushes', {
label: 'Brushes/Tools',
defaultValue: false,
isVisible: () => materialsSection.radioButton('materialsIncluded')?.value() !== 'student'
}, '1fr');
row.addCheckbox('easel', {
label: 'Easel Usage',
defaultValue: false,
isVisible: () => materialsSection.radioButton('materialsIncluded')?.value() !== 'student'
}, '1fr');
});
// Package Section
const packageSection = form.addSubform('package', { title: '๐ฆ Package Options' });
packageSection.addRow(row => {
row.addDropdown('paymentPlan', {
label: 'Payment Plan',
options: [
{ id: 'per-lesson', name: 'Pay Per Lesson' },
{ id: 'monthly', name: 'Monthly Package (4 lessons, 5% off)' },
{ id: '8-pack', name: '8-Lesson Package (10% off)' },
{ id: '12-pack', name: '12-Lesson Package (15% off)' },
{ id: 'semester', name: 'Semester (16 lessons, 20% off)' }
],
defaultValue: 'monthly',
isRequired: true
}, '1fr');
});
// Add-ons Section
const addonsSection = form.addSubform('addons', { title: 'โจ Additional Services' });
addonsSection.addRow(row => {
row.addCheckbox('portfolioReview', {
label: 'Portfolio Review',
defaultValue: false
}, '1fr');
row.addCheckbox('exhibition', {
label: 'Student Exhibition Entry',
defaultValue: false
}, '1fr');
});
addonsSection.addRow(row => {
row.addCheckbox('certification', {
label: 'Completion Certificate',
defaultValue: false
}, '1fr');
row.addCheckbox('digitalCopy', {
label: 'Digital Documentation',
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 artType = mediumSection.radioButton('artType')?.value() || 'drawing';
const classType = formatSection.radioButton('classType')?.value() || 'private';
const duration = parseInt(formatSection.dropdown('duration')?.value() || '90');
const location = formatSection.dropdown('location')?.value() || 'studio';
const skillLevel = studentSection.dropdown('skillLevel')?.value() || 'beginner';
const goals = studentSection.dropdown('goals')?.value() || 'hobby';
const teacherLevel = instructorSection.radioButton('teacherLevel')?.value() || 'experienced';
const materialsIncluded = materialsSection.radioButton('materialsIncluded')?.value() || 'basic';
const paymentPlan = packageSection.dropdown('paymentPlan')?.value() || 'monthly';
// Base rate per hour for private lesson
const baseRates: Record<string, number> = {
'student': 25,
'junior': 40,
'experienced': 60,
'master': 85,
'renowned': 125
};
let hourlyRate = baseRates[teacherLevel] || 60;
// Art medium adjustment
const mediumMult: Record<string, number> = {
'drawing': 1.0,
'painting': 1.15,
'sculpture': 1.25,
'digital': 1.1,
'mixed': 1.2
};
hourlyRate *= mediumMult[artType] || 1.0;
// Duration calculation
const hours = duration / 60;
let lessonPrice = hourlyRate * hours;
// Class type adjustment (per student)
const classMult: Record<string, number> = {
'private': 1.0,
'semi-private': 0.7,
'small-group': 0.5,
'large-group': 0.35
};
lessonPrice *= classMult[classType] || 1.0;
// Location adjustment
const locationMult: Record<string, number> = {
'studio': 1.0,
'home': 1.3,
'online': 0.85,
'plein-air': 1.15
};
lessonPrice *= locationMult[location] || 1.0;
// Skill level adjustment
const levelMult: Record<string, number> = {
'beginner': 1.0,
'elementary': 1.0,
'intermediate': 1.1,
'advanced': 1.2,
'professional': 1.35
};
lessonPrice *= levelMult[skillLevel] || 1.0;
// Goals adjustment
const goalsMult: Record<string, number> = {
'hobby': 1.0,
'skill-building': 1.05,
'portfolio': 1.15,
'competition': 1.2,
'therapy': 1.1
};
lessonPrice *= goalsMult[goals] || 1.0;
// Materials cost
let materialsCost = 0;
if (materialsIncluded === 'included') {
materialsCost = 20;
} else if (materialsIncluded === 'basic') {
materialsCost = 10;
}
// Additional materials
if (materialsSection.checkbox('canvas')?.value()) materialsCost += 8;
if (materialsSection.checkbox('paints')?.value()) materialsCost += 12;
if (materialsSection.checkbox('brushes')?.value()) materialsCost += 5;
if (materialsSection.checkbox('easel')?.value()) materialsCost += 5;
// Package calculations
const packageDiscount: Record<string, number> = {
'per-lesson': 0,
'monthly': 0.05,
'8-pack': 0.10,
'12-pack': 0.15,
'semester': 0.20
};
const discount = packageDiscount[paymentPlan] || 0;
const packageLessons: Record<string, number> = {
'per-lesson': 1,
'monthly': 4,
'8-pack': 8,
'12-pack': 12,
'semester': 16
};
const numLessons = packageLessons[paymentPlan] || 1;
// Add-ons
let addonsPrice = 0;
if (addonsSection.checkbox('portfolioReview')?.value()) addonsPrice += 50;
if (addonsSection.checkbox('exhibition')?.value()) addonsPrice += 35;
if (addonsSection.checkbox('certification')?.value()) addonsPrice += 25;
if (addonsSection.checkbox('digitalCopy')?.value()) addonsPrice += 15;
const lessonWithMaterials = lessonPrice + materialsCost;
const packageTotal = (lessonWithMaterials * numLessons * (1 - discount)) + addonsPrice;
const effectivePerLesson = (packageTotal - addonsPrice) / numLessons;
return {
lessonPrice: Math.round(lessonPrice),
materialsCost: Math.round(materialsCost),
lessonWithMaterials: Math.round(lessonWithMaterials),
discount: Math.round(discount * 100),
packageTotal: Math.round(packageTotal),
numLessons,
effectivePerLesson: Math.round(effectivePerLesson),
addonsPrice: Math.round(addonsPrice),
duration
};
};
pricingSection.addRow(row => {
row.addPriceDisplay('perLesson', {
label: 'Per Lesson',
computedValue: () => calculatePrice().lessonPrice,
variant: 'default'
}, '1fr');
row.addPriceDisplay('materials', {
label: 'Materials',
computedValue: () => calculatePrice().materialsCost,
variant: 'default',
isVisible: () => calculatePrice().materialsCost > 0
}, '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 (pay per lesson)';
},
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: '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: () => 'Prices may vary based on specific project requirements. Trial lessons may be available at a reduced rate.',
customStyles: { 'font-size': '0.85rem', 'color': '#64748b', 'text-align': 'center' }
});
});
form.configureSubmitButton({
label: 'Book Art Lesson'
});
}