export function storageUnitRentalCalculator(form: FormTs) {
// Base monthly rates by unit size
const unitSizeRates: Record<string, number> = {
'5x5': 45,
'5x10': 75,
'10x10': 120,
'10x15': 160,
'10x20': 200,
'10x25': 250,
'10x30': 300
};
// Climate control premium
const climateControlPremium = 1.35;
// Location multipliers
const locationMultipliers: Record<string, number> = {
'urban': 1.3,
'suburban': 1.0,
'rural': 0.85
};
// Floor level discounts/premiums
const floorAdjustments: Record<string, number> = {
'ground': 1.1,
'upper': 0.95,
'basement': 0.90
};
form.addRow(row => {
row.addTextPanel('header', {
computedValue: () => 'Storage Unit Rental Estimate',
customStyles: { 'font-size': '1.5rem', 'font-weight': '600', 'color': '#1e293b' }
});
});
form.addSpacer({ height: 20 });
// Unit Selection Section
const unitSection = form.addSubform('unitSelection', { title: '📦 Unit Selection' });
unitSection.addRow(row => {
row.addRadioButton('unitSize', {
label: 'Unit Size',
options: [
{ id: '5x5', name: '5x5 (25 sq ft) - Small closet' },
{ id: '5x10', name: '5x10 (50 sq ft) - Walk-in closet' },
{ id: '10x10', name: '10x10 (100 sq ft) - Half garage' },
{ id: '10x15', name: '10x15 (150 sq ft) - Large bedroom' },
{ id: '10x20', name: '10x20 (200 sq ft) - One-car garage' },
{ id: '10x25', name: '10x25 (250 sq ft) - Large garage' },
{ id: '10x30', name: '10x30 (300 sq ft) - Two-car garage' }
],
defaultValue: '10x10',
orientation: 'vertical',
isRequired: true
});
});
unitSection.addRow(row => {
row.addDropdown('location', {
label: 'Facility Location',
options: [
{ id: 'urban', name: 'Urban/Downtown (+30%)' },
{ id: 'suburban', name: 'Suburban (Standard)' },
{ id: 'rural', name: 'Rural (-15%)' }
],
defaultValue: 'suburban',
isRequired: true
}, '1fr');
row.addDropdown('floorLevel', {
label: 'Floor Level',
options: [
{ id: 'ground', name: 'Ground Floor (+10%)' },
{ id: 'upper', name: 'Upper Floor (-5%)' },
{ id: 'basement', name: 'Basement Level (-10%)' }
],
defaultValue: 'ground',
isRequired: true
}, '1fr');
});
// Features Section
const featuresSection = form.addSubform('features', { title: '🌡️ Unit Features' });
featuresSection.addRow(row => {
row.addCheckbox('climateControl', {
label: 'Climate Controlled (+35%)',
defaultValue: false
}, '1fr');
row.addCheckbox('driveUp', {
label: 'Drive-Up Access (+$15/mo)',
defaultValue: false
}, '1fr');
});
featuresSection.addRow(row => {
row.addCheckbox('electricity', {
label: 'Electrical Outlet (+$25/mo)',
defaultValue: false
}, '1fr');
row.addCheckbox('twentyFourHour', {
label: '24/7 Access (+$20/mo)',
defaultValue: true
}, '1fr');
});
// Rental Duration Section
const durationSection = form.addSubform('duration', { title: '📅 Rental Duration' });
durationSection.addRow(row => {
row.addRadioButton('rentalTerm', {
label: 'Rental Term',
options: [
{ id: 'monthly', name: 'Month-to-Month' },
{ id: '3-month', name: '3 Months (-5%)' },
{ id: '6-month', name: '6 Months (-10%)' },
{ id: '12-month', name: '12 Months (-15%)' }
],
defaultValue: 'monthly',
orientation: 'vertical',
isRequired: true
});
});
durationSection.addRow(row => {
row.addCheckbox('firstMonthFree', {
label: 'First Month Free Promo (if available)',
defaultValue: false
});
});
// Additional Services Section
const servicesSection = form.addSubform('services', { title: '✨ Additional Services' });
servicesSection.addRow(row => {
row.addCheckbox('insurance', {
label: 'Storage Insurance ($15/mo for $5,000 coverage)',
defaultValue: true
}, '1fr');
row.addCheckbox('locks', {
label: 'Heavy-Duty Lock ($20 one-time)',
defaultValue: false
}, '1fr');
});
servicesSection.addRow(row => {
row.addCheckbox('movingSupplies', {
label: 'Moving Supplies Kit ($50 one-time)',
defaultValue: false
}, '1fr');
row.addCheckbox('packingHelp', {
label: 'Packing Assistance ($75/hour)',
defaultValue: false
}, '1fr');
});
servicesSection.addRow(row => {
row.addInteger('packingHours', {
label: 'Packing Hours Needed',
min: 1,
max: 8,
defaultValue: 2,
isVisible: () => servicesSection.checkbox('packingHelp')?.value() === true
}, '1fr');
});
form.addSpacer({ height: 20, showLine: true, lineStyle: 'dashed' });
// Price Summary Section
const summarySection = form.addSubform('summary', { title: '💰 Cost Breakdown', isCollapsible: false });
summarySection.addRow(row => {
row.addPriceDisplay('baseRent', {
label: 'Base Monthly Rent',
computedValue: () => {
const unitSize = unitSection.radioButton('unitSize')?.value() || '10x10';
const location = unitSection.dropdown('location')?.value() || 'suburban';
const floorLevel = unitSection.dropdown('floorLevel')?.value() || 'ground';
const climateControl = featuresSection.checkbox('climateControl')?.value() || false;
let rate = unitSizeRates[unitSize] || 120;
rate *= locationMultipliers[location] || 1.0;
rate *= floorAdjustments[floorLevel] || 1.0;
if (climateControl) rate *= climateControlPremium;
return Math.round(rate);
},
variant: 'default'
}, '1fr');
row.addPriceDisplay('featuresTotal', {
label: 'Features & Access',
computedValue: () => {
let total = 0;
if (featuresSection.checkbox('driveUp')?.value()) total += 15;
if (featuresSection.checkbox('electricity')?.value()) total += 25;
if (featuresSection.checkbox('twentyFourHour')?.value()) total += 20;
return total;
},
variant: 'default',
prefix: '+',
suffix: '/mo'
}, '1fr');
});
summarySection.addRow(row => {
row.addPriceDisplay('termDiscount', {
label: 'Term Discount',
computedValue: () => {
const unitSize = unitSection.radioButton('unitSize')?.value() || '10x10';
const location = unitSection.dropdown('location')?.value() || 'suburban';
const floorLevel = unitSection.dropdown('floorLevel')?.value() || 'ground';
const climateControl = featuresSection.checkbox('climateControl')?.value() || false;
const rentalTerm = durationSection.radioButton('rentalTerm')?.value() || 'monthly';
let rate = unitSizeRates[unitSize] || 120;
rate *= locationMultipliers[location] || 1.0;
rate *= floorAdjustments[floorLevel] || 1.0;
if (climateControl) rate *= climateControlPremium;
let features = 0;
if (featuresSection.checkbox('driveUp')?.value()) features += 15;
if (featuresSection.checkbox('electricity')?.value()) features += 25;
if (featuresSection.checkbox('twentyFourHour')?.value()) features += 20;
const monthlyTotal = rate + features;
const termDiscounts: Record<string, number> = {
'monthly': 0,
'3-month': 0.05,
'6-month': 0.10,
'12-month': 0.15
};
const discount = termDiscounts[rentalTerm] || 0;
return -Math.round(monthlyTotal * discount);
},
variant: 'success',
prefix: '',
suffix: '/mo'
}, '1fr');
row.addPriceDisplay('insurance', {
label: 'Insurance',
computedValue: () => {
return servicesSection.checkbox('insurance')?.value() ? 15 : 0;
},
variant: 'default',
prefix: '+',
suffix: '/mo'
}, '1fr');
});
summarySection.addRow(row => {
row.addPriceDisplay('oneTimeFees', {
label: 'One-Time Fees',
computedValue: () => {
let total = 0;
if (servicesSection.checkbox('locks')?.value()) total += 20;
if (servicesSection.checkbox('movingSupplies')?.value()) total += 50;
if (servicesSection.checkbox('packingHelp')?.value()) {
const hours = servicesSection.integer('packingHours')?.value() || 2;
total += hours * 75;
}
return total;
},
variant: 'default',
prefix: '+'
}, '1fr');
});
const finalSection = form.addSubform('final', {
title: '🏢 Your Estimate',
isCollapsible: false,
sticky: 'bottom'
});
finalSection.addRow(row => {
row.addPriceDisplay('monthlyTotal', {
label: 'Monthly Total',
computedValue: () => {
const unitSize = unitSection.radioButton('unitSize')?.value() || '10x10';
const location = unitSection.dropdown('location')?.value() || 'suburban';
const floorLevel = unitSection.dropdown('floorLevel')?.value() || 'ground';
const climateControl = featuresSection.checkbox('climateControl')?.value() || false;
const rentalTerm = durationSection.radioButton('rentalTerm')?.value() || 'monthly';
let rate = unitSizeRates[unitSize] || 120;
rate *= locationMultipliers[location] || 1.0;
rate *= floorAdjustments[floorLevel] || 1.0;
if (climateControl) rate *= climateControlPremium;
let features = 0;
if (featuresSection.checkbox('driveUp')?.value()) features += 15;
if (featuresSection.checkbox('electricity')?.value()) features += 25;
if (featuresSection.checkbox('twentyFourHour')?.value()) features += 20;
const subtotal = rate + features;
const termDiscounts: Record<string, number> = {
'monthly': 0,
'3-month': 0.05,
'6-month': 0.10,
'12-month': 0.15
};
const discount = termDiscounts[rentalTerm] || 0;
const discountedTotal = subtotal * (1 - discount);
const insurance = servicesSection.checkbox('insurance')?.value() ? 15 : 0;
return Math.round(discountedTotal + insurance);
},
variant: 'large',
suffix: '/mo'
}, '1fr');
row.addPriceDisplay('moveInCost', {
label: 'Move-In Cost',
computedValue: () => {
const unitSize = unitSection.radioButton('unitSize')?.value() || '10x10';
const location = unitSection.dropdown('location')?.value() || 'suburban';
const floorLevel = unitSection.dropdown('floorLevel')?.value() || 'ground';
const climateControl = featuresSection.checkbox('climateControl')?.value() || false;
const rentalTerm = durationSection.radioButton('rentalTerm')?.value() || 'monthly';
const firstMonthFree = durationSection.checkbox('firstMonthFree')?.value() || false;
let rate = unitSizeRates[unitSize] || 120;
rate *= locationMultipliers[location] || 1.0;
rate *= floorAdjustments[floorLevel] || 1.0;
if (climateControl) rate *= climateControlPremium;
let features = 0;
if (featuresSection.checkbox('driveUp')?.value()) features += 15;
if (featuresSection.checkbox('electricity')?.value()) features += 25;
if (featuresSection.checkbox('twentyFourHour')?.value()) features += 20;
const subtotal = rate + features;
const termDiscounts: Record<string, number> = {
'monthly': 0,
'3-month': 0.05,
'6-month': 0.10,
'12-month': 0.15
};
const discount = termDiscounts[rentalTerm] || 0;
const monthlyRent = subtotal * (1 - discount);
const insurance = servicesSection.checkbox('insurance')?.value() ? 15 : 0;
const monthly = monthlyRent + insurance;
// First month rent (or free)
let moveIn = firstMonthFree ? 0 : monthly;
// Admin fee
moveIn += 25;
// One-time fees
if (servicesSection.checkbox('locks')?.value()) moveIn += 20;
if (servicesSection.checkbox('movingSupplies')?.value()) moveIn += 50;
if (servicesSection.checkbox('packingHelp')?.value()) {
const hours = servicesSection.integer('packingHours')?.value() || 2;
moveIn += hours * 75;
}
return Math.round(moveIn);
},
variant: 'default'
}, '1fr');
});
finalSection.addRow(row => {
row.addTextPanel('promoNote', {
computedValue: () => {
const firstMonthFree = durationSection.checkbox('firstMonthFree')?.value();
return firstMonthFree ? '* First month free promo applied!' : '';
},
customStyles: { 'font-size': '0.9rem', 'color': '#059669', 'font-weight': '500' },
isVisible: () => durationSection.checkbox('firstMonthFree')?.value() === true
});
});
finalSection.addRow(row => {
row.addTextPanel('disclaimer', {
computedValue: () => 'Prices may vary by location. $25 admin fee applies at move-in. Subject to availability.',
customStyles: { 'font-size': '0.85rem', 'color': '#64748b', 'font-style': 'italic' }
});
});
form.configureSubmitButton({
label: 'Reserve Unit'
});
}