export function equipmentRequestSurvey(form: FormTs) {
// IT/Equipment Request Form - Internal operations procurement
// Demonstrates: Dropdown, CheckboxList, RadioButton, Datepicker, Slider, PriceDisplay, computed values
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'IT Equipment Request',
computedValue: () => 'Submit your hardware and equipment needs for approval',
customStyles: {
background: 'linear-gradient(135deg, #0f172a 0%, #334155 100%)',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Requester Information
// ============================================
const requesterSection = form.addSubform('requesterSection', {
title: 'Requester Information'
});
requesterSection.addRow(row => {
row.addTextbox('requesterName', {
label: 'Your Name',
placeholder: 'Full name',
isRequired: true
}, '1fr');
row.addEmail('requesterEmail', {
label: 'Email',
placeholder: 'your.email@company.com',
isRequired: true
}, '1fr');
});
requesterSection.addRow(row => {
row.addDropdown('department', {
label: 'Department',
options: [
{ id: 'engineering', name: 'Engineering' },
{ id: 'sales', name: 'Sales' },
{ id: 'marketing', name: 'Marketing' },
{ id: 'hr', name: 'Human Resources' },
{ id: 'finance', name: 'Finance' },
{ id: 'operations', name: 'Operations' },
{ id: 'support', name: 'Customer Support' },
{ id: 'executive', name: 'Executive' },
{ id: 'other', name: 'Other' }
],
isRequired: true
}, '1fr');
row.addTextbox('managerName', {
label: 'Manager/Approver Name',
placeholder: 'Your direct manager',
isRequired: true
}, '1fr');
});
// ============================================
// SECTION 2: Request Type
// ============================================
const requestTypeSection = form.addSubform('requestTypeSection', {
title: 'Request Type',
isVisible: () => requesterSection.textbox('requesterName')?.value()?.trim() !== ''
});
requestTypeSection.addRow(row => {
row.addRadioButton('requestType', {
label: 'What type of request is this?',
options: [
{ id: 'new', name: 'New Equipment - First-time request for new role or project' },
{ id: 'replacement', name: 'Replacement - Replace damaged, lost, or outdated equipment' },
{ id: 'upgrade', name: 'Upgrade - Upgrade existing equipment for better performance' },
{ id: 'additional', name: 'Additional - Extra equipment for current role' }
],
orientation: 'vertical',
isRequired: true
});
});
// Replacement details
requestTypeSection.addRow(row => {
row.addTextbox('currentAssetTag', {
label: 'Current Asset Tag/ID (if known)',
placeholder: 'e.g., LAPTOP-2023-0456',
isVisible: () => {
const type = requestTypeSection.radioButton('requestType')?.value();
return type === 'replacement' || type === 'upgrade';
}
}, '1fr');
row.addTextarea('replacementReason', {
label: 'Reason for replacement/upgrade',
placeholder: 'Describe what\'s wrong or why an upgrade is needed...',
rows: 2,
isRequired: () => {
const type = requestTypeSection.radioButton('requestType')?.value();
return type === 'replacement' || type === 'upgrade';
},
isVisible: () => {
const type = requestTypeSection.radioButton('requestType')?.value();
return type === 'replacement' || type === 'upgrade';
}
}, '1fr');
});
// ============================================
// SECTION 3: Equipment Selection
// ============================================
const equipmentSection = form.addSubform('equipmentSection', {
title: 'Equipment Needed',
isVisible: () => requestTypeSection.radioButton('requestType')?.value() !== null
});
// State for price calculation
const selectedPrices = form.state<Record<string, number>>({});
equipmentSection.addRow(row => {
row.addDropdown('equipmentCategory', {
label: 'Equipment Category',
options: [
{ id: 'computer', name: 'Computer/Laptop' },
{ id: 'monitor', name: 'Monitor/Display' },
{ id: 'peripherals', name: 'Peripherals (Keyboard, Mouse, etc.)' },
{ id: 'audio-video', name: 'Audio/Video Equipment' },
{ id: 'mobile', name: 'Mobile Device' },
{ id: 'storage', name: 'Storage/Backup' },
{ id: 'networking', name: 'Networking Equipment' },
{ id: 'other', name: 'Other' }
],
isRequired: true,
onValueChange: () => selectedPrices.set({})
});
});
// Computer options
equipmentSection.addRow(row => {
row.addCheckboxList('computerItems', {
label: 'Select computer type:',
options: [
{ id: 'laptop-standard', name: 'Standard Laptop (~$1,200)' },
{ id: 'laptop-power', name: 'Power Laptop - Development/Design (~$2,500)' },
{ id: 'desktop-standard', name: 'Standard Desktop (~$900)' },
{ id: 'desktop-workstation', name: 'Workstation - High Performance (~$3,500)' },
{ id: 'macbook-pro', name: 'MacBook Pro 14" (~$2,000)' },
{ id: 'macbook-pro-max', name: 'MacBook Pro 16" Max (~$3,500)' }
],
orientation: 'vertical',
isVisible: () => equipmentSection.dropdown('equipmentCategory')?.value() === 'computer',
onValueChange: (items) => {
const prices: Record<string, number> = {
'laptop-standard': 1200,
'laptop-power': 2500,
'desktop-standard': 900,
'desktop-workstation': 3500,
'macbook-pro': 2000,
'macbook-pro-max': 3500
};
const total: Record<string, number> = {};
(items || []).forEach(id => { total[id] = prices[id] || 0; });
selectedPrices.set(total);
}
});
});
// Monitor options
equipmentSection.addRow(row => {
row.addCheckboxList('monitorItems', {
label: 'Select monitor(s):',
options: [
{ id: 'monitor-24', name: '24" Standard Monitor (~$250)' },
{ id: 'monitor-27', name: '27" QHD Monitor (~$400)' },
{ id: 'monitor-32', name: '32" 4K Monitor (~$600)' },
{ id: 'monitor-ultra', name: '34" Ultrawide (~$800)' },
{ id: 'monitor-arm', name: 'Monitor Arm (~$100)' }
],
orientation: 'vertical',
isVisible: () => equipmentSection.dropdown('equipmentCategory')?.value() === 'monitor',
onValueChange: (items) => {
const prices: Record<string, number> = {
'monitor-24': 250,
'monitor-27': 400,
'monitor-32': 600,
'monitor-ultra': 800,
'monitor-arm': 100
};
const total: Record<string, number> = {};
(items || []).forEach(id => { total[id] = prices[id] || 0; });
selectedPrices.set(total);
}
});
});
// Peripherals
equipmentSection.addRow(row => {
row.addCheckboxList('peripheralItems', {
label: 'Select peripherals:',
options: [
{ id: 'keyboard-standard', name: 'Standard Keyboard (~$50)' },
{ id: 'keyboard-mech', name: 'Mechanical Keyboard (~$150)' },
{ id: 'mouse-standard', name: 'Standard Mouse (~$30)' },
{ id: 'mouse-ergo', name: 'Ergonomic Mouse (~$80)' },
{ id: 'docking-station', name: 'Docking Station (~$250)' },
{ id: 'usb-hub', name: 'USB Hub (~$40)' }
],
orientation: 'vertical',
isVisible: () => equipmentSection.dropdown('equipmentCategory')?.value() === 'peripherals',
onValueChange: (items) => {
const prices: Record<string, number> = {
'keyboard-standard': 50,
'keyboard-mech': 150,
'mouse-standard': 30,
'mouse-ergo': 80,
'docking-station': 250,
'usb-hub': 40
};
const total: Record<string, number> = {};
(items || []).forEach(id => { total[id] = prices[id] || 0; });
selectedPrices.set(total);
}
});
});
// Audio/Video
equipmentSection.addRow(row => {
row.addCheckboxList('avItems', {
label: 'Select audio/video equipment:',
options: [
{ id: 'headset-basic', name: 'Basic Headset (~$60)' },
{ id: 'headset-pro', name: 'Professional Headset (~$200)' },
{ id: 'webcam-hd', name: 'HD Webcam (~$100)' },
{ id: 'webcam-4k', name: '4K Webcam (~$200)' },
{ id: 'ring-light', name: 'Ring Light (~$50)' },
{ id: 'microphone', name: 'USB Microphone (~$150)' }
],
orientation: 'vertical',
isVisible: () => equipmentSection.dropdown('equipmentCategory')?.value() === 'audio-video',
onValueChange: (items) => {
const prices: Record<string, number> = {
'headset-basic': 60,
'headset-pro': 200,
'webcam-hd': 100,
'webcam-4k': 200,
'ring-light': 50,
'microphone': 150
};
const total: Record<string, number> = {};
(items || []).forEach(id => { total[id] = prices[id] || 0; });
selectedPrices.set(total);
}
});
});
// Other equipment description
equipmentSection.addRow(row => {
row.addTextarea('otherEquipment', {
label: 'Describe the equipment you need:',
placeholder: 'Please provide specific make/model or detailed requirements...',
rows: 3,
isRequired: true,
isVisible: () => {
const cat = equipmentSection.dropdown('equipmentCategory')?.value();
return cat === 'other' || cat === 'mobile' || cat === 'storage' || cat === 'networking';
}
});
});
// ============================================
// SECTION 4: Urgency & Timeline
// ============================================
const urgencySection = form.addSubform('urgencySection', {
title: 'Urgency & Timeline',
isVisible: () => equipmentSection.dropdown('equipmentCategory')?.value() !== null
});
urgencySection.addRow(row => {
row.addSlider('urgencyLevel', {
label: 'How urgent is this request?',
min: 1,
max: 5,
step: 1,
showValue: true,
defaultValue: 3
}, '1fr');
row.addTextPanel('urgencyLabel', {
computedValue: () => {
const level = urgencySection.slider('urgencyLevel')?.value();
const labels: Record<number, string> = {
1: '🟢 Low - Can wait several weeks',
2: '🟡 Normal - Within 2 weeks',
3: '🟠 Medium - Within 1 week',
4: '🔴 High - Within 2-3 days',
5: '🚨 Critical - Blocking work'
};
return labels[level || 3] || '';
},
customStyles: () => {
const level = urgencySection.slider('urgencyLevel')?.value();
const colors: Record<number, string> = {
1: '#dcfce7',
2: '#fef9c3',
3: '#fed7aa',
4: '#fecaca',
5: '#fee2e2'
};
return {
backgroundColor: colors[level || 3] || '#f8fafc',
padding: '12px',
borderRadius: '6px',
textAlign: 'center'
};
}
}, '1fr');
});
urgencySection.addRow(row => {
row.addDatepicker('neededByDate', {
label: 'Date needed by',
minDate: new Date().toISOString(),
isRequired: () => {
const level = urgencySection.slider('urgencyLevel')?.value();
return level !== null && level !== undefined && level >= 4;
}
}, '1fr');
row.addTextarea('urgencyJustification', {
label: 'Justification for urgent request',
placeholder: 'Explain why this is urgent...',
rows: 2,
isVisible: () => {
const level = urgencySection.slider('urgencyLevel')?.value();
return level !== null && level !== undefined && level >= 4;
},
isRequired: () => {
const level = urgencySection.slider('urgencyLevel')?.value();
return level !== null && level !== undefined && level >= 4;
}
}, '1fr');
});
// ============================================
// SECTION 5: Business Justification
// ============================================
const justificationSection = form.addSubform('justificationSection', {
title: 'Business Justification',
isVisible: () => equipmentSection.dropdown('equipmentCategory')?.value() !== null
});
justificationSection.addRow(row => {
row.addTextarea('businessNeed', {
label: 'Why do you need this equipment?',
placeholder: 'Describe the business need and how this equipment will help you be more productive...',
rows: 3,
isRequired: true
});
});
justificationSection.addRow(row => {
row.addRadioButton('projectRelated', {
label: 'Is this related to a specific project?',
options: [
{ id: 'yes', name: 'Yes - Project-specific requirement' },
{ id: 'no', name: 'No - General productivity/role requirement' }
],
orientation: 'horizontal'
});
});
justificationSection.addRow(row => {
row.addTextbox('projectName', {
label: 'Project Name/Code',
placeholder: 'e.g., Project Phoenix, Q1-2024-LAUNCH',
isVisible: () => justificationSection.radioButton('projectRelated')?.value() === 'yes',
isRequired: () => justificationSection.radioButton('projectRelated')?.value() === 'yes'
});
});
// ============================================
// SECTION 6: Cost Estimate
// ============================================
const costSection = form.addSubform('costSection', {
title: 'Estimated Cost',
isVisible: () => {
const prices = selectedPrices();
return Object.keys(prices).length > 0;
},
customStyles: { backgroundColor: '#eff6ff', padding: '16px', borderRadius: '8px' }
});
costSection.addRow(row => {
row.addPriceDisplay('estimatedTotal', {
label: 'Estimated Total Cost',
computedValue: () => {
const prices = selectedPrices();
return Object.values(prices).reduce((sum, price) => sum + price, 0);
},
currency: '$',
variant: 'large',
alignment: 'center',
prefix: 'Approximately'
});
});
costSection.addRow(row => {
row.addTextPanel('costNote', {
computedValue: () => {
const total = Object.values(selectedPrices()).reduce((sum, price) => sum + price, 0);
if (total > 2000) {
return '⚠️ Requests over $2,000 require additional approval from IT leadership.';
}
return '✅ Standard approval process - Manager approval required.';
},
customStyles: () => {
const total = Object.values(selectedPrices()).reduce((sum, price) => sum + price, 0);
return {
backgroundColor: total > 2000 ? '#fef3c7' : '#dcfce7',
padding: '12px',
borderRadius: '6px',
textAlign: 'center',
borderLeft: total > 2000 ? '4px solid #f59e0b' : '4px solid #22c55e'
};
}
});
});
// ============================================
// REQUEST SUMMARY
// ============================================
const summarySection = form.addSubform('summarySection', {
title: 'Request Summary',
isVisible: () => justificationSection.textarea('businessNeed')?.value()?.trim() !== ''
});
summarySection.addRow(row => {
row.addTextPanel('summary', {
computedValue: () => {
const name = requesterSection.textbox('requesterName')?.value();
const dept = requesterSection.dropdown('department')?.value();
const manager = requesterSection.textbox('managerName')?.value();
const reqType = requestTypeSection.radioButton('requestType')?.value();
const category = equipmentSection.dropdown('equipmentCategory')?.value();
const urgency = urgencySection.slider('urgencyLevel')?.value();
const neededBy = urgencySection.datepicker('neededByDate')?.value();
const prices = selectedPrices();
const total = Object.values(prices).reduce((sum, price) => sum + price, 0);
const items = Object.keys(prices);
let summary = '📦 EQUIPMENT REQUEST SUMMARY\n';
summary += '═'.repeat(30) + '\n\n';
if (name) summary += `👤 Requester: ${name}\n`;
if (dept) summary += `🏢 Department: ${dept}\n`;
if (manager) summary += `👔 Approver: ${manager}\n\n`;
if (reqType) {
const typeLabels: Record<string, string> = {
'new': 'New Equipment',
'replacement': 'Replacement',
'upgrade': 'Upgrade',
'additional': 'Additional'
};
summary += `📋 Request Type: ${typeLabels[reqType] || reqType}\n`;
}
if (category) summary += `📁 Category: ${category}\n`;
if (items.length > 0) {
summary += `\n🛒 Items Selected: ${items.length}\n`;
}
if (total > 0) {
summary += `💰 Estimated Cost: $${total.toLocaleString()}\n`;
}
if (urgency) {
const urgencyLabels: Record<number, string> = {
1: 'Low',
2: 'Normal',
3: 'Medium',
4: 'High',
5: 'Critical'
};
summary += `\n⏰ Urgency: ${urgencyLabels[urgency] || urgency}\n`;
}
if (neededBy) {
summary += `📅 Needed By: ${neededBy}\n`;
}
if (total > 2000) {
summary += `\n⚠️ Requires IT leadership approval\n`;
}
return summary;
},
customStyles: {
padding: '16px',
borderRadius: '8px',
backgroundColor: '#f8fafc',
borderLeft: '4px solid #64748b',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '13px'
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: () => {
const total = Object.values(selectedPrices()).reduce((sum, price) => sum + price, 0);
return total > 2000 ? 'Submit for Approval (IT Leadership Required)' : 'Submit Request';
},
isVisible: () => justificationSection.textarea('businessNeed')?.value()?.trim() !== ''
});
form.configureCompletionScreen({
type: 'text',
title: 'Request Submitted Successfully!',
message: () => {
const total = Object.values(selectedPrices()).reduce((sum, price) => sum + price, 0);
if (total > 2000) {
return 'Your request has been submitted and will be reviewed by your manager and IT leadership. You will receive an email with the approval status and next steps.';
}
return 'Your request has been submitted to your manager for approval. You will receive an email notification once it has been reviewed.';
}
});
}