export function portfolioReview(form: FormTs) {
// Portfolio Review Form - Creative work evaluation
// Demonstrates: Pages (multi-page wizard), StarRating, MatrixQuestion, RadioButton, SuggestionChips, conditional sections
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Portfolio Review',
computedValue: () => 'Provide structured feedback on creative work',
customStyles: {
backgroundColor: '#0891b2',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// MULTI-PAGE STRUCTURE
// ============================================
const pages = form.addPages('reviewPages', {
heightMode: 'current-page'
});
// ============================================
// PAGE 1: Reviewer Info & First Impressions
// ============================================
const page1 = pages.addPage('impressions');
page1.addRow(row => {
row.addTextPanel('page1Title', {
label: 'Page 1 of 3: First Impressions',
customStyles: {
backgroundColor: '#ecfeff',
padding: '12px 16px',
borderRadius: '8px',
fontWeight: 'bold'
}
});
});
// Reviewer information
const reviewerSection = page1.addSubform('reviewerSection', {
title: 'Reviewer Information',
customStyles: { padding: '16px', borderRadius: '8px', border: '1px solid #cffafe' }
});
reviewerSection.addRow(row => {
row.addDropdown('reviewerRole', {
label: 'Your role',
options: [
{ id: 'hiring', name: 'Hiring manager/Recruiter' },
{ id: 'senior', name: 'Senior designer/Creative' },
{ id: 'mentor', name: 'Mentor/Instructor' },
{ id: 'peer', name: 'Peer reviewer' },
{ id: 'client', name: 'Client/Stakeholder' },
{ id: 'other', name: 'Other' }
],
placeholder: 'Select your role',
isRequired: true
}, '1fr');
row.addDropdown('experienceLevel', {
label: 'Your experience in this field',
options: [
{ id: '1-3', name: '1-3 years' },
{ id: '4-7', name: '4-7 years' },
{ id: '8-15', name: '8-15 years' },
{ id: '15+', name: '15+ years' }
],
placeholder: 'Select experience'
}, '1fr');
});
reviewerSection.addRow(row => {
row.addDropdown('portfolioType', {
label: 'Type of portfolio being reviewed',
options: [
{ id: 'ux-ui', name: 'UX/UI Design' },
{ id: 'graphic', name: 'Graphic Design' },
{ id: 'illustration', name: 'Illustration' },
{ id: 'photography', name: 'Photography' },
{ id: 'motion', name: 'Motion/Animation' },
{ id: 'web', name: 'Web Development' },
{ id: 'mixed', name: 'Mixed/Multi-disciplinary' },
{ id: 'other', name: 'Other creative work' }
],
placeholder: 'Select portfolio type'
});
});
// First impressions
const impressionsSection = page1.addSubform('impressionsSection', {
title: 'First Impressions',
customStyles: () => {
const impression = impressionsSection.emojiRating('firstImpression')?.value();
if (impression === 'excellent' || impression === 'good') {
return { backgroundColor: '#ecfeff', padding: '16px', borderRadius: '8px', borderLeft: '4px solid #0891b2' };
}
if (impression === 'bad' || impression === 'very-bad') {
return { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px', borderLeft: '4px solid #f59e0b' };
}
return { padding: '16px', borderRadius: '8px', border: '1px dashed #67e8f9' };
}
});
impressionsSection.addRow(row => {
row.addEmojiRating('firstImpression', {
label: 'Your first impression of the portfolio',
preset: 'satisfaction',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
impressionsSection.addRow(row => {
row.addStarRating('presentationRating', {
label: 'Portfolio presentation & organization',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#0891b2'
}, '1fr');
row.addStarRating('consistencyRating', {
label: 'Visual consistency & branding',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#0891b2'
}, '1fr');
});
impressionsSection.addRow(row => {
row.addSuggestionChips('standoutQualities', {
label: 'What stood out positively? (select up to 4)',
suggestions: [
{ id: 'creativity', name: 'Creativity' },
{ id: 'technique', name: 'Technical skill' },
{ id: 'variety', name: 'Range of work' },
{ id: 'storytelling', name: 'Storytelling' },
{ id: 'process', name: 'Process documentation' },
{ id: 'results', name: 'Measurable results' },
{ id: 'polish', name: 'Polish & finish' },
{ id: 'personality', name: 'Unique voice/style' }
],
max: 4,
alignment: 'center'
});
});
page1.addRow(row => {
row.addEmpty('1fr');
row.addButton('next1', {
label: 'Next: Individual Pieces',
onClick: () => pages.goToPage('pieces')
});
});
// ============================================
// PAGE 2: Individual Piece Evaluation
// ============================================
const page2 = pages.addPage('pieces');
page2.addRow(row => {
row.addTextPanel('page2Title', {
label: 'Page 2 of 3: Evaluate Key Pieces',
customStyles: {
backgroundColor: '#ecfeff',
padding: '12px 16px',
borderRadius: '8px',
fontWeight: 'bold'
}
});
});
page2.addRow(row => {
row.addTextPanel('page2Instructions', {
computedValue: () => 'Rate 3-5 pieces that best represent the portfolio. Focus on the work that influenced your overall impression.',
customStyles: {
backgroundColor: '#f8fafc',
padding: '12px',
borderRadius: '8px',
fontSize: '14px',
fontStyle: 'italic'
}
});
});
// Piece 1
const piece1Section = page2.addSubform('piece1Section', {
title: 'Piece #1 (Strongest Work)',
customStyles: { padding: '16px', borderRadius: '8px', border: '1px solid #cffafe' }
});
piece1Section.addRow(row => {
row.addTextbox('piece1Name', {
label: 'Project/Piece name',
placeholder: 'e.g., "E-commerce Redesign"',
isRequired: true
});
});
piece1Section.addRow(row => {
row.addStarRating('piece1Overall', {
label: 'Overall quality',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#0891b2'
}, '1fr');
row.addStarRating('piece1Execution', {
label: 'Execution & craft',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#0891b2'
}, '1fr');
});
piece1Section.addRow(row => {
row.addStarRating('piece1Concept', {
label: 'Concept & thinking',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#0891b2'
}, '1fr');
row.addStarRating('piece1Relevance', {
label: 'Relevance & impact',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#0891b2'
}, '1fr');
});
piece1Section.addRow(row => {
row.addTextarea('piece1Comments', {
label: 'Specific feedback on this piece',
placeholder: 'What works well? What could be improved?',
rows: 2,
autoExpand: true
});
});
// Piece 2
const piece2Section = page2.addSubform('piece2Section', {
title: 'Piece #2',
customStyles: { padding: '16px', borderRadius: '8px', border: '1px solid #cffafe' }
});
piece2Section.addRow(row => {
row.addTextbox('piece2Name', {
label: 'Project/Piece name',
placeholder: 'e.g., "Mobile App UI"'
});
});
piece2Section.addRow(row => {
row.addStarRating('piece2Overall', {
label: 'Overall quality',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#0891b2'
}, '1fr');
row.addStarRating('piece2Execution', {
label: 'Execution & craft',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#0891b2'
}, '1fr');
});
piece2Section.addRow(row => {
row.addTextarea('piece2Comments', {
label: 'Feedback',
placeholder: 'Optional comments...',
rows: 2,
autoExpand: true
});
});
// Piece 3
const piece3Section = page2.addSubform('piece3Section', {
title: 'Piece #3',
customStyles: { padding: '16px', borderRadius: '8px', border: '1px solid #cffafe' }
});
piece3Section.addRow(row => {
row.addTextbox('piece3Name', {
label: 'Project/Piece name',
placeholder: 'e.g., "Brand Identity"'
});
});
piece3Section.addRow(row => {
row.addStarRating('piece3Overall', {
label: 'Overall quality',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#0891b2'
}, '1fr');
row.addStarRating('piece3Execution', {
label: 'Execution & craft',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#0891b2'
}, '1fr');
});
piece3Section.addRow(row => {
row.addTextarea('piece3Comments', {
label: 'Feedback',
placeholder: 'Optional comments...',
rows: 2,
autoExpand: true
});
});
page2.addRow(row => {
row.addButton('back2', {
label: 'Back',
onClick: () => pages.goToPage('impressions')
});
row.addEmpty('1fr');
row.addButton('next2', {
label: 'Next: Skills & Recommendation',
onClick: () => pages.goToPage('skills')
});
});
// ============================================
// PAGE 3: Skills Assessment & Recommendation
// ============================================
const page3 = pages.addPage('skills');
page3.addRow(row => {
row.addTextPanel('page3Title', {
label: 'Page 3 of 3: Skills & Recommendation',
customStyles: {
backgroundColor: '#ecfeff',
padding: '12px 16px',
borderRadius: '8px',
fontWeight: 'bold'
}
});
});
// Skills Matrix
const skillsSection = page3.addSubform('skillsSection', {
title: 'Skills Assessment',
customStyles: { padding: '16px', borderRadius: '8px', border: '1px solid #cffafe' }
});
skillsSection.addRow(row => {
row.addMatrixQuestion('skillsMatrix', {
label: 'Evaluate demonstrated skills:',
rows: [
{ id: 'visual', label: 'Visual Design', description: 'Aesthetics, composition, typography', isRequired: true },
{ id: 'conceptual', label: 'Conceptual Thinking', description: 'Problem-solving, strategy', isRequired: true },
{ id: 'technical', label: 'Technical Execution', description: 'Tools, implementation', isRequired: true },
{ id: 'communication', label: 'Communication', description: 'Explaining work, storytelling', isRequired: false },
{ id: 'process', label: 'Design Process', description: 'Research, iteration, testing', isRequired: false }
],
columns: [
{ id: 'cant-assess', label: 'Can\'t Assess' },
{ id: '1', label: 'Developing' },
{ id: '2', label: 'Competent' },
{ id: '3', label: 'Proficient' },
{ id: '4', label: 'Expert' }
],
striped: true,
fullWidth: true
});
});
// Growth areas
const growthSection = page3.addSubform('growthSection', {
title: 'Development Areas'
});
growthSection.addRow(row => {
row.addSuggestionChips('strengthAreas', {
label: 'Strongest areas (select up to 3)',
suggestions: [
{ id: 'visual', name: 'Visual design' },
{ id: 'ux', name: 'User experience' },
{ id: 'branding', name: 'Branding' },
{ id: 'illustration', name: 'Illustration' },
{ id: 'typography', name: 'Typography' },
{ id: 'color', name: 'Color usage' },
{ id: 'layout', name: 'Layout' },
{ id: 'motion', name: 'Motion design' }
],
max: 3,
alignment: 'center'
});
});
growthSection.addRow(row => {
row.addSuggestionChips('growthAreas', {
label: 'Areas needing development (select up to 3)',
suggestions: [
{ id: 'visual', name: 'Visual refinement' },
{ id: 'ux', name: 'UX thinking' },
{ id: 'process', name: 'Process documentation' },
{ id: 'presentation', name: 'Portfolio presentation' },
{ id: 'variety', name: 'Work variety' },
{ id: 'depth', name: 'Project depth' },
{ id: 'writing', name: 'Case study writing' },
{ id: 'results', name: 'Showing results' }
],
max: 3,
alignment: 'center'
});
});
// Overall recommendation
const recommendSection = page3.addSubform('recommendSection', {
title: 'Overall Recommendation',
customStyles: () => {
const rec = recommendSection.radioButton('recommendation')?.value();
if (rec === 'strong-yes' || rec === 'yes') {
return { backgroundColor: '#ecfeff', padding: '16px', borderRadius: '8px', borderLeft: '4px solid #0891b2' };
}
if (rec === 'no' || rec === 'strong-no') {
return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px', borderLeft: '4px solid #ef4444' };
}
return { padding: '16px', borderRadius: '8px', border: '1px dashed #67e8f9' };
}
});
recommendSection.addRow(row => {
row.addRadioButton('recommendation', {
label: 'Overall recommendation',
options: [
{ id: 'strong-yes', name: 'Strong Yes - Exceptional portfolio' },
{ id: 'yes', name: 'Yes - Solid portfolio, meets expectations' },
{ id: 'maybe', name: 'Maybe - Shows potential, needs development' },
{ id: 'no', name: 'No - Significant gaps for this level' },
{ id: 'strong-no', name: 'Strong No - Not ready' }
],
orientation: 'vertical',
isRequired: true
});
});
recommendSection.addRow(row => {
row.addDropdown('suitableLevel', {
label: 'Suitable for what level?',
options: [
{ id: 'intern', name: 'Intern' },
{ id: 'junior', name: 'Junior (0-2 years)' },
{ id: 'mid', name: 'Mid-level (2-5 years)' },
{ id: 'senior', name: 'Senior (5+ years)' },
{ id: 'lead', name: 'Lead/Principal' }
],
placeholder: 'Select appropriate level'
});
});
// Final feedback
const finalSection = page3.addSubform('finalSection', {
title: 'Final Feedback'
});
finalSection.addSpacer();
finalSection.addRow(row => {
row.addTextarea('topStrength', {
label: 'What is the greatest strength of this portfolio?',
placeholder: 'Highlight what works best...',
rows: 2,
autoExpand: true
});
});
finalSection.addRow(row => {
row.addTextarea('topImprovement', {
label: 'What is the single most important thing to improve?',
placeholder: 'One actionable recommendation...',
rows: 2,
autoExpand: true
});
});
finalSection.addRow(row => {
row.addTextarea('additionalNotes', {
label: 'Any additional notes for the portfolio owner?',
placeholder: 'Optional additional feedback...',
rows: 3,
autoExpand: true
});
});
// Summary
const summarySection = page3.addSubform('summarySection', {
title: 'Review Summary'
});
summarySection.addRow(row => {
row.addTextPanel('summary', {
computedValue: () => {
const impression = impressionsSection.emojiRating('firstImpression')?.value();
const presentation = impressionsSection.starRating('presentationRating')?.value();
const piece1 = piece1Section.starRating('piece1Overall')?.value();
const piece2 = piece2Section.starRating('piece2Overall')?.value();
const piece3 = piece3Section.starRating('piece3Overall')?.value();
const recommendation = recommendSection.radioButton('recommendation')?.value();
const level = recommendSection.dropdown('suitableLevel')?.value();
const strengths = growthSection.suggestionChips('strengthAreas')?.value() || [];
const growth = growthSection.suggestionChips('growthAreas')?.value() || [];
const impressionLabels: Record<string, string> = {
'very-bad': 'Weak',
'bad': 'Below expectations',
'neutral': 'Neutral',
'good': 'Positive',
'excellent': 'Excellent'
};
const recommendLabels: Record<string, string> = {
'strong-yes': '✅ Strong Yes',
'yes': '✅ Yes',
'maybe': '🤔 Maybe',
'no': '❌ No',
'strong-no': '❌ Strong No'
};
const levelLabels: Record<string, string> = {
'intern': 'Intern',
'junior': 'Junior',
'mid': 'Mid-level',
'senior': 'Senior',
'lead': 'Lead/Principal'
};
let summary = `📋 PORTFOLIO REVIEW\n`;
summary += `${'═'.repeat(25)}\n\n`;
if (impression) {
summary += `First Impression: ${impressionLabels[impression]}\n`;
}
if (presentation) {
summary += `Presentation: ${'★'.repeat(presentation)}${'☆'.repeat(5 - presentation)}\n`;
}
const pieceRatings = [piece1, piece2, piece3].filter(p => p !== null && p !== undefined) as number[];
if (pieceRatings.length > 0) {
const avg = pieceRatings.reduce((a, b) => a + b, 0) / pieceRatings.length;
summary += `\nPieces Avg: ${avg.toFixed(1)}/5 (${pieceRatings.length} reviewed)\n`;
}
if (strengths.length > 0) {
summary += `\n🌟 Strengths: ${strengths.length}`;
}
if (growth.length > 0) {
summary += `\n📈 Growth areas: ${growth.length}`;
}
if (recommendation) {
summary += `\n\n${recommendLabels[recommendation]}`;
}
if (level) {
summary += `\nLevel: ${levelLabels[level]}`;
}
return summary;
},
customStyles: () => {
const rec = recommendSection.radioButton('recommendation')?.value();
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '13px'
};
if (rec === 'strong-yes' || rec === 'yes') {
return { ...baseStyles, backgroundColor: '#ecfeff', borderLeft: '4px solid #0891b2' };
} else if (rec === 'no' || rec === 'strong-no') {
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
} else if (rec === 'maybe') {
return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
}
return { ...baseStyles, backgroundColor: '#f8fafc', borderLeft: '4px solid #0891b2' };
}
});
});
page3.addRow(row => {
row.addButton('back3', {
label: 'Back',
onClick: () => pages.goToPage('pieces')
});
row.addEmpty('1fr');
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Review',
isVisible: () => {
const currentPage = pages.currentPageIndex();
return currentPage === 2; // Show only on last page (0-indexed)
}
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Review!',
message: 'Your thoughtful feedback will help the portfolio owner grow as a creative professional. We appreciate you taking the time to provide structured, actionable insights.'
});
}