export function bikeRepairCalculator(form: FormTs) {
// Service prices by category
const servicePrices: Record<string, number> = {
// Tune-ups
'basic-tune': 45,
'standard-tune': 85,
'full-overhaul': 175,
// Brakes
'brake-adjust': 15,
'brake-pads': 25,
'brake-cable': 20,
'hydraulic-bleed': 45,
'disc-brake-install': 75,
// Drivetrain
'derailleur-adjust': 20,
'cable-replace': 25,
'chain-replace': 25,
'cassette-replace': 35,
'chainring-replace': 30,
'bottom-bracket': 55,
// Wheels
'flat-repair': 15,
'tube-replace': 20,
'tire-replace': 25,
'wheel-true': 25,
'spoke-replace': 15,
'hub-service': 45,
// Other
'headset-adjust': 20,
'headset-replace': 55,
'fork-service': 85,
'suspension-service': 125
};
// Bike type multipliers
const bikeMultipliers: Record<string, number> = {
'standard': 1,
'road': 1.1,
'mountain': 1.2,
'ebike': 1.4,
'carbon': 1.3
};
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Bike Repair Cost Calculator',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Bike Information Section
const bikeSection = form.addSubform('bikeInfo', { title: '๐ฒ Your Bike' });
bikeSection.addRow(row => {
row.addDropdown('bikeType', {
label: 'Bike Type',
options: [
{ id: 'standard', name: 'Standard/Commuter' },
{ id: 'road', name: 'Road Bike (+10%)' },
{ id: 'mountain', name: 'Mountain Bike (+20%)' },
{ id: 'ebike', name: 'E-Bike (+40%)' },
{ id: 'carbon', name: 'Carbon Frame (+30%)' }
],
defaultValue: 'standard',
isRequired: true,
tooltip: 'Specialty bikes may require more time and expertise'
}, '1fr');
row.addDropdown('bikeCondition', {
label: 'Current Condition',
options: [
{ id: 'good', name: 'Good (regular maintenance)' },
{ id: 'fair', name: 'Fair (some issues)' },
{ id: 'poor', name: 'Poor (neglected)' },
{ id: 'unknown', name: 'Unknown/Needs inspection' }
],
defaultValue: 'fair'
}, '1fr');
});
// Tune-up Services
const tuneupSection = form.addSubform('tuneup', { title: '๐ง Tune-up Services' });
tuneupSection.addRow(row => {
row.addRadioButton('tuneupLevel', {
label: 'Tune-up Package',
options: [
{ id: 'none', name: 'No tune-up (individual services only)' },
{ id: 'basic-tune', name: 'Basic Tune ($45) - Safety check, lubrication, adjustments' },
{ id: 'standard-tune', name: 'Standard Tune ($85) - Basic + brake/derailleur service' },
{ id: 'full-overhaul', name: 'Full Overhaul ($175) - Complete disassembly and rebuild' }
],
defaultValue: 'none',
orientation: 'vertical'
});
});
// Brake Services
const brakeSection = form.addSubform('brakes', { title: '๐ Brake Services' });
brakeSection.addRow(row => {
row.addCheckbox('brakeAdjust', {
label: 'Brake Adjustment ($15)',
defaultValue: false
}, '1fr');
row.addCheckbox('brakePads', {
label: 'Brake Pad Replacement ($25)',
defaultValue: false,
tooltip: 'Parts not included'
}, '1fr');
});
brakeSection.addRow(row => {
row.addCheckbox('brakeCable', {
label: 'Brake Cable Replacement ($20)',
defaultValue: false
}, '1fr');
row.addCheckbox('hydraulicBleed', {
label: 'Hydraulic Brake Bleed ($45)',
defaultValue: false,
tooltip: 'For disc brake systems'
}, '1fr');
});
// Drivetrain Services
const drivetrainSection = form.addSubform('drivetrain', { title: 'โ๏ธ Drivetrain Services' });
drivetrainSection.addRow(row => {
row.addCheckbox('derailleurAdjust', {
label: 'Derailleur Adjustment ($20)',
defaultValue: false
}, '1fr');
row.addCheckbox('cableReplace', {
label: 'Shift Cable Replacement ($25)',
defaultValue: false
}, '1fr');
});
drivetrainSection.addRow(row => {
row.addCheckbox('chainReplace', {
label: 'Chain Replacement ($25)',
defaultValue: false,
tooltip: 'Parts not included'
}, '1fr');
row.addCheckbox('cassetteReplace', {
label: 'Cassette Replacement ($35)',
defaultValue: false,
tooltip: 'Parts not included'
}, '1fr');
});
drivetrainSection.addRow(row => {
row.addCheckbox('chainringReplace', {
label: 'Chainring Replacement ($30)',
defaultValue: false
}, '1fr');
row.addCheckbox('bottomBracket', {
label: 'Bottom Bracket Service ($55)',
defaultValue: false
}, '1fr');
});
// Wheel Services
const wheelSection = form.addSubform('wheels', { title: '๐ Wheel Services' });
wheelSection.addRow(row => {
row.addCheckbox('flatRepair', {
label: 'Flat Repair ($15)',
defaultValue: false
}, '1fr');
row.addCheckbox('tubeReplace', {
label: 'Tube Replacement ($20)',
defaultValue: false,
tooltip: 'Parts not included'
}, '1fr');
});
wheelSection.addRow(row => {
row.addCheckbox('tireReplace', {
label: 'Tire Installation ($25)',
defaultValue: false,
tooltip: 'Parts not included'
}, '1fr');
row.addCheckbox('wheelTrue', {
label: 'Wheel Truing ($25)',
defaultValue: false
}, '1fr');
});
wheelSection.addRow(row => {
row.addCheckbox('spokeReplace', {
label: 'Spoke Replacement ($15/spoke)',
defaultValue: false
}, '1fr');
row.addCheckbox('hubService', {
label: 'Hub Service ($45)',
defaultValue: false,
tooltip: 'Clean, repack bearings, adjust'
}, '1fr');
});
wheelSection.addRow(row => {
row.addInteger('spokeCount', {
label: 'Number of Spokes',
min: 1,
max: 10,
defaultValue: 1,
isVisible: () => wheelSection.checkbox('spokeReplace')?.value() === true
}, '1fr');
row.addInteger('wheelCount', {
label: 'Number of Wheels',
min: 1,
max: 2,
defaultValue: 1,
tooltip: 'Select 2 for both wheels',
isVisible: () =>
wheelSection.checkbox('flatRepair')?.value() ||
wheelSection.checkbox('tubeReplace')?.value() ||
wheelSection.checkbox('tireReplace')?.value() ||
wheelSection.checkbox('wheelTrue')?.value() ||
wheelSection.checkbox('hubService')?.value()
}, '1fr');
});
// Other Services
const otherSection = form.addSubform('other', { title: 'โจ Other Services' });
otherSection.addRow(row => {
row.addCheckbox('headsetAdjust', {
label: 'Headset Adjustment ($20)',
defaultValue: false
}, '1fr');
row.addCheckbox('headsetReplace', {
label: 'Headset Replacement ($55)',
defaultValue: false
}, '1fr');
});
otherSection.addRow(row => {
row.addCheckbox('forkService', {
label: 'Fork Service ($85)',
defaultValue: false,
tooltip: 'For suspension forks',
isVisible: () => bikeSection.dropdown('bikeType')?.value() === 'mountain'
}, '1fr');
row.addCheckbox('suspensionService', {
label: 'Full Suspension Service ($125)',
defaultValue: false,
tooltip: 'Fork and rear shock',
isVisible: () => bikeSection.dropdown('bikeType')?.value() === 'mountain'
}, '1fr');
});
otherSection.addRow(row => {
row.addCheckbox('cleanLube', {
label: 'Deep Clean & Lube ($35)',
defaultValue: false
}, '1fr');
row.addCheckbox('safetyInspection', {
label: 'Safety Inspection ($15)',
defaultValue: false,
tooltip: 'Comprehensive safety check'
}, '1fr');
});
// Additional Options
const optionsSection = form.addSubform('options', { title: '๐ Additional Options' });
optionsSection.addRow(row => {
row.addCheckbox('rushService', {
label: 'Rush Service (+50%)',
defaultValue: false,
tooltip: 'Same-day or next-day completion'
}, '1fr');
row.addCheckbox('pickup', {
label: 'Bike Pickup/Delivery (+$25)',
defaultValue: false,
tooltip: 'We pick up and deliver your bike'
}, '1fr');
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Price Summary Section
const summarySection = form.addSubform('summary', { title: '๐ฐ Repair Estimate', isCollapsible: false });
summarySection.addRow(row => {
row.addPriceDisplay('tuneupPrice', {
label: 'Tune-up Package',
computedValue: () => {
const tuneup = tuneupSection.radioButton('tuneupLevel')?.value() || 'none';
if (tuneup === 'none') return 0;
return servicePrices[tuneup] || 0;
},
variant: 'default'
}, '1fr');
row.addPriceDisplay('servicesPrice', {
label: 'Individual Services',
computedValue: () => {
let total = 0;
const wheelCount = wheelSection.integer('wheelCount')?.value() || 1;
const spokeCount = wheelSection.integer('spokeCount')?.value() || 1;
// Brakes
if (brakeSection.checkbox('brakeAdjust')?.value()) total += (servicePrices['brake-adjust'] || 0);
if (brakeSection.checkbox('brakePads')?.value()) total += (servicePrices['brake-pads'] || 0);
if (brakeSection.checkbox('brakeCable')?.value()) total += (servicePrices['brake-cable'] || 0);
if (brakeSection.checkbox('hydraulicBleed')?.value()) total += (servicePrices['hydraulic-bleed'] || 0);
// Drivetrain
if (drivetrainSection.checkbox('derailleurAdjust')?.value()) total += (servicePrices['derailleur-adjust'] || 0);
if (drivetrainSection.checkbox('cableReplace')?.value()) total += (servicePrices['cable-replace'] || 0);
if (drivetrainSection.checkbox('chainReplace')?.value()) total += (servicePrices['chain-replace'] || 0);
if (drivetrainSection.checkbox('cassetteReplace')?.value()) total += (servicePrices['cassette-replace'] || 0);
if (drivetrainSection.checkbox('chainringReplace')?.value()) total += (servicePrices['chainring-replace'] || 0);
if (drivetrainSection.checkbox('bottomBracket')?.value()) total += (servicePrices['bottom-bracket'] || 0);
// Wheels (multiplied by wheel count where applicable)
if (wheelSection.checkbox('flatRepair')?.value()) total += (servicePrices['flat-repair'] || 0) * wheelCount;
if (wheelSection.checkbox('tubeReplace')?.value()) total += (servicePrices['tube-replace'] || 0) * wheelCount;
if (wheelSection.checkbox('tireReplace')?.value()) total += (servicePrices['tire-replace'] || 0) * wheelCount;
if (wheelSection.checkbox('wheelTrue')?.value()) total += (servicePrices['wheel-true'] || 0) * wheelCount;
if (wheelSection.checkbox('hubService')?.value()) total += (servicePrices['hub-service'] || 0) * wheelCount;
if (wheelSection.checkbox('spokeReplace')?.value()) total += (servicePrices['spoke-replace'] || 0) * spokeCount;
// Other
if (otherSection.checkbox('headsetAdjust')?.value()) total += (servicePrices['headset-adjust'] || 0);
if (otherSection.checkbox('headsetReplace')?.value()) total += (servicePrices['headset-replace'] || 0);
if (otherSection.checkbox('forkService')?.value()) total += (servicePrices['fork-service'] || 0);
if (otherSection.checkbox('suspensionService')?.value()) total += (servicePrices['suspension-service'] || 0);
if (otherSection.checkbox('cleanLube')?.value()) total += 35;
if (otherSection.checkbox('safetyInspection')?.value()) total += 15;
return total;
},
variant: 'default',
prefix: '+'
}, '1fr');
});
summarySection.addRow(row => {
row.addPriceDisplay('bikeTypeAdjustment', {
label: 'Bike Type Adjustment',
computedValue: () => {
const bikeType = bikeSection.dropdown('bikeType')?.value() || 'standard';
const multiplier = bikeMultipliers[bikeType] || 1;
if (multiplier === 1) return 0;
// Calculate base services total
const tuneup = tuneupSection.radioButton('tuneupLevel')?.value() || 'none';
let baseTotal = tuneup !== 'none' ? servicePrices[tuneup] || 0 : 0;
const wheelCount = wheelSection.integer('wheelCount')?.value() || 1;
const spokeCount = wheelSection.integer('spokeCount')?.value() || 1;
if (brakeSection.checkbox('brakeAdjust')?.value()) baseTotal += (servicePrices['brake-adjust'] || 0);
if (brakeSection.checkbox('brakePads')?.value()) baseTotal += (servicePrices['brake-pads'] || 0);
if (brakeSection.checkbox('brakeCable')?.value()) baseTotal += (servicePrices['brake-cable'] || 0);
if (brakeSection.checkbox('hydraulicBleed')?.value()) baseTotal += (servicePrices['hydraulic-bleed'] || 0);
if (drivetrainSection.checkbox('derailleurAdjust')?.value()) baseTotal += (servicePrices['derailleur-adjust'] || 0);
if (drivetrainSection.checkbox('cableReplace')?.value()) baseTotal += (servicePrices['cable-replace'] || 0);
if (drivetrainSection.checkbox('chainReplace')?.value()) baseTotal += (servicePrices['chain-replace'] || 0);
if (drivetrainSection.checkbox('cassetteReplace')?.value()) baseTotal += (servicePrices['cassette-replace'] || 0);
if (drivetrainSection.checkbox('chainringReplace')?.value()) baseTotal += (servicePrices['chainring-replace'] || 0);
if (drivetrainSection.checkbox('bottomBracket')?.value()) baseTotal += (servicePrices['bottom-bracket'] || 0);
if (wheelSection.checkbox('flatRepair')?.value()) baseTotal += (servicePrices['flat-repair'] || 0) * wheelCount;
if (wheelSection.checkbox('tubeReplace')?.value()) baseTotal += (servicePrices['tube-replace'] || 0) * wheelCount;
if (wheelSection.checkbox('tireReplace')?.value()) baseTotal += (servicePrices['tire-replace'] || 0) * wheelCount;
if (wheelSection.checkbox('wheelTrue')?.value()) baseTotal += (servicePrices['wheel-true'] || 0) * wheelCount;
if (wheelSection.checkbox('hubService')?.value()) baseTotal += (servicePrices['hub-service'] || 0) * wheelCount;
if (wheelSection.checkbox('spokeReplace')?.value()) baseTotal += (servicePrices['spoke-replace'] || 0) * spokeCount;
if (otherSection.checkbox('headsetAdjust')?.value()) baseTotal += (servicePrices['headset-adjust'] || 0);
if (otherSection.checkbox('headsetReplace')?.value()) baseTotal += (servicePrices['headset-replace'] || 0);
if (otherSection.checkbox('forkService')?.value()) baseTotal += (servicePrices['fork-service'] || 0);
if (otherSection.checkbox('suspensionService')?.value()) baseTotal += (servicePrices['suspension-service'] || 0);
if (otherSection.checkbox('cleanLube')?.value()) baseTotal += 35;
if (otherSection.checkbox('safetyInspection')?.value()) baseTotal += 15;
return Math.round(baseTotal * (multiplier - 1));
},
variant: 'default',
prefix: '+'
}, '1fr');
row.addPriceDisplay('extras', {
label: 'Additional Options',
computedValue: () => {
let total = 0;
if (optionsSection.checkbox('pickup')?.value()) total += 25;
return total;
},
variant: 'default',
prefix: '+'
}, '1fr');
});
const finalSection = form.addSubform('final', {
title: '๐งพ Summary',
isCollapsible: false,
sticky: 'bottom'
});
finalSection.addRow(row => {
row.addPriceDisplay('totalPrice', {
label: 'Total Estimate',
computedValue: () => {
const bikeType = bikeSection.dropdown('bikeType')?.value() || 'standard';
const multiplier = bikeMultipliers[bikeType] || 1;
const wheelCount = wheelSection.integer('wheelCount')?.value() || 1;
const spokeCount = wheelSection.integer('spokeCount')?.value() || 1;
// Tune-up
const tuneup = tuneupSection.radioButton('tuneupLevel')?.value() || 'none';
let total = tuneup !== 'none' ? servicePrices[tuneup] || 0 : 0;
// Individual services
if (brakeSection.checkbox('brakeAdjust')?.value()) total += (servicePrices['brake-adjust'] || 0);
if (brakeSection.checkbox('brakePads')?.value()) total += (servicePrices['brake-pads'] || 0);
if (brakeSection.checkbox('brakeCable')?.value()) total += (servicePrices['brake-cable'] || 0);
if (brakeSection.checkbox('hydraulicBleed')?.value()) total += (servicePrices['hydraulic-bleed'] || 0);
if (drivetrainSection.checkbox('derailleurAdjust')?.value()) total += (servicePrices['derailleur-adjust'] || 0);
if (drivetrainSection.checkbox('cableReplace')?.value()) total += (servicePrices['cable-replace'] || 0);
if (drivetrainSection.checkbox('chainReplace')?.value()) total += (servicePrices['chain-replace'] || 0);
if (drivetrainSection.checkbox('cassetteReplace')?.value()) total += (servicePrices['cassette-replace'] || 0);
if (drivetrainSection.checkbox('chainringReplace')?.value()) total += (servicePrices['chainring-replace'] || 0);
if (drivetrainSection.checkbox('bottomBracket')?.value()) total += (servicePrices['bottom-bracket'] || 0);
if (wheelSection.checkbox('flatRepair')?.value()) total += (servicePrices['flat-repair'] || 0) * wheelCount;
if (wheelSection.checkbox('tubeReplace')?.value()) total += (servicePrices['tube-replace'] || 0) * wheelCount;
if (wheelSection.checkbox('tireReplace')?.value()) total += (servicePrices['tire-replace'] || 0) * wheelCount;
if (wheelSection.checkbox('wheelTrue')?.value()) total += (servicePrices['wheel-true'] || 0) * wheelCount;
if (wheelSection.checkbox('hubService')?.value()) total += (servicePrices['hub-service'] || 0) * wheelCount;
if (wheelSection.checkbox('spokeReplace')?.value()) total += (servicePrices['spoke-replace'] || 0) * spokeCount;
if (otherSection.checkbox('headsetAdjust')?.value()) total += (servicePrices['headset-adjust'] || 0);
if (otherSection.checkbox('headsetReplace')?.value()) total += (servicePrices['headset-replace'] || 0);
if (otherSection.checkbox('forkService')?.value()) total += (servicePrices['fork-service'] || 0);
if (otherSection.checkbox('suspensionService')?.value()) total += (servicePrices['suspension-service'] || 0);
if (otherSection.checkbox('cleanLube')?.value()) total += 35;
if (otherSection.checkbox('safetyInspection')?.value()) total += 15;
// Bike type multiplier
total *= multiplier;
// Rush service
if (optionsSection.checkbox('rushService')?.value()) total *= 1.5;
// Pickup/delivery
if (optionsSection.checkbox('pickup')?.value()) total += 25;
return Math.round(total);
},
variant: 'large'
}, '1fr');
});
finalSection.addRow(row => {
row.addTextPanel('disclaimer', {
computedValue: () => 'Labor only - parts priced separately. Free estimate on drop-off. 30-day warranty on all repairs.',
customStyles: { 'font-size': '0.85rem', 'color': '#64748b', 'font-style': 'italic' }
});
});
form.configureSubmitButton({
label: 'Book Service'
});
}