export function beautySalonCalculator(form: FormTs) {
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Beauty Salon Price Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Service Category Section
const categorySection = form.addSubform('category', { title: '๐
Service Category' });
categorySection.addRow(row => {
row.addRadioButton('serviceType', {
label: 'What would you like today?',
options: [
{ id: 'facial', name: 'Facial Treatments' },
{ id: 'waxing', name: 'Waxing Services' },
{ id: 'makeup', name: 'Makeup Services' },
{ id: 'body', name: 'Body Treatments' },
{ id: 'package', name: 'Spa Package' }
],
defaultValue: 'facial',
orientation: 'vertical',
isRequired: true
});
});
// Facial Section
const facialSection = form.addSubform('facial', {
title: 'โจ Facial Treatments',
isVisible: () => categorySection.radioButton('serviceType')?.value() === 'facial'
});
facialSection.addRow(row => {
row.addDropdown('facialType', {
label: 'Facial Type',
options: [
{ id: 'express', name: 'Express Facial (30 min)' },
{ id: 'classic', name: 'Classic Facial (60 min)' },
{ id: 'deep-cleansing', name: 'Deep Cleansing Facial' },
{ id: 'anti-aging', name: 'Anti-Aging Facial' },
{ id: 'hydrating', name: 'Hydrating Facial' },
{ id: 'acne', name: 'Acne Treatment Facial' },
{ id: 'brightening', name: 'Brightening/Vitamin C Facial' }
],
defaultValue: 'classic',
isRequired: true
}, '1fr');
});
facialSection.addRow(row => {
row.addCheckbox('microderm', {
label: 'Add Microdermabrasion (+$50)',
defaultValue: false
}, '1fr');
row.addCheckbox('chemicalPeel', {
label: 'Add Chemical Peel (+$75)',
defaultValue: false
}, '1fr');
});
facialSection.addRow(row => {
row.addCheckbox('ledTherapy', {
label: 'LED Light Therapy (+$35)',
defaultValue: false
}, '1fr');
row.addCheckbox('extractions', {
label: 'Extended Extractions (+$25)',
defaultValue: false
}, '1fr');
});
// Waxing Section
const waxingSection = form.addSubform('waxing', {
title: '๐ธ Waxing Services',
isVisible: () => categorySection.radioButton('serviceType')?.value() === 'waxing'
});
waxingSection.addRow(row => {
row.addDropdown('waxType', {
label: 'Wax Type',
options: [
{ id: 'soft', name: 'Soft Wax (Standard)' },
{ id: 'hard', name: 'Hard Wax (Sensitive Skin)' },
{ id: 'sugar', name: 'Sugar Wax (Natural)' }
],
defaultValue: 'hard'
}, '1fr');
});
waxingSection.addRow(row => {
row.addTextPanel('faceLabel', {
computedValue: () => 'Face',
customStyles: { 'font-weight': '600', 'color': '#475569' }
});
});
waxingSection.addRow(row => {
row.addCheckbox('eyebrows', {
label: 'Eyebrows',
defaultValue: false
}, '1fr');
row.addCheckbox('upperLip', {
label: 'Upper Lip',
defaultValue: false
}, '1fr');
row.addCheckbox('chin', {
label: 'Chin',
defaultValue: false
}, '1fr');
});
waxingSection.addRow(row => {
row.addCheckbox('fullFace', {
label: 'Full Face',
defaultValue: false
}, '1fr');
row.addCheckbox('sideburns', {
label: 'Sideburns',
defaultValue: false
}, '1fr');
});
waxingSection.addRow(row => {
row.addTextPanel('bodyLabel', {
computedValue: () => 'Body',
customStyles: { 'font-weight': '600', 'color': '#475569', 'margin-top': '10px' }
});
});
waxingSection.addRow(row => {
row.addCheckbox('underarms', {
label: 'Underarms',
defaultValue: false
}, '1fr');
row.addCheckbox('fullArms', {
label: 'Full Arms',
defaultValue: false
}, '1fr');
row.addCheckbox('halfArms', {
label: 'Half Arms',
defaultValue: false
}, '1fr');
});
waxingSection.addRow(row => {
row.addCheckbox('fullLegs', {
label: 'Full Legs',
defaultValue: false
}, '1fr');
row.addCheckbox('halfLegs', {
label: 'Half Legs',
defaultValue: false
}, '1fr');
row.addCheckbox('back', {
label: 'Back',
defaultValue: false
}, '1fr');
});
waxingSection.addRow(row => {
row.addCheckbox('bikini', {
label: 'Bikini Line',
defaultValue: false
}, '1fr');
row.addCheckbox('brazilianWax', {
label: 'Brazilian',
defaultValue: false
}, '1fr');
});
// Makeup Section
const makeupSection = form.addSubform('makeup', {
title: '๐ Makeup Services',
isVisible: () => categorySection.radioButton('serviceType')?.value() === 'makeup'
});
makeupSection.addRow(row => {
row.addDropdown('makeupType', {
label: 'Occasion',
options: [
{ id: 'everyday', name: 'Everyday/Natural Look' },
{ id: 'evening', name: 'Evening/Glamour' },
{ id: 'special', name: 'Special Event' },
{ id: 'bridal', name: 'Bridal Makeup' },
{ id: 'photoshoot', name: 'Photoshoot/Editorial' }
],
defaultValue: 'everyday',
isRequired: true
}, '1fr');
});
makeupSection.addRow(row => {
row.addCheckbox('bridalTrial', {
label: 'Include Trial Session',
defaultValue: true,
isVisible: () => makeupSection.dropdown('makeupType')?.value() === 'bridal'
}, '1fr');
row.addCheckbox('lashes', {
label: 'False Lashes Application (+$20)',
defaultValue: false
}, '1fr');
});
makeupSection.addRow(row => {
row.addCheckbox('touchUpKit', {
label: 'Touch-Up Kit (+$15)',
defaultValue: false
}, '1fr');
row.addCheckbox('makeupLesson', {
label: 'Include Mini Lesson (+$30)',
defaultValue: false
}, '1fr');
});
// Body Treatments Section
const bodySection = form.addSubform('body', {
title: '๐งด Body Treatments',
isVisible: () => categorySection.radioButton('serviceType')?.value() === 'body'
});
bodySection.addRow(row => {
row.addCheckbox('bodyScrub', {
label: 'Body Scrub/Exfoliation',
defaultValue: false
}, '1fr');
row.addCheckbox('bodyWrap', {
label: 'Body Wrap',
defaultValue: false
}, '1fr');
});
bodySection.addRow(row => {
row.addDropdown('wrapType', {
label: 'Wrap Type',
options: [
{ id: 'detox', name: 'Detox/Mud Wrap' },
{ id: 'hydrating', name: 'Hydrating Wrap' },
{ id: 'slimming', name: 'Slimming/Contour Wrap' },
{ id: 'seaweed', name: 'Seaweed Wrap' }
],
defaultValue: 'hydrating',
isVisible: () => bodySection.checkbox('bodyWrap')?.value() === true
}, '1fr');
});
bodySection.addRow(row => {
row.addCheckbox('backFacial', {
label: 'Back Facial',
defaultValue: false
}, '1fr');
row.addCheckbox('handTreatment', {
label: 'Hand Treatment',
defaultValue: false
}, '1fr');
});
bodySection.addRow(row => {
row.addCheckbox('footTreatment', {
label: 'Foot Treatment',
defaultValue: false
}, '1fr');
row.addCheckbox('scalp', {
label: 'Scalp Treatment',
defaultValue: false
}, '1fr');
});
// Package Section
const packageSection = form.addSubform('package', {
title: '๐ Spa Packages',
isVisible: () => categorySection.radioButton('serviceType')?.value() === 'package'
});
packageSection.addRow(row => {
row.addDropdown('packageType', {
label: 'Select Package',
options: [
{ id: 'express', name: 'Express Refresh (1 hour)' },
{ id: 'classic', name: 'Classic Spa Day (2 hours)' },
{ id: 'deluxe', name: 'Deluxe Pamper (3 hours)' },
{ id: 'ultimate', name: 'Ultimate Indulgence (4 hours)' },
{ id: 'bridal', name: 'Bridal Beauty Package' },
{ id: 'couples', name: 'Couples Package' }
],
defaultValue: 'classic',
isRequired: true
}, '1fr');
});
packageSection.addRow(row => {
row.addTextPanel('packageDetails', {
computedValue: () => {
const pkg = packageSection.dropdown('packageType')?.value();
const details: Record<string, string> = {
'express': 'Includes: Express Facial + Mini Manicure',
'classic': 'Includes: Classic Facial + Full Manicure + Pedicure',
'deluxe': 'Includes: Signature Facial + Mani/Pedi + Body Scrub',
'ultimate': 'Includes: Anti-Aging Facial + Full Body Treatment + Mani/Pedi + Makeup',
'bridal': 'Includes: Bridal Facial + Waxing Package + Mani/Pedi + Trial Makeup',
'couples': 'Includes: 2 Classic Facials + 2 Massages + Champagne'
};
return details[pkg || 'classic'] || '';
},
customStyles: { 'font-size': '0.9rem', 'color': '#059669', 'font-style': 'italic' }
});
});
// Add-ons Section
const addonsSection = form.addSubform('addons', { title: 'โ Enhancements' });
addonsSection.addRow(row => {
row.addCheckbox('aromatherapy', {
label: 'Aromatherapy (+$15)',
defaultValue: false
}, '1fr');
row.addCheckbox('hotStones', {
label: 'Hot Stone Add-on (+$25)',
defaultValue: false
}, '1fr');
});
addonsSection.addRow(row => {
row.addCheckbox('eyeMask', {
label: 'Collagen Eye Mask (+$20)',
defaultValue: false
}, '1fr');
row.addCheckbox('lipMask', {
label: 'Lip Treatment (+$15)',
defaultValue: false
}, '1fr');
});
// Timing Section
const timingSection = form.addSubform('timing', { title: '๐
Appointment Details' });
timingSection.addRow(row => {
row.addDropdown('timing', {
label: 'Day & Time',
options: [
{ id: 'weekday', name: 'Weekday (Mon-Thu)' },
{ id: 'friday', name: 'Friday' },
{ id: 'weekend', name: 'Weekend (Sat-Sun)' },
{ id: 'evening', name: 'Evening After 6pm' }
],
defaultValue: 'weekday'
}, '1fr');
row.addDropdown('specialist', {
label: 'Esthetician Level',
options: [
{ id: 'junior', name: 'Junior Esthetician' },
{ id: 'senior', name: 'Senior Esthetician' },
{ id: 'master', name: 'Master Esthetician' }
],
defaultValue: 'senior'
}, '1fr');
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Pricing Section
const pricingSection = form.addSubform('pricing', { title: '๐ฐ Pricing', isCollapsible: false });
const calculatePrice = () => {
const serviceType = categorySection.radioButton('serviceType')?.value() || 'facial';
const timing = timingSection.dropdown('timing')?.value() || 'weekday';
const specialist = timingSection.dropdown('specialist')?.value() || 'senior';
let basePrice = 0;
let addonsTotal = 0;
// Facial pricing
if (serviceType === 'facial') {
const facialType = facialSection.dropdown('facialType')?.value() || 'classic';
const facialPrices: Record<string, number> = {
'express': 55,
'classic': 85,
'deep-cleansing': 95,
'anti-aging': 125,
'hydrating': 95,
'acne': 110,
'brightening': 115
};
basePrice = facialPrices[facialType] || 85;
if (facialSection.checkbox('microderm')?.value()) addonsTotal += 50;
if (facialSection.checkbox('chemicalPeel')?.value()) addonsTotal += 75;
if (facialSection.checkbox('ledTherapy')?.value()) addonsTotal += 35;
if (facialSection.checkbox('extractions')?.value()) addonsTotal += 25;
}
// Waxing pricing
if (serviceType === 'waxing') {
const waxType = waxingSection.dropdown('waxType')?.value() || 'hard';
const waxMult = waxType === 'hard' ? 1.15 : waxType === 'sugar' ? 1.25 : 1.0;
// Face waxing
if (waxingSection.checkbox('eyebrows')?.value()) basePrice += 20;
if (waxingSection.checkbox('upperLip')?.value()) basePrice += 12;
if (waxingSection.checkbox('chin')?.value()) basePrice += 15;
if (waxingSection.checkbox('fullFace')?.value()) basePrice += 55;
if (waxingSection.checkbox('sideburns')?.value()) basePrice += 18;
// Body waxing
if (waxingSection.checkbox('underarms')?.value()) basePrice += 25;
if (waxingSection.checkbox('fullArms')?.value()) basePrice += 45;
if (waxingSection.checkbox('halfArms')?.value()) basePrice += 30;
if (waxingSection.checkbox('fullLegs')?.value()) basePrice += 75;
if (waxingSection.checkbox('halfLegs')?.value()) basePrice += 45;
if (waxingSection.checkbox('back')?.value()) basePrice += 55;
if (waxingSection.checkbox('bikini')?.value()) basePrice += 40;
if (waxingSection.checkbox('brazilianWax')?.value()) basePrice += 70;
basePrice *= waxMult;
}
// Makeup pricing
if (serviceType === 'makeup') {
const makeupType = makeupSection.dropdown('makeupType')?.value() || 'everyday';
const makeupPrices: Record<string, number> = {
'everyday': 65,
'evening': 85,
'special': 100,
'bridal': 175,
'photoshoot': 150
};
basePrice = makeupPrices[makeupType] || 65;
if (makeupType === 'bridal' && makeupSection.checkbox('bridalTrial')?.value()) {
basePrice += 75;
}
if (makeupSection.checkbox('lashes')?.value()) addonsTotal += 20;
if (makeupSection.checkbox('touchUpKit')?.value()) addonsTotal += 15;
if (makeupSection.checkbox('makeupLesson')?.value()) addonsTotal += 30;
}
// Body treatments pricing
if (serviceType === 'body') {
if (bodySection.checkbox('bodyScrub')?.value()) basePrice += 85;
if (bodySection.checkbox('bodyWrap')?.value()) {
const wrapType = bodySection.dropdown('wrapType')?.value() || 'hydrating';
const wrapPrices: Record<string, number> = {
'detox': 120,
'hydrating': 100,
'slimming': 140,
'seaweed': 130
};
basePrice += wrapPrices[wrapType] || 100;
}
if (bodySection.checkbox('backFacial')?.value()) basePrice += 95;
if (bodySection.checkbox('handTreatment')?.value()) basePrice += 35;
if (bodySection.checkbox('footTreatment')?.value()) basePrice += 45;
if (bodySection.checkbox('scalp')?.value()) basePrice += 40;
}
// Package pricing
if (serviceType === 'package') {
const packageType = packageSection.dropdown('packageType')?.value() || 'classic';
const packagePrices: Record<string, number> = {
'express': 95,
'classic': 175,
'deluxe': 275,
'ultimate': 395,
'bridal': 450,
'couples': 350
};
basePrice = packagePrices[packageType] || 175;
}
// Global add-ons
if (addonsSection.checkbox('aromatherapy')?.value()) addonsTotal += 15;
if (addonsSection.checkbox('hotStones')?.value()) addonsTotal += 25;
if (addonsSection.checkbox('eyeMask')?.value()) addonsTotal += 20;
if (addonsSection.checkbox('lipMask')?.value()) addonsTotal += 15;
// Specialist level adjustment
const specialistMult: Record<string, number> = {
'junior': 0.85,
'senior': 1.0,
'master': 1.2
};
basePrice *= specialistMult[specialist] || 1.0;
// Timing adjustment
const timingMult: Record<string, number> = {
'weekday': 1.0,
'friday': 1.0,
'weekend': 1.1,
'evening': 1.05
};
basePrice *= timingMult[timing] || 1.0;
const total = basePrice + addonsTotal;
const tipSuggestion = Math.round(total * 0.2);
return {
services: Math.round(basePrice),
addons: Math.round(addonsTotal),
total: Math.round(total),
tipSuggestion
};
};
pricingSection.addRow(row => {
row.addPriceDisplay('services', {
label: 'Services',
computedValue: () => calculatePrice().services,
variant: 'default'
}, '1fr');
row.addPriceDisplay('addons', {
label: 'Enhancements',
computedValue: () => calculatePrice().addons,
variant: 'default',
isVisible: () => calculatePrice().addons > 0
}, '1fr');
});
// Summary Section
const summarySection = form.addSubform('summary', {
title: '๐งพ Summary',
isCollapsible: false,
sticky: 'bottom'
});
summarySection.addRow(row => {
row.addPriceDisplay('total', {
label: 'Total',
computedValue: () => calculatePrice().total,
variant: 'large'
}, '1fr');
row.addPriceDisplay('tip', {
label: 'Suggested Tip (20%)',
computedValue: () => calculatePrice().tipSuggestion,
variant: 'default'
}, '1fr');
});
summarySection.addRow(row => {
row.addTextPanel('note', {
computedValue: () => 'Prices may vary. Gratuity is appreciated but not included. Please arrive 10 minutes early for your appointment.',
customStyles: { 'font-size': '0.85rem', 'color': '#64748b', 'text-align': 'center' }
});
});
form.configureSubmitButton({
label: 'Book Appointment'
});
}