Project Milestone Sign-off Form

This comprehensive milestone sign-off form streamlines the project phase approval process. It covers milestone identification, deliverable verification, quality assessment, and multi-party approvals. With built-in conditional logic for incomplete items and punch lists, the form ensures nothing is missed before moving to the next project phase. Perfect for construction, software development, and any project-based work requiring formal milestone acceptance.

Specialized

Try the Form

Formal approval for project phase completion
 
Project Details
 
 
 
 
Milestone Details
 
 
 
 
Verify Milestone Deliverables
Complete Partial Incomplete N/A
All scope items completed per plans*
Work meets specifications*
Complies with applicable codes*
Required documentation submitted*
Safety requirements met*
Site cleanup completed*
 
 
 
Rate Work Quality
0/5
0/5
0/5
0/5
Quality Issues
 
 
 
 
Approval Decision
 
Sign-off Information
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
export function projectMilestoneSignoff(form: FormTs) {
// Project Milestone Sign-off Form - Construction/Development Approval
// Demonstrates: Multi-page wizard, StarRating, CheckboxList, conditional approval workflow
 
// ============================================
// STATE
// ============================================
const hasIncompleteItems = form.state(false);
const approvalStatus = form.state<'pending' | 'approved' | 'conditional' | 'rejected'>('pending');
 
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Project Milestone Sign-off',
computedValue: () => 'Formal approval for project phase completion',
customStyles: {
backgroundColor: '#1e40af',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
 
// ============================================
// MULTI-PAGE WIZARD
// ============================================
const pages = form.addPages('milestonePages');
 
// ============================================
// PAGE 1: Project & Milestone Information
// ============================================
const page1 = pages.addPage('projectInfo');
 
page1.addRow(row => {
row.addTextPanel('page1Title', {
label: 'Step 1 of 4: Project Information',
customStyles: {
backgroundColor: '#dbeafe',
color: '#1e40af',
padding: '12px 16px',
borderRadius: '8px',
fontWeight: 'bold'
}
});
});
 
const projectSection = page1.addSubform('projectDetails', {
title: 'Project Details'
});
 
projectSection.addRow(row => {
row.addTextbox('projectName', {
label: 'Project Name',
placeholder: 'Enter project name',
isRequired: true
}, '1fr');
row.addTextbox('projectNumber', {
label: 'Project Number/ID',
placeholder: 'e.g., PRJ-2024-001'
}, '1fr');
});
 
projectSection.addRow(row => {
row.addTextbox('clientName', {
label: 'Client/Owner Name',
placeholder: 'Enter client name',
isRequired: true
}, '1fr');
row.addTextbox('contractorName', {
label: 'Contractor/Vendor',
placeholder: 'Enter contractor name'
}, '1fr');
});
 
const milestoneSection = page1.addSubform('milestoneDetails', {
title: 'Milestone Details'
});
 
milestoneSection.addRow(row => {
row.addDropdown('milestoneType', {
label: 'Milestone Type',
options: [
{ id: 'foundation', name: 'Foundation Complete' },
{ id: 'framing', name: 'Framing Complete' },
{ id: 'roofing', name: 'Roofing Complete' },
{ id: 'mep-rough', name: 'MEP Rough-in Complete' },
{ id: 'drywall', name: 'Drywall Complete' },
{ id: 'finishes', name: 'Finishes Complete' },
{ id: 'substantial', name: 'Substantial Completion' },
{ id: 'final', name: 'Final Completion' },
{ id: 'custom', name: 'Custom Milestone' }
],
isRequired: true
}, '1fr');
row.addTextbox('customMilestone', {
label: 'Custom Milestone Name',
placeholder: 'Describe the milestone',
isVisible: () => milestoneSection.dropdown('milestoneType')?.value() === 'custom',
isRequired: () => milestoneSection.dropdown('milestoneType')?.value() === 'custom'
}, '1fr');
});
 
milestoneSection.addRow(row => {
row.addDatepicker('scheduledDate', {
label: 'Scheduled Completion Date'
}, '1fr');
row.addDatepicker('actualDate', {
label: 'Actual Completion Date',
isRequired: true,
defaultValue: new Date().toISOString().slice(0, 10)
}, '1fr');
});
 
page1.addSpacer();
 
page1.addRow(row => {
row.addButton('nextToPage2', {
label: 'Next: Deliverables Review',
onClick: () => pages.goToPage('deliverables')
});
});
 
// ============================================
// PAGE 2: Deliverables Verification
// ============================================
const page2 = pages.addPage('deliverables');
 
page2.addRow(row => {
row.addTextPanel('page2Title', {
label: 'Step 2 of 4: Deliverables Review',
customStyles: {
backgroundColor: '#dbeafe',
color: '#1e40af',
padding: '12px 16px',
borderRadius: '8px',
fontWeight: 'bold'
}
});
});
 
const deliverablesSection = page2.addSubform('deliverables', {
title: 'Verify Milestone Deliverables'
});
 
deliverablesSection.addRow(row => {
row.addMatrixQuestion('deliverableStatus', {
label: 'Review each deliverable for this milestone:',
rows: [
{ id: 'scope', label: 'All scope items completed per plans', isRequired: true },
{ id: 'specs', label: 'Work meets specifications', isRequired: true },
{ id: 'codes', label: 'Complies with applicable codes', isRequired: true },
{ id: 'docs', label: 'Required documentation submitted', isRequired: true },
{ id: 'safety', label: 'Safety requirements met', isRequired: true },
{ id: 'cleanup', label: 'Site cleanup completed', isRequired: true }
],
columns: [
{ id: 'complete', label: 'Complete' },
{ id: 'partial', label: 'Partial' },
{ id: 'incomplete', label: 'Incomplete' },
{ id: 'na', label: 'N/A' }
],
fullWidth: true,
onValueChange: (value) => {
if (!value) return;
const hasIssues = Object.values(value).some(v => v === 'partial' || v === 'incomplete');
hasIncompleteItems.set(hasIssues);
}
});
});
 
const punchListSection = page2.addSubform('punchList', {
title: 'Punch List Items',
isVisible: () => hasIncompleteItems(),
customStyles: { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' }
});
 
punchListSection.addRow(row => {
row.addTextPanel('punchNote', {
computedValue: () => 'Document all incomplete or partial items that require attention before final approval.',
customStyles: { color: '#92400e', fontStyle: 'italic' }
});
});
 
punchListSection.addRow(row => {
row.addTextarea('punchItems', {
label: 'List all punch list items:',
placeholder: '1. Item description and location\n2. Item description and location\n3. ...',
rows: 5,
isRequired: () => hasIncompleteItems()
});
});
 
punchListSection.addRow(row => {
row.addDatepicker('punchDeadline', {
label: 'Punch List Completion Deadline',
isRequired: () => hasIncompleteItems()
});
});
 
page2.addSpacer();
 
page2.addRow(row => {
row.addButton('backToPage1', {
label: 'Back',
onClick: () => pages.goToPage('projectInfo')
}, '100px');
row.addEmpty('1fr');
row.addButton('nextToPage3', {
label: 'Next: Quality Assessment',
onClick: () => pages.goToPage('quality')
}, 'auto');
});
 
// ============================================
// PAGE 3: Quality Assessment
// ============================================
const page3 = pages.addPage('quality');
 
page3.addRow(row => {
row.addTextPanel('page3Title', {
label: 'Step 3 of 4: Quality Assessment',
customStyles: {
backgroundColor: '#dbeafe',
color: '#1e40af',
padding: '12px 16px',
borderRadius: '8px',
fontWeight: 'bold'
}
});
});
 
const qualitySection = page3.addSubform('qualityAssessment', {
title: 'Rate Work Quality'
});
 
qualitySection.addRow(row => {
row.addStarRating('workmanship', {
label: 'Workmanship Quality',
maxStars: 5,
size: 'lg',
showCounter: true
}, '1fr');
row.addStarRating('materials', {
label: 'Materials Quality',
maxStars: 5,
size: 'lg',
showCounter: true
}, '1fr');
});
 
qualitySection.addRow(row => {
row.addStarRating('timeliness', {
label: 'Schedule Adherence',
maxStars: 5,
size: 'lg',
showCounter: true
}, '1fr');
row.addStarRating('communication', {
label: 'Communication & Coordination',
maxStars: 5,
size: 'lg',
showCounter: true
}, '1fr');
});
 
qualitySection.addRow(row => {
row.addEmojiRating('overallSatisfaction', {
label: 'Overall Satisfaction with Milestone Completion',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
 
const issuesSection = page3.addSubform('issues', {
title: 'Quality Issues'
});
 
issuesSection.addRow(row => {
row.addCheckboxList('qualityIssues', {
label: 'Any quality concerns? (select all that apply)',
options: [
{ id: 'none', name: 'No quality concerns' },
{ id: 'finish', name: 'Finish quality below standard' },
{ id: 'alignment', name: 'Alignment/levelness issues' },
{ id: 'damage', name: 'Damage requiring repair' },
{ id: 'incomplete', name: 'Missing or incomplete elements' },
{ id: 'deviation', name: 'Deviation from approved plans' }
],
orientation: 'vertical'
});
});
 
issuesSection.addSpacer();
 
issuesSection.addRow(row => {
row.addTextarea('qualityNotes', {
label: 'Quality Assessment Notes',
placeholder: 'Document any specific quality observations, concerns, or commendations...',
rows: 4
});
});
 
page3.addSpacer();
 
page3.addRow(row => {
row.addButton('backToPage2', {
label: 'Back',
onClick: () => pages.goToPage('deliverables')
}, '100px');
row.addEmpty('1fr');
row.addButton('nextToPage4', {
label: 'Next: Approval',
onClick: () => pages.goToPage('approval')
}, 'auto');
});
 
// ============================================
// PAGE 4: Approval & Sign-off
// ============================================
const page4 = pages.addPage('approval');
 
page4.addRow(row => {
row.addTextPanel('page4Title', {
label: 'Step 4 of 4: Approval & Sign-off',
customStyles: {
backgroundColor: '#dbeafe',
color: '#1e40af',
padding: '12px 16px',
borderRadius: '8px',
fontWeight: 'bold'
}
});
});
 
const approvalSection = page4.addSubform('approvalDecision', {
title: 'Approval Decision'
});
 
approvalSection.addRow(row => {
row.addRadioButton('approvalType', {
label: 'Milestone Approval Status:',
options: [
{ id: 'approved', name: 'Approved - Milestone accepted as complete' },
{ id: 'conditional', name: 'Conditionally Approved - Approved with punch list items' },
{ id: 'rejected', name: 'Rejected - Significant issues require rework' }
],
orientation: 'vertical',
isRequired: true,
onValueChange: (value) => {
if (value === 'approved') approvalStatus.set('approved');
else if (value === 'conditional') approvalStatus.set('conditional');
else if (value === 'rejected') approvalStatus.set('rejected');
else approvalStatus.set('pending');
}
});
});
 
const conditionsSection = page4.addSubform('conditions', {
title: 'Approval Conditions',
isVisible: () => approvalStatus() === 'conditional',
customStyles: { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' }
});
 
conditionsSection.addRow(row => {
row.addTextarea('conditionDetails', {
label: 'Conditions for Approval',
placeholder: 'List conditions that must be met for full approval...',
rows: 4,
isRequired: () => approvalStatus() === 'conditional'
});
});
 
const rejectionSection = page4.addSubform('rejection', {
title: 'Rejection Details',
isVisible: () => approvalStatus() === 'rejected',
customStyles: { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' }
});
 
rejectionSection.addRow(row => {
row.addTextarea('rejectionReason', {
label: 'Reason for Rejection',
placeholder: 'Explain why the milestone cannot be approved...',
rows: 4,
isRequired: () => approvalStatus() === 'rejected'
});
});
 
const signoffSection = page4.addSubform('signoff', {
title: 'Sign-off Information'
});
 
signoffSection.addRow(row => {
row.addTextbox('reviewerName', {
label: 'Reviewer Name',
placeholder: 'Enter your full name',
isRequired: true
}, '1fr');
row.addTextbox('reviewerTitle', {
label: 'Title/Role',
placeholder: 'e.g., Project Manager'
}, '1fr');
});
 
signoffSection.addRow(row => {
row.addDatepicker('signoffDate', {
label: 'Sign-off Date',
defaultValue: new Date().toISOString().slice(0, 10),
isRequired: true
}, '1fr');
row.addEmail('reviewerEmail', {
label: 'Email',
placeholder: 'your@email.com'
}, '1fr');
});
 
signoffSection.addRow(row => {
row.addCheckbox('confirmAccuracy', {
label: 'I confirm that this assessment is accurate and complete to the best of my knowledge',
isRequired: true
});
});
 
// ============================================
// SUMMARY SECTION
// ============================================
const summarySection = page4.addSubform('summary', {
title: 'Sign-off Summary',
isVisible: () => approvalStatus() !== 'pending'
});
 
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const status = approvalStatus();
const statusText = status === 'approved' ? 'APPROVED' :
status === 'conditional' ? 'CONDITIONALLY APPROVED' : 'REJECTED';
const emoji = status === 'approved' ? '' :
status === 'conditional' ? '' : '';
 
return `${emoji} MILESTONE STATUS: ${statusText}\n\nThis milestone sign-off will be recorded and all relevant parties will be notified.`;
},
customStyles: () => {
const status = approvalStatus();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
textAlign: 'center',
fontWeight: 'bold'
};
 
if (status === 'approved') {
return { ...baseStyles, backgroundColor: '#d1fae5', color: '#065f46', borderLeft: '4px solid #059669' };
} else if (status === 'conditional') {
return { ...baseStyles, backgroundColor: '#fef3c7', color: '#92400e', borderLeft: '4px solid #d97706' };
}
return { ...baseStyles, backgroundColor: '#fee2e2', color: '#991b1b', borderLeft: '4px solid #dc2626' };
}
});
});
 
page4.addSpacer();
 
page4.addRow(row => {
row.addButton('backToPage3', {
label: 'Back',
onClick: () => pages.goToPage('quality')
}, '100px');
});
 
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: () => {
const status = approvalStatus();
if (status === 'approved') return 'Submit Approval';
if (status === 'conditional') return 'Submit Conditional Approval';
if (status === 'rejected') return 'Submit Rejection';
return 'Submit Sign-off';
},
isVisible: () => approvalStatus() !== 'pending'
});
 
form.configureCompletionScreen({
type: 'text',
title: () => {
const status = approvalStatus();
if (status === 'approved') return 'Milestone Approved!';
if (status === 'conditional') return 'Conditional Approval Recorded';
return 'Sign-off Submitted';
},
message: 'Your milestone sign-off has been recorded. All stakeholders will receive notification of this decision. Please retain a copy for your records.'
});
}
 

Frequently Asked Questions

What is a milestone sign-off?

A milestone sign-off is a formal approval process that confirms a project phase or deliverable has been completed satisfactorily. It typically involves verification of work, quality assessment, and stakeholder approval before proceeding to the next phase.

Who should complete this form?

This form is typically completed by the project manager or site supervisor, with input from quality inspectors and final approval from the client or project sponsor. Multiple parties may need to review and approve the milestone.

What happens if items are incomplete?

If deliverables are incomplete, the form captures punch list items and allows for conditional approval. You can specify what needs to be completed and set a deadline for remediation while still progressing with approved items.

Can this be used for software projects?

Yes, the form is flexible enough for any project type. For software projects, deliverables might include features, documentation, and testing results. The quality assessment and approval workflow remain the same regardless of industry.

How do I handle disputes during sign-off?

The form includes a section for documenting concerns and conditions. If there's a dispute, document the specific issues, proposed resolutions, and any agreed-upon compromises. The form creates an audit trail of the approval process.