export function punchListWalkthrough(form: FormTs) {
// Punch List / Final Walkthrough Form - Construction defect tracking
// Demonstrates: Pages (multi-page), MatrixQuestion, RatingScale, StarRating, ThumbRating, CheckboxList, SuggestionChips, conditional visibility, dynamic styling
// ============================================
// STATE
// ============================================
const totalDefects = form.state(0);
const criticalCount = form.state(0);
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Punch List / Final Walkthrough',
computedValue: () => 'Document defects and incomplete items before project handover',
customStyles: {
backgroundColor: '#b45309',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// MULTI-PAGE STRUCTURE
// ============================================
const pages = form.addPages('punchlistPages', {
heightMode: 'current-page'
});
// ============================================
// PAGE 1: Project Information
// ============================================
const page1 = pages.addPage('info');
page1.addRow(row => {
row.addTextPanel('page1Title', {
label: 'Step 1 of 4: Project Information',
customStyles: {
backgroundColor: '#fef3c7',
padding: '12px 16px',
borderRadius: '8px',
fontWeight: 'bold'
}
});
});
const projectSection = page1.addSubform('project', {
title: 'Project Details',
customStyles: { padding: '16px', borderRadius: '8px', border: '1px solid #e2e8f0' }
});
projectSection.addRow(row => {
row.addTextbox('projectName', {
label: 'Project Name',
placeholder: 'e.g., 123 Main Street Renovation',
isRequired: true
}, '1fr');
row.addTextbox('projectNumber', {
label: 'Project/Job Number',
placeholder: 'e.g., PRJ-2024-001'
}, '1fr');
});
projectSection.addRow(row => {
row.addTextbox('projectAddress', {
label: 'Project Address',
placeholder: 'Full address of the project',
isRequired: true
});
});
projectSection.addRow(row => {
row.addDatepicker('walkthroughDate', {
label: 'Walkthrough Date',
isRequired: true
}, '1fr');
row.addDropdown('walkthroughType', {
label: 'Walkthrough Type',
options: [
{ id: 'initial', name: 'Initial Punch List' },
{ id: 'follow-up', name: 'Follow-up Inspection' },
{ id: 'final', name: 'Final Inspection' },
{ id: 'warranty', name: 'Warranty Walkthrough' }
],
isRequired: true,
placeholder: 'Select type'
}, '1fr');
});
const attendeesSection = page1.addSubform('attendees', {
title: 'Walkthrough Attendees'
});
attendeesSection.addRow(row => {
row.addTextbox('contractor', {
label: 'General Contractor Rep',
placeholder: 'Name'
}, '1fr');
row.addTextbox('owner', {
label: 'Owner/Client Rep',
placeholder: 'Name'
}, '1fr');
});
attendeesSection.addRow(row => {
row.addTextbox('architect', {
label: 'Architect/PM',
placeholder: 'Name (if present)'
}, '1fr');
row.addTextbox('inspector', {
label: 'Inspector',
placeholder: 'Your name',
isRequired: true
}, '1fr');
});
page1.addRow(row => {
row.addEmpty('1fr');
row.addButton('toPage2', {
label: 'Next: Interior Inspection',
onClick: () => pages.goToPage('interior')
});
});
// ============================================
// PAGE 2: Interior Areas
// ============================================
const page2 = pages.addPage('interior');
page2.addRow(row => {
row.addTextPanel('page2Title', {
label: 'Step 2 of 4: Interior Areas',
customStyles: {
backgroundColor: '#fef3c7',
padding: '12px 16px',
borderRadius: '8px',
fontWeight: 'bold'
}
});
});
const interiorSection = page2.addSubform('interior', {
title: 'Interior Inspection',
customStyles: { padding: '16px', borderRadius: '8px', border: '1px solid #e2e8f0' }
});
interiorSection.addRow(row => {
row.addMatrixQuestion('interiorAreas', {
label: 'Rate condition of each interior area:',
rows: [
{ id: 'entry', label: 'Entry/Foyer', isRequired: true },
{ id: 'living', label: 'Living Room', isRequired: true },
{ id: 'dining', label: 'Dining Room', isRequired: false },
{ id: 'kitchen', label: 'Kitchen', isRequired: true },
{ id: 'master-bed', label: 'Master Bedroom', isRequired: true },
{ id: 'bedrooms', label: 'Other Bedrooms', isRequired: false },
{ id: 'bathrooms', label: 'Bathrooms', isRequired: true },
{ id: 'laundry', label: 'Laundry Room', isRequired: false },
{ id: 'basement', label: 'Basement', isRequired: false },
{ id: 'garage', label: 'Garage', isRequired: false }
],
columns: [
{ id: 'na', label: 'N/A' },
{ id: 'complete', label: 'Complete' },
{ id: 'minor', label: 'Minor Issues' },
{ id: 'major', label: 'Major Issues' },
{ id: 'incomplete', label: 'Incomplete' }
],
striped: true,
fullWidth: true
});
});
const interiorDefects = page2.addSubform('interiorDefects', {
title: 'Interior Defects Found',
customStyles: { backgroundColor: '#fef9c3', padding: '16px', borderRadius: '8px' }
});
interiorDefects.addRow(row => {
row.addCheckboxList('interiorIssues', {
label: 'Select all defect types found in interior areas:',
options: [
{ id: 'paint-touch', name: 'Paint touch-ups needed' },
{ id: 'drywall', name: 'Drywall repairs/patches' },
{ id: 'trim', name: 'Trim/molding issues' },
{ id: 'doors', name: 'Door adjustments needed' },
{ id: 'hardware', name: 'Hardware missing/damaged' },
{ id: 'flooring', name: 'Flooring defects' },
{ id: 'cabinets', name: 'Cabinet/millwork issues' },
{ id: 'countertops', name: 'Countertop issues' },
{ id: 'fixtures', name: 'Fixture issues' },
{ id: 'cleaning', name: 'Cleaning required' }
],
orientation: 'vertical'
});
});
interiorDefects.addSpacer({ isVisible: () => {
const issues = interiorDefects.checkboxList('interiorIssues')?.value() || [];
return issues.length > 0;
}});
interiorDefects.addRow(row => {
row.addTextarea('interiorNotes', {
label: 'Detailed interior defect descriptions',
placeholder: 'Describe each defect with location (e.g., "Kitchen - Cabinet door #3 misaligned, needs adjustment")',
rows: 4,
autoExpand: true,
isVisible: () => {
const issues = interiorDefects.checkboxList('interiorIssues')?.value() || [];
return issues.length > 0;
}
});
});
page2.addRow(row => {
row.addButton('backToPage1', {
label: 'Back',
onClick: () => pages.goToPage('info')
});
row.addEmpty('1fr');
row.addButton('toPage3', {
label: 'Next: Systems & Exterior',
onClick: () => pages.goToPage('systems')
});
});
// ============================================
// PAGE 3: Systems & Exterior
// ============================================
const page3 = pages.addPage('systems');
page3.addRow(row => {
row.addTextPanel('page3Title', {
label: 'Step 3 of 4: Systems & Exterior',
customStyles: {
backgroundColor: '#fef3c7',
padding: '12px 16px',
borderRadius: '8px',
fontWeight: 'bold'
}
});
});
const systemsSection = page3.addSubform('systems', {
title: 'Building Systems',
customStyles: { padding: '16px', borderRadius: '8px', border: '1px solid #e2e8f0' }
});
systemsSection.addRow(row => {
row.addMatrixQuestion('systemsCheck', {
label: 'Inspect building systems:',
rows: [
{ id: 'electrical', label: 'Electrical', description: 'Outlets, switches, panels', isRequired: true },
{ id: 'plumbing', label: 'Plumbing', description: 'Fixtures, water pressure, drains', isRequired: true },
{ id: 'hvac', label: 'HVAC', description: 'Heating, cooling, ventilation', isRequired: true },
{ id: 'fire-safety', label: 'Fire Safety', description: 'Detectors, alarms, extinguishers', isRequired: true },
{ id: 'appliances', label: 'Appliances', description: 'All installed appliances', isRequired: false }
],
columns: [
{ id: 'na', label: 'N/A' },
{ id: 'pass', label: 'Pass' },
{ id: 'minor', label: 'Minor Issue' },
{ id: 'fail', label: 'Fail' }
],
striped: true,
fullWidth: true
});
});
const exteriorSection = page3.addSubform('exterior', {
title: 'Exterior & Site'
});
exteriorSection.addRow(row => {
row.addMatrixQuestion('exteriorCheck', {
label: 'Inspect exterior areas:',
rows: [
{ id: 'siding', label: 'Siding/Exterior Finish', isRequired: true },
{ id: 'roofing', label: 'Roofing (visible)', isRequired: false },
{ id: 'windows', label: 'Windows & Doors', isRequired: true },
{ id: 'gutters', label: 'Gutters & Downspouts', isRequired: false },
{ id: 'driveway', label: 'Driveway/Walkways', isRequired: false },
{ id: 'landscaping', label: 'Landscaping', isRequired: false },
{ id: 'grading', label: 'Grading/Drainage', isRequired: false }
],
columns: [
{ id: 'na', label: 'N/A' },
{ id: 'complete', label: 'Complete' },
{ id: 'minor', label: 'Minor Issues' },
{ id: 'major', label: 'Major Issues' },
{ id: 'incomplete', label: 'Incomplete' }
],
striped: true,
fullWidth: true
});
});
const systemsDefects = page3.addSubform('systemsDefects', {
title: 'Systems & Exterior Defects',
customStyles: { backgroundColor: '#fef9c3', padding: '16px', borderRadius: '8px' }
});
systemsDefects.addRow(row => {
row.addSuggestionChips('criticalIssues', {
label: 'Critical issues requiring immediate attention:',
suggestions: [
{ id: 'electrical-safety', name: 'Electrical Safety' },
{ id: 'plumbing-leak', name: 'Plumbing Leak' },
{ id: 'hvac-not-working', name: 'HVAC Not Working' },
{ id: 'fire-safety', name: 'Fire Safety Issue' },
{ id: 'structural', name: 'Structural Concern' },
{ id: 'water-intrusion', name: 'Water Intrusion' },
{ id: 'security', name: 'Security Issue' }
],
alignment: 'center'
});
});
systemsDefects.addSpacer();
systemsDefects.addRow(row => {
row.addTextarea('systemsNotes', {
label: 'Systems and exterior defect details',
placeholder: 'Describe each issue with specific location and severity...',
rows: 4,
autoExpand: true
});
});
page3.addRow(row => {
row.addButton('backToPage2', {
label: 'Back',
onClick: () => pages.goToPage('interior')
});
row.addEmpty('1fr');
row.addButton('toPage4', {
label: 'Next: Review & Summary',
onClick: () => pages.goToPage('summary')
});
});
// ============================================
// PAGE 4: Summary & Sign-off
// ============================================
const page4 = pages.addPage('summary');
page4.addRow(row => {
row.addTextPanel('page4Title', {
label: 'Step 4 of 4: Review & Summary',
customStyles: {
backgroundColor: '#fef3c7',
padding: '12px 16px',
borderRadius: '8px',
fontWeight: 'bold'
}
});
});
const overallSection = page4.addSubform('overall', {
title: 'Overall Assessment',
customStyles: () => {
const rating = overallSection.starRating('overallQuality')?.value() || 0;
if (rating >= 4) return { backgroundColor: '#dcfce7', padding: '16px', borderRadius: '8px' };
if (rating >= 3) return { backgroundColor: '#fef9c3', padding: '16px', borderRadius: '8px' };
if (rating >= 1) return { backgroundColor: '#fecaca', padding: '16px', borderRadius: '8px' };
return { padding: '16px', borderRadius: '8px', border: '1px solid #e2e8f0' };
}
});
overallSection.addRow(row => {
row.addStarRating('overallQuality', {
label: 'Overall Construction Quality',
maxStars: 5,
size: 'xl',
alignment: 'center',
showConfettiOnMax: true
});
});
overallSection.addRow(row => {
row.addRatingScale('completionLevel', {
preset: 'custom',
min: 0,
max: 100,
label: 'Project Completion Level',
lowLabel: '0% - Not Ready',
highLabel: '100% - Fully Complete',
alignment: 'center'
});
});
overallSection.addRow(row => {
row.addThumbRating('readyForHandover', {
label: 'Is the project ready for handover?',
showLabels: true,
upLabel: 'Yes - Ready',
downLabel: 'No - Needs Work',
alignment: 'center',
size: 'lg'
});
});
const prioritySection = page4.addSubform('priority', {
title: 'Priority Classification',
isVisible: () => overallSection.thumbRating('readyForHandover')?.value() === 'down'
});
prioritySection.addRow(row => {
row.addTextPanel('priorityNote', {
computedValue: () => 'Classify the severity of issues found to help prioritize repairs.',
customStyles: {
backgroundColor: '#fee2e2',
padding: '12px 16px',
borderRadius: '8px',
borderLeft: '4px solid #ef4444',
fontSize: '14px'
}
});
});
prioritySection.addRow(row => {
row.addInteger('criticalItems', {
label: 'Critical Items',
placeholder: '0',
min: 0,
tooltip: 'Must fix before occupancy'
}, '1fr');
row.addInteger('majorItems', {
label: 'Major Items',
placeholder: '0',
min: 0,
tooltip: 'Significant issues'
}, '1fr');
row.addInteger('minorItems', {
label: 'Minor Items',
placeholder: '0',
min: 0,
tooltip: 'Cosmetic or minor'
}, '1fr');
});
const nextSteps = page4.addSubform('nextSteps', {
title: 'Next Steps & Timeline'
});
nextSteps.addRow(row => {
row.addDropdown('followUpRequired', {
label: 'Follow-up inspection required?',
options: [
{ id: 'no', name: 'No - All items are minor' },
{ id: 'yes-1week', name: 'Yes - Within 1 week' },
{ id: 'yes-2weeks', name: 'Yes - Within 2 weeks' },
{ id: 'yes-1month', name: 'Yes - Within 1 month' }
],
placeholder: 'Select'
}, '1fr');
row.addDatepicker('targetCompletion', {
label: 'Target Completion Date',
minDate: () => new Date().toISOString().split('T')[0]
}, '1fr');
});
nextSteps.addSpacer();
nextSteps.addRow(row => {
row.addTextarea('actionItems', {
label: 'Key action items for contractor',
placeholder: 'List the most important items to address...',
rows: 3,
autoExpand: true
});
});
// Summary panel
const summaryPanel = page4.addSubform('summaryPanel', {
title: 'Walkthrough Summary'
});
summaryPanel.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const project = projectSection.textbox('projectName')?.value();
const date = projectSection.datepicker('walkthroughDate')?.value();
const type = projectSection.dropdown('walkthroughType')?.value();
const quality = overallSection.starRating('overallQuality')?.value();
const ready = overallSection.thumbRating('readyForHandover')?.value();
const interiorIssues = interiorDefects.checkboxList('interiorIssues')?.value() || [];
const criticalIssues = systemsDefects.suggestionChips('criticalIssues')?.value() || [];
const critical = prioritySection.integer('criticalItems')?.value() || 0;
const major = prioritySection.integer('majorItems')?.value() || 0;
const minor = prioritySection.integer('minorItems')?.value() || 0;
let summary = `PUNCH LIST SUMMARY\n`;
summary += `${'═'.repeat(25)}\n\n`;
if (project) summary += `Project: ${project}\n`;
if (date) summary += `Date: ${date}\n`;
if (type) {
const typeLabels: Record<string, string> = {
'initial': 'Initial Punch List',
'follow-up': 'Follow-up Inspection',
'final': 'Final Inspection',
'warranty': 'Warranty Walkthrough'
};
summary += `Type: ${typeLabels[type]}\n`;
}
if (quality) {
summary += `\nQuality: ${'★'.repeat(quality)}${'☆'.repeat(5 - quality)} (${quality}/5)\n`;
}
const totalIssues = interiorIssues.length + criticalIssues.length;
if (totalIssues > 0 || critical > 0 || major > 0 || minor > 0) {
summary += `\nISSUES FOUND:\n`;
if (critical > 0) summary += ` Critical: ${critical}\n`;
if (major > 0) summary += ` Major: ${major}\n`;
if (minor > 0) summary += ` Minor: ${minor}\n`;
if (interiorIssues.length > 0) summary += ` Interior defect types: ${interiorIssues.length}\n`;
if (criticalIssues.length > 0) summary += ` Critical system issues: ${criticalIssues.length}\n`;
}
if (ready) {
summary += `\nHandover Ready: ${ready === 'up' ? 'YES' : 'NO'}`;
}
return summary;
},
customStyles: () => {
const ready = overallSection.thumbRating('readyForHandover')?.value();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '13px'
};
if (ready === 'up') {
return { ...baseStyles, backgroundColor: '#dcfce7', borderLeft: '4px solid #22c55e' };
} else if (ready === 'down') {
return { ...baseStyles, backgroundColor: '#fecaca', borderLeft: '4px solid #ef4444' };
}
return { ...baseStyles, backgroundColor: '#f8fafc', borderLeft: '4px solid #b45309' };
}
});
});
page4.addRow(row => {
row.addButton('backToPage3', {
label: 'Back',
onClick: () => pages.goToPage('systems')
});
row.addEmpty('1fr');
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: () => {
const ready = overallSection.thumbRating('readyForHandover')?.value();
return ready === 'up' ? 'Submit & Approve' : 'Submit Punch List';
},
isVisible: () => pages.currentPageIndex() === 3
});
form.configureCompletionScreen({
type: 'text',
title: 'Punch List Submitted',
message: () => {
const ready = overallSection.thumbRating('readyForHandover')?.value();
if (ready === 'up') {
return 'The project has been approved for handover. Congratulations on project completion!';
}
return 'The punch list has been recorded. Please distribute to the responsible parties for resolution and schedule a follow-up inspection.';
}
});
}