export function nailSalonCalculator(form: FormTs) {
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Nail Salon Price Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Service Type Section
const serviceSection = form.addSubform('services', { title: '๐
Services' });
serviceSection.addRow(row => {
row.addCheckbox('manicure', {
label: 'Manicure',
defaultValue: true
}, '1fr');
row.addCheckbox('pedicure', {
label: 'Pedicure',
defaultValue: false
}, '1fr');
});
// Manicure Options
const manicureSection = form.addSubform('manicureOptions', {
title: 'โ Manicure Options',
isVisible: () => serviceSection.checkbox('manicure')?.value() === true
});
manicureSection.addRow(row => {
row.addDropdown('manicureType', {
label: 'Manicure Type',
options: [
{ id: 'basic', name: 'Basic Manicure' },
{ id: 'gel', name: 'Gel Manicure' },
{ id: 'dip', name: 'Dip Powder Manicure' },
{ id: 'shellac', name: 'Shellac Manicure' }
],
defaultValue: 'basic',
isRequired: true
}, '1fr');
});
// Nail Enhancement Section
const enhancementSection = form.addSubform('enhancements', { title: '๐ Nail Enhancements' });
enhancementSection.addRow(row => {
row.addCheckbox('extensions', {
label: 'Nail Extensions',
defaultValue: false
}, '1fr');
});
enhancementSection.addRow(row => {
row.addDropdown('extensionType', {
label: 'Extension Type',
options: [
{ id: 'acrylic', name: 'Acrylic' },
{ id: 'hard-gel', name: 'Hard Gel' },
{ id: 'polygel', name: 'Polygel' },
{ id: 'fiberglass', name: 'Fiberglass/Silk Wrap' },
{ id: 'press-on', name: 'Press-On Nails' }
],
defaultValue: 'acrylic',
isVisible: () => enhancementSection.checkbox('extensions')?.value() === true
}, '1fr');
row.addDropdown('serviceType', {
label: 'Service Type',
options: [
{ id: 'full-set', name: 'Full Set (New)' },
{ id: 'fill', name: 'Fill/Refill' },
{ id: 'overlay', name: 'Overlay (Natural Nails)' }
],
defaultValue: 'full-set',
isVisible: () => enhancementSection.checkbox('extensions')?.value() === true
}, '1fr');
});
enhancementSection.addRow(row => {
row.addDropdown('nailLength', {
label: 'Nail Length',
options: [
{ id: 'natural', name: 'Natural/Short' },
{ id: 'medium', name: 'Medium' },
{ id: 'long', name: 'Long' },
{ id: 'extra-long', name: 'Extra Long/Stiletto' }
],
defaultValue: 'medium',
isVisible: () => enhancementSection.checkbox('extensions')?.value() === true
}, '1fr');
row.addDropdown('nailShape', {
label: 'Nail Shape',
options: [
{ id: 'round', name: 'Round' },
{ id: 'square', name: 'Square' },
{ id: 'squoval', name: 'Squoval' },
{ id: 'oval', name: 'Oval' },
{ id: 'almond', name: 'Almond' },
{ id: 'coffin', name: 'Coffin/Ballerina' },
{ id: 'stiletto', name: 'Stiletto' }
],
defaultValue: 'squoval',
isVisible: () => enhancementSection.checkbox('extensions')?.value() === true
}, '1fr');
});
// Pedicure Options
const pedicureSection = form.addSubform('pedicureOptions', {
title: '๐ฆถ Pedicure Options',
isVisible: () => serviceSection.checkbox('pedicure')?.value() === true
});
pedicureSection.addRow(row => {
row.addDropdown('pedicureType', {
label: 'Pedicure Type',
options: [
{ id: 'basic', name: 'Basic Pedicure' },
{ id: 'spa', name: 'Spa Pedicure' },
{ id: 'gel', name: 'Gel Pedicure' },
{ id: 'deluxe', name: 'Deluxe/Luxury Pedicure' },
{ id: 'medical', name: 'Medical Pedicure' }
],
defaultValue: 'spa',
isRequired: true
}, '1fr');
});
// Nail Art Section
const artSection = form.addSubform('nailArt', { title: '๐จ Nail Art & Design' });
artSection.addRow(row => {
row.addCheckbox('nailArt', {
label: 'Add Nail Art',
defaultValue: false
}, '1fr');
});
artSection.addRow(row => {
row.addDropdown('artType', {
label: 'Art Type',
options: [
{ id: 'simple', name: 'Simple (dots, stripes, tips)' },
{ id: 'stamping', name: 'Stamping/Patterns' },
{ id: 'hand-painted', name: 'Hand-Painted Design' },
{ id: 'detailed', name: 'Detailed/Complex Art' },
{ id: '3d', name: '3D Nail Art' }
],
defaultValue: 'simple',
isVisible: () => artSection.checkbox('nailArt')?.value() === true
}, '1fr');
row.addDropdown('artNails', {
label: 'Number of Nails',
options: [
{ id: '2', name: '2 Accent Nails' },
{ id: '4', name: '4 Nails' },
{ id: '10', name: 'All 10 Nails' }
],
defaultValue: '2',
isVisible: () => artSection.checkbox('nailArt')?.value() === true
}, '1fr');
});
artSection.addRow(row => {
row.addCheckbox('gems', {
label: 'Add Gems/Rhinestones',
defaultValue: false
}, '1fr');
row.addCheckbox('chrome', {
label: 'Chrome/Mirror Effect',
defaultValue: false
}, '1fr');
});
artSection.addRow(row => {
row.addCheckbox('ombre', {
label: 'Ombre/Gradient',
defaultValue: false
}, '1fr');
row.addCheckbox('frenchTip', {
label: 'French Tip',
defaultValue: false
}, '1fr');
});
// Add-ons Section
const addonsSection = form.addSubform('addons', { title: 'โจ Additional Services' });
addonsSection.addRow(row => {
row.addCheckbox('nailRepair', {
label: 'Nail Repair (per nail)',
defaultValue: false
}, '1fr');
row.addInteger('repairCount', {
label: 'Number of Repairs',
defaultValue: 1,
min: 1,
max: 10,
isVisible: () => addonsSection.checkbox('nailRepair')?.value() === true
}, '1fr');
});
addonsSection.addRow(row => {
row.addCheckbox('soak', {
label: 'Gel/Acrylic Removal/Soak Off',
defaultValue: false
}, '1fr');
row.addCheckbox('cuticleOil', {
label: 'Cuticle Oil Treatment',
defaultValue: false
}, '1fr');
});
addonsSection.addRow(row => {
row.addCheckbox('paraffin', {
label: 'Paraffin Wax Treatment',
defaultValue: false
}, '1fr');
row.addCheckbox('massage', {
label: 'Extended Hand/Foot Massage',
defaultValue: false
}, '1fr');
});
addonsSection.addRow(row => {
row.addCheckbox('nailStrength', {
label: 'Nail Strengthening Treatment',
defaultValue: false
}, '1fr');
row.addCheckbox('callus', {
label: 'Callus Removal',
defaultValue: false,
isVisible: () => serviceSection.checkbox('pedicure')?.value() === true
}, '1fr');
});
// Technician Level Section
const techSection = form.addSubform('technician', { title: '๐ฉโ๐จ Technician Level' });
techSection.addRow(row => {
row.addRadioButton('techLevel', {
label: 'Select Technician',
options: [
{ id: 'junior', name: 'Junior Technician' },
{ id: 'senior', name: 'Senior Technician' },
{ id: 'master', name: 'Master Nail Artist' }
],
defaultValue: 'senior',
orientation: 'horizontal'
});
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Pricing Section
const pricingSection = form.addSubform('pricing', { title: '๐ฐ Pricing', isCollapsible: false });
const calculatePrice = () => {
const hasManicure = serviceSection.checkbox('manicure')?.value();
const hasPedicure = serviceSection.checkbox('pedicure')?.value();
const hasExtensions = enhancementSection.checkbox('extensions')?.value();
const hasNailArt = artSection.checkbox('nailArt')?.value();
const techLevel = techSection.radioButton('techLevel')?.value() || 'senior';
let manicurePrice = 0;
let pedicurePrice = 0;
let extensionPrice = 0;
let artPrice = 0;
let addonsPrice = 0;
// Manicure pricing
if (hasManicure) {
const manicureType = manicureSection.dropdown('manicureType')?.value() || 'basic';
const manicurePrices: Record<string, number> = {
'basic': 25,
'gel': 45,
'dip': 50,
'shellac': 40
};
manicurePrice = manicurePrices[manicureType] || 25;
}
// Extension pricing
if (hasExtensions) {
const extensionType = enhancementSection.dropdown('extensionType')?.value() || 'acrylic';
const serviceType = enhancementSection.dropdown('serviceType')?.value() || 'full-set';
const nailLength = enhancementSection.dropdown('nailLength')?.value() || 'medium';
const extensionBasePrices: Record<string, number> = {
'acrylic': 50,
'hard-gel': 60,
'polygel': 65,
'fiberglass': 70,
'press-on': 35
};
const serviceMult: Record<string, number> = {
'full-set': 1.0,
'fill': 0.6,
'overlay': 0.75
};
const lengthMult: Record<string, number> = {
'natural': 1.0,
'medium': 1.15,
'long': 1.35,
'extra-long': 1.6
};
extensionPrice = (extensionBasePrices[extensionType] || 50)
* (serviceMult[serviceType] || 1.0)
* (lengthMult[nailLength] || 1.0);
}
// Pedicure pricing
if (hasPedicure) {
const pedicureType = pedicureSection.dropdown('pedicureType')?.value() || 'spa';
const pedicurePrices: Record<string, number> = {
'basic': 30,
'spa': 45,
'gel': 55,
'deluxe': 65,
'medical': 75
};
pedicurePrice = pedicurePrices[pedicureType] || 45;
}
// Nail art pricing
if (hasNailArt) {
const artType = artSection.dropdown('artType')?.value() || 'simple';
const artNails = artSection.dropdown('artNails')?.value() || '2';
const artPerNail: Record<string, number> = {
'simple': 5,
'stamping': 7,
'hand-painted': 12,
'detailed': 18,
'3d': 25
};
const nailCount = parseInt(artNails) || 2;
artPrice = (artPerNail[artType] || 5) * nailCount;
}
// Art add-ons
if (artSection.checkbox('gems')?.value()) artPrice += 15;
if (artSection.checkbox('chrome')?.value()) artPrice += 20;
if (artSection.checkbox('ombre')?.value()) artPrice += 15;
if (artSection.checkbox('frenchTip')?.value()) artPrice += 10;
// Service add-ons
if (addonsSection.checkbox('nailRepair')?.value()) {
const repairCount = addonsSection.integer('repairCount')?.value() || 1;
addonsPrice += 8 * repairCount;
}
if (addonsSection.checkbox('soak')?.value()) addonsPrice += 15;
if (addonsSection.checkbox('cuticleOil')?.value()) addonsPrice += 8;
if (addonsSection.checkbox('paraffin')?.value()) addonsPrice += 15;
if (addonsSection.checkbox('massage')?.value()) addonsPrice += 12;
if (addonsSection.checkbox('nailStrength')?.value()) addonsPrice += 10;
if (addonsSection.checkbox('callus')?.value()) addonsPrice += 12;
// Sum before technician adjustment
let subtotal = manicurePrice + pedicurePrice + extensionPrice + artPrice;
// Technician level multiplier
const techMult: Record<string, number> = {
'junior': 0.85,
'senior': 1.0,
'master': 1.25
};
subtotal *= techMult[techLevel] || 1.0;
const total = subtotal + addonsPrice;
return {
manicurePrice: Math.round(manicurePrice * (techMult[techLevel] || 1.0)),
pedicurePrice: Math.round(pedicurePrice * (techMult[techLevel] || 1.0)),
extensionPrice: Math.round(extensionPrice * (techMult[techLevel] || 1.0)),
artPrice: Math.round(artPrice * (techMult[techLevel] || 1.0)),
addonsPrice: Math.round(addonsPrice),
total: Math.round(total)
};
};
pricingSection.addRow(row => {
row.addPriceDisplay('manicure', {
label: 'Manicure',
computedValue: () => calculatePrice().manicurePrice,
variant: 'default',
isVisible: () => calculatePrice().manicurePrice > 0
}, '1fr');
row.addPriceDisplay('pedicure', {
label: 'Pedicure',
computedValue: () => calculatePrice().pedicurePrice,
variant: 'default',
isVisible: () => calculatePrice().pedicurePrice > 0
}, '1fr');
});
pricingSection.addRow(row => {
row.addPriceDisplay('extensions', {
label: 'Nail Extensions',
computedValue: () => calculatePrice().extensionPrice,
variant: 'default',
isVisible: () => calculatePrice().extensionPrice > 0
}, '1fr');
row.addPriceDisplay('art', {
label: 'Nail Art & Design',
computedValue: () => calculatePrice().artPrice,
variant: 'default',
isVisible: () => calculatePrice().artPrice > 0
}, '1fr');
});
pricingSection.addRow(row => {
row.addPriceDisplay('addons', {
label: 'Additional Services',
computedValue: () => calculatePrice().addonsPrice,
variant: 'default',
isVisible: () => calculatePrice().addonsPrice > 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');
});
summarySection.addRow(row => {
row.addTextPanel('note', {
computedValue: () => 'Prices may vary based on nail condition and final design complexity. Please arrive with clean, polish-free nails for best results.',
customStyles: { 'font-size': '0.85rem', 'color': '#64748b', 'text-align': 'center' }
});
});
form.configureSubmitButton({
label: 'Book Appointment'
});
}