export function carDetailingCalculator(form: FormTs) {
// Base rates by vehicle size
const sizeRates: Record<string, number> = {
'compact': 80,
'sedan': 100,
'suv-small': 120,
'suv-large': 145,
'truck': 140,
'truck-xl': 165,
'van': 150,
'sports': 130,
'luxury': 180,
'exotic': 250
};
// Package multipliers
const packageMultipliers: Record<string, number> = {
'express': 0.6,
'basic': 1.0,
'standard': 1.5,
'premium': 2.2,
'ultimate': 3.0
};
// Condition multipliers
const conditionMultipliers: Record<string, number> = {
'excellent': 0.9,
'good': 1.0,
'fair': 1.15,
'poor': 1.35,
'severe': 1.6
};
// Helper functions
const getVehicleSize = () => vehicleSection.radioButton('vehicleSize')?.value() || 'sedan';
const getCondition = () => vehicleSection.radioButton('condition')?.value() || 'good';
const getServiceType = () => serviceSection.radioButton('serviceType')?.value() || 'full';
const isTruck = () => {
const size = getVehicleSize();
return size === 'truck' || size === 'truck-xl';
};
const isConvertible = () => vehicleSection.checkbox('isConvertible')?.value() === true;
const isMobile = () => locationSection.radioButton('location')?.value() === 'mobile';
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Auto Detailing Quote',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Vehicle Details Section
const vehicleSection = form.addSubform('vehicleDetails', { title: '🚗 Vehicle Information' });
vehicleSection.addRow(row => {
row.addRadioButton('vehicleSize', {
label: 'Vehicle Size',
options: [
{ id: 'compact', name: 'Compact (MINI, Civic, Corolla)' },
{ id: 'sedan', name: 'Sedan (Camry, Accord, Model 3)' },
{ id: 'suv-small', name: 'Small SUV (RAV4, CR-V, Tucson)' },
{ id: 'suv-large', name: 'Large SUV (Tahoe, Expedition, X5)' },
{ id: 'truck', name: 'Truck (F-150, Silverado, Tacoma)' },
{ id: 'truck-xl', name: 'XL Truck (F-250+, Dually, Crew Cab)' },
{ id: 'van', name: 'Van / Minivan' },
{ id: 'sports', name: 'Sports Car' },
{ id: 'luxury', name: 'Luxury Vehicle' },
{ id: 'exotic', name: 'Exotic / Supercar' }
],
defaultValue: 'sedan',
orientation: 'vertical',
isRequired: true
}, '1fr');
row.addRadioButton('condition', {
label: 'Current Condition',
options: [
{ id: 'excellent', name: 'Excellent (-10%)' },
{ id: 'good', name: 'Good (standard)' },
{ id: 'fair', name: 'Fair (+15%)' },
{ id: 'poor', name: 'Poor (+35%)' },
{ id: 'severe', name: 'Severe (+60%)' }
],
defaultValue: 'good',
orientation: 'vertical',
isRequired: true
}, '1fr');
});
vehicleSection.addRow(row => {
row.addCheckbox('isConvertible', {
label: 'Convertible / Soft Top (+$30)',
defaultValue: false
});
});
// Service Type Section
const serviceSection = form.addSubform('serviceType', { title: '🎯 Service Type' });
serviceSection.addRow(row => {
row.addRadioButton('serviceType', {
label: 'What do you need?',
options: [
{ id: 'exterior', name: 'Exterior Only' },
{ id: 'interior', name: 'Interior Only' },
{ id: 'full', name: 'Full Detail (Interior + Exterior)' }
],
defaultValue: 'full',
orientation: 'horizontal',
isRequired: true
});
});
// Package Selection
const packageSection = form.addSubform('packageSelection', { title: '📦 Select Package' });
packageSection.addRow(row => {
row.addRadioButton('package', {
label: 'Detailing Package',
options: [
{ id: 'express', name: 'Express - Quick wash & vacuum (40% off base)' },
{ id: 'basic', name: 'Basic - Wash, vacuum, windows, tire shine' },
{ id: 'standard', name: 'Standard - Basic + interior wipe-down, dash treatment' },
{ id: 'premium', name: 'Premium - Standard + clay bar, wax, deep interior clean' },
{ id: 'ultimate', name: 'Ultimate - Premium + paint correction, ceramic coating' }
],
defaultValue: 'standard',
orientation: 'vertical',
isRequired: true
});
});
// Exterior Add-ons Section
const exteriorSection = form.addSubform('exteriorAddons', {
title: '✨ Exterior Add-ons',
isVisible: () => getServiceType() !== 'interior'
});
exteriorSection.addRow(row => {
row.addCheckboxList('paintAddons', {
label: 'Paint Care',
options: [
{ id: 'clayBar', name: 'Clay Bar Treatment (+$50)' },
{ id: 'polish', name: 'Paint Polish (+$75)' },
{ id: 'wax', name: 'Hand Wax (+$40)' },
{ id: 'sealant', name: 'Paint Sealant (+$60)' },
{ id: 'ceramic', name: 'Ceramic Spray Coating (+$100)' },
{ id: 'ceramicFull', name: 'Full Ceramic Coating (+$300)' }
],
defaultValue: [],
orientation: 'vertical'
}, '1fr');
row.addCheckboxList('exteriorExtras', {
label: 'Exterior Extras',
options: [
{ id: 'headlights', name: 'Headlight Restoration (+$45)' },
{ id: 'trim', name: 'Trim Restoration (+$35)' },
{ id: 'wheels', name: 'Wheel Detail & Coating (+$50)' },
{ id: 'glass', name: 'Glass Treatment (+$25)' },
{ id: 'engine', name: 'Engine Bay Cleaning (+$60)' }
],
defaultValue: [],
orientation: 'vertical'
}, '1fr');
});
// Truck-specific add-ons
const truckSection = form.addSubform('truckAddons', {
title: '🛻 Truck Add-ons',
isVisible: isTruck
});
truckSection.addRow(row => {
row.addCheckboxList('truckExtras', {
label: 'Truck-Specific Services',
options: [
{ id: 'bedClean', name: 'Truck Bed Cleaning (+$40)' },
{ id: 'bedLiner', name: 'Bed Liner Treatment (+$50)' },
{ id: 'bedCover', name: 'Tonneau Cover Clean (+$25)' },
{ id: 'undercarriage', name: 'Undercarriage Wash (+$35)' }
],
defaultValue: [],
orientation: 'vertical'
});
});
// Interior Add-ons Section
const interiorSection = form.addSubform('interiorAddons', {
title: '🪑 Interior Add-ons',
isVisible: () => getServiceType() !== 'exterior'
});
interiorSection.addRow(row => {
row.addCheckboxList('surfaceAddons', {
label: 'Surfaces',
options: [
{ id: 'leather', name: 'Leather Conditioning (+$35)' },
{ id: 'fabric', name: 'Fabric Protection (+$40)' },
{ id: 'carpet', name: 'Carpet Shampoo (+$55)' },
{ id: 'upholstery', name: 'Upholstery Shampoo (+$50)' },
{ id: 'steam', name: 'Steam Cleaning (+$60)' }
],
defaultValue: [],
orientation: 'vertical'
}, '1fr');
row.addCheckboxList('specialAddons', {
label: 'Special Treatments',
options: [
{ id: 'odor', name: 'Odor Removal (+$50)' },
{ id: 'ozone', name: 'Ozone Treatment (+$75)' },
{ id: 'petHair', name: 'Pet Hair Removal (+$40)' },
{ id: 'sanitize', name: 'Antibacterial Treatment (+$35)' },
{ id: 'kidMess', name: 'Heavy Kid Mess Clean (+$45)' }
],
defaultValue: [],
orientation: 'vertical'
}, '1fr');
});
// Location & Scheduling
const locationSection = form.addSubform('location', { title: '📍 Service Location' });
locationSection.addRow(row => {
row.addRadioButton('location', {
label: 'Where should we detail your vehicle?',
options: [
{ id: 'shop', name: 'At Our Shop' },
{ id: 'mobile', name: 'Mobile Service (we come to you) +$25' }
],
defaultValue: 'shop',
orientation: 'horizontal'
}, '1fr');
row.addDatepicker('preferredDate', {
label: 'Preferred Date',
minDate: new Date().toISOString().split('T')[0]
}, '1fr');
});
locationSection.addRow(row => {
row.addTextbox('address', {
label: 'Service Address',
placeholder: 'Enter your address for mobile service...',
isVisible: isMobile,
isRequired: isMobile
}, '1fr');
row.addRadioButton('timeSlot', {
label: 'Preferred Time',
options: [
{ id: 'morning', name: 'Morning (8am-12pm)' },
{ id: 'afternoon', name: 'Afternoon (12pm-5pm)' },
{ id: 'flexible', name: 'Flexible' }
],
defaultValue: 'flexible',
orientation: 'horizontal'
}, '1fr');
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Price Calculations
const calculateBasePrice = () => {
const size = getVehicleSize();
const pkg = packageSection.radioButton('package')?.value() || 'standard';
const condition = getCondition();
const serviceType = getServiceType();
const baseRate = sizeRates[size] || 100;
const pkgMult = packageMultipliers[pkg] || 1.5;
const condMult = conditionMultipliers[condition] || 1.0;
let price = baseRate * pkgMult * condMult;
// Adjust for service type
if (serviceType === 'exterior' || serviceType === 'interior') {
price *= 0.65; // 35% discount for single service
}
// Convertible surcharge
if (isConvertible()) {
price += 30;
}
return price;
};
const calculateExteriorAddons = () => {
if (getServiceType() === 'interior') return 0;
let total = 0;
const paintAddons = exteriorSection.checkboxList('paintAddons')?.value() || [];
const exteriorExtras = exteriorSection.checkboxList('exteriorExtras')?.value() || [];
if (paintAddons.includes('clayBar')) total += 50;
if (paintAddons.includes('polish')) total += 75;
if (paintAddons.includes('wax')) total += 40;
if (paintAddons.includes('sealant')) total += 60;
if (paintAddons.includes('ceramic')) total += 100;
if (paintAddons.includes('ceramicFull')) total += 300;
if (exteriorExtras.includes('headlights')) total += 45;
if (exteriorExtras.includes('trim')) total += 35;
if (exteriorExtras.includes('wheels')) total += 50;
if (exteriorExtras.includes('glass')) total += 25;
if (exteriorExtras.includes('engine')) total += 60;
return total;
};
const calculateTruckAddons = () => {
if (!isTruck()) return 0;
let total = 0;
const truckExtras = truckSection.checkboxList('truckExtras')?.value() || [];
if (truckExtras.includes('bedClean')) total += 40;
if (truckExtras.includes('bedLiner')) total += 50;
if (truckExtras.includes('bedCover')) total += 25;
if (truckExtras.includes('undercarriage')) total += 35;
return total;
};
const calculateInteriorAddons = () => {
if (getServiceType() === 'exterior') return 0;
let total = 0;
const surfaceAddons = interiorSection.checkboxList('surfaceAddons')?.value() || [];
const specialAddons = interiorSection.checkboxList('specialAddons')?.value() || [];
if (surfaceAddons.includes('leather')) total += 35;
if (surfaceAddons.includes('fabric')) total += 40;
if (surfaceAddons.includes('carpet')) total += 55;
if (surfaceAddons.includes('upholstery')) total += 50;
if (surfaceAddons.includes('steam')) total += 60;
if (specialAddons.includes('odor')) total += 50;
if (specialAddons.includes('ozone')) total += 75;
if (specialAddons.includes('petHair')) total += 40;
if (specialAddons.includes('sanitize')) total += 35;
if (specialAddons.includes('kidMess')) total += 45;
return total;
};
const getMobileFee = () => isMobile() ? 25 : 0;
// Summary Section
const summarySection = form.addSubform('summary', { title: '💰 Your Quote' });
summarySection.addRow(row => {
row.addPriceDisplay('basePrice', {
label: 'Package Price',
computedValue: () => Math.round(calculateBasePrice()),
variant: 'default'
}, '1fr');
row.addPriceDisplay('exteriorAddons', {
label: 'Exterior Add-ons',
computedValue: () => calculateExteriorAddons(),
variant: 'default',
prefix: '+',
isVisible: () => calculateExteriorAddons() > 0
}, '1fr');
});
summarySection.addRow(row => {
row.addPriceDisplay('interiorAddons', {
label: 'Interior Add-ons',
computedValue: () => calculateInteriorAddons(),
variant: 'default',
prefix: '+',
isVisible: () => calculateInteriorAddons() > 0
}, '1fr');
row.addPriceDisplay('truckAddons', {
label: 'Truck Add-ons',
computedValue: () => calculateTruckAddons(),
variant: 'default',
prefix: '+',
isVisible: () => calculateTruckAddons() > 0
}, '1fr');
});
summarySection.addRow(row => {
row.addPriceDisplay('mobileFee', {
label: 'Mobile Service Fee',
computedValue: () => getMobileFee(),
variant: 'default',
prefix: '+',
isVisible: isMobile
}, '1fr');
});
summarySection.addSpacer({ showLine: true, lineStyle: 'solid', lineColor: '#e2e8f0' });
summarySection.addRow(row => {
row.addPriceDisplay('totalPrice', {
label: 'Total Quote',
computedValue: () => {
const base = calculateBasePrice();
const exterior = calculateExteriorAddons();
const interior = calculateInteriorAddons();
const truck = calculateTruckAddons();
const mobile = getMobileFee();
return Math.round(base + exterior + interior + truck + mobile);
},
variant: 'large'
}, '1fr');
row.addTextPanel('timeEstimate', {
computedValue: () => {
const pkg = packageSection.radioButton('package')?.value() || 'standard';
const times: Record<string, string> = {
'express': '45 min - 1 hr',
'basic': '1-2 hours',
'standard': '2-3 hours',
'premium': '4-5 hours',
'ultimate': '6-8 hours'
};
return `⏱️ Est. ${times[pkg] || '2-3 hours'}`;
},
customStyles: { 'font-size': '1rem', 'color': '#059669', 'font-weight': '500' }
}, '1fr');
});
summarySection.addRow(row => {
row.addTextPanel('disclaimer', {
computedValue: () => 'Final price confirmed upon vehicle inspection. Ceramic coating requires paint assessment.',
customStyles: { 'font-size': '0.85rem', 'color': '#64748b', 'font-style': 'italic', 'text-align': 'center' }
});
});
form.configureSubmitButton({
label: 'Book Appointment'
});
}