export function productReviewSurvey(form: FormTs) {
// Product Review Form - E-commerce Product Rating and Feedback
// Demonstrates: StarRating (multiple), SuggestionChips (pros/cons), MatrixQuestion, ThumbRating, conditional sections, dynamic styling
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Write a Product Review',
computedValue: () => 'Share your experience to help other shoppers make informed decisions.',
customStyles: {
backgroundColor: '#f97316',
color: 'white',
padding: '24px',
borderRadius: '12px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Overall Rating
// ============================================
const overallSection = form.addSubform('overallSection', {
title: 'Overall Rating',
customStyles: () => {
const rating = overallSection.starRating('overallRating')?.value() || 0;
if (rating >= 4) return { backgroundColor: '#d1fae5', padding: '16px', borderRadius: '8px' };
if (rating >= 3) return { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' };
if (rating >= 1) return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { backgroundColor: '#f8fafc', padding: '16px', borderRadius: '8px' };
}
});
overallSection.addRow(row => {
row.addStarRating('overallRating', {
label: 'How would you rate this product overall?',
maxStars: 5,
size: 'xl',
alignment: 'center',
showConfettiOnMax: true
});
});
// Dynamic message based on rating
overallSection.addRow(row => {
row.addTextPanel('ratingMessage', {
computedValue: () => {
const rating = overallSection.starRating('overallRating')?.value();
switch (rating) {
case 5: return '🎉 Excellent! We\'re thrilled you love it!';
case 4: return '👍 Great! Thanks for the positive feedback!';
case 3: return '😐 Thanks for your honest feedback.';
case 2: return '😕 We\'re sorry it didn\'t meet expectations.';
case 1: return '😞 We\'re sorry to hear that. Please tell us more.';
default: return '';
}
},
customStyles: {
textAlign: 'center',
fontStyle: 'italic',
marginTop: '8px'
},
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
});
// ============================================
// SECTION 2: Category Ratings
// ============================================
const categorySection = form.addSubform('categorySection', {
title: 'Rate Specific Aspects',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
categorySection.addRow(row => {
row.addStarRating('qualityRating', {
label: 'Quality',
maxStars: 5,
size: 'md',
alignment: 'center'
}, '1fr');
row.addStarRating('valueRating', {
label: 'Value for Money',
maxStars: 5,
size: 'md',
alignment: 'center'
}, '1fr');
});
categorySection.addRow(row => {
row.addStarRating('durabilityRating', {
label: 'Durability',
maxStars: 5,
size: 'md',
alignment: 'center'
}, '1fr');
row.addStarRating('appearanceRating', {
label: 'Appearance',
maxStars: 5,
size: 'md',
alignment: 'center'
}, '1fr');
});
// ============================================
// SECTION 3: Fit & Size (conditional for applicable products)
// ============================================
const fitSection = form.addSubform('fitSection', {
title: 'Fit & Sizing',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
fitSection.addRow(row => {
row.addRadioButton('productHasFit', {
label: 'Does this product have fit/sizing aspects?',
options: [
{ id: 'yes', name: 'Yes (clothing, shoes, etc.)' },
{ id: 'no', name: 'No (electronics, home goods, etc.)' }
],
orientation: 'horizontal'
});
});
fitSection.addRow(row => {
row.addRatingScale('fitScale', {
preset: 'custom',
min: 1,
max: 5,
label: 'How does the sizing run?',
lowLabel: 'Runs Small',
highLabel: 'Runs Large',
alignment: 'center',
isVisible: () => fitSection.radioButton('productHasFit')?.value() === 'yes'
});
});
fitSection.addRow(row => {
row.addRadioButton('fitAccuracy', {
label: 'Did the product fit as expected based on the size guide?',
options: [
{ id: 'yes', name: 'Yes, perfect fit' },
{ id: 'close', name: 'Close, minor adjustments needed' },
{ id: 'no', name: 'No, sizing was off' }
],
orientation: 'horizontal',
isVisible: () => fitSection.radioButton('productHasFit')?.value() === 'yes'
});
});
// ============================================
// SECTION 4: Pros & Cons
// ============================================
const prosConsSection = form.addSubform('prosConsSection', {
title: 'What Did You Like & Dislike?',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
prosConsSection.addRow(row => {
row.addSuggestionChips('pros', {
label: 'Pros - What did you like? (Select up to 5)',
suggestions: [
{ id: 'quality', name: 'Great quality' },
{ id: 'value', name: 'Good value' },
{ id: 'looks', name: 'Looks great' },
{ id: 'comfortable', name: 'Comfortable' },
{ id: 'durable', name: 'Durable' },
{ id: 'easy-use', name: 'Easy to use' },
{ id: 'fast-shipping', name: 'Fast shipping' },
{ id: 'good-packaging', name: 'Nice packaging' },
{ id: 'as-described', name: 'As described' },
{ id: 'exceeded', name: 'Exceeded expectations' }
],
max: 5,
alignment: 'left'
});
});
prosConsSection.addSpacer({ height: '16px' });
prosConsSection.addRow(row => {
row.addSuggestionChips('cons', {
label: 'Cons - What could be improved? (Select up to 5)',
suggestions: [
{ id: 'quality', name: 'Quality issues' },
{ id: 'pricey', name: 'Overpriced' },
{ id: 'looks-diff', name: 'Looks different than photos' },
{ id: 'uncomfortable', name: 'Uncomfortable' },
{ id: 'fragile', name: 'Fragile' },
{ id: 'complicated', name: 'Complicated to use' },
{ id: 'slow-shipping', name: 'Slow shipping' },
{ id: 'poor-packaging', name: 'Poor packaging' },
{ id: 'not-as-described', name: 'Not as described' },
{ id: 'none', name: 'No complaints' }
],
max: 5,
alignment: 'left'
});
});
// ============================================
// SECTION 5: Written Review
// ============================================
const reviewSection = form.addSubform('reviewSection', {
title: 'Write Your Review',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
reviewSection.addRow(row => {
row.addTextbox('reviewTitle', {
label: 'Review Title',
placeholder: 'Summarize your experience in a few words...',
maxLength: 100,
isRequired: true
});
});
reviewSection.addSpacer();
reviewSection.addRow(row => {
row.addTextarea('reviewBody', {
label: 'Detailed Review',
placeholder: 'Share details about your experience with this product. What did you use it for? How did it perform? Would you buy it again?',
rows: 4,
autoExpand: true,
maxLength: 2000
});
});
// ============================================
// SECTION 6: Recommendation
// ============================================
const recommendSection = form.addSubform('recommendSection', {
title: 'Would You Recommend?',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null,
customStyles: () => {
const recommend = recommendSection.thumbRating('wouldRecommend')?.value();
if (recommend === 'up') return { backgroundColor: '#d1fae5', padding: '16px', borderRadius: '8px' };
if (recommend === 'down') return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { padding: '16px', borderRadius: '8px', border: '1px dashed #e2e8f0' };
}
});
recommendSection.addRow(row => {
row.addThumbRating('wouldRecommend', {
label: 'Would you recommend this product to a friend?',
showLabels: true,
upLabel: 'Yes, I recommend it',
downLabel: 'No, I wouldn\'t recommend',
size: 'lg',
alignment: 'center'
});
});
recommendSection.addRow(row => {
row.addThumbRating('wouldBuyAgain', {
label: 'Would you purchase this product again?',
showLabels: true,
upLabel: 'Yes',
downLabel: 'No',
alignment: 'center',
isVisible: () => recommendSection.thumbRating('wouldRecommend')?.value() !== null
});
});
// ============================================
// SECTION 7: Purchase Context
// ============================================
const contextSection = form.addSubform('contextSection', {
title: 'About Your Purchase',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
contextSection.addRow(row => {
row.addDropdown('purchasePurpose', {
label: 'Why did you buy this product?',
options: [
{ id: 'myself', name: 'For myself' },
{ id: 'gift', name: 'As a gift' },
{ id: 'work', name: 'For work/business' },
{ id: 'replace', name: 'To replace an old one' },
{ id: 'try', name: 'To try something new' }
],
placeholder: 'Select'
}, '1fr');
row.addDropdown('howLongUsed', {
label: 'How long have you been using it?',
options: [
{ id: 'just-received', name: 'Just received it' },
{ id: 'few-days', name: 'A few days' },
{ id: 'week', name: 'About a week' },
{ id: 'few-weeks', name: 'A few weeks' },
{ id: 'month-plus', name: 'Over a month' }
],
placeholder: 'Select'
}, '1fr');
});
// ============================================
// SECTION 8: Reviewer Info (optional)
// ============================================
const reviewerSection = form.addSubform('reviewerSection', {
title: 'About You (Optional)',
isVisible: () => overallSection.starRating('overallRating')?.value() !== null
});
reviewerSection.addRow(row => {
row.addTextbox('reviewerName', {
label: 'Display Name',
placeholder: 'How should we display your name?'
}, '1fr');
row.addTextbox('reviewerLocation', {
label: 'Location',
placeholder: 'City, State/Country'
}, '1fr');
});
reviewerSection.addRow(row => {
row.addCheckbox('verifiedPurchaser', {
label: 'I confirm this is a genuine review of a product I purchased'
});
});
// ============================================
// SECTION 9: Summary
// ============================================
const summarySection = form.addSubform('summarySection', {
title: 'Review Summary',
isVisible: () => {
const title = reviewSection.textbox('reviewTitle')?.value();
return title !== null && title !== undefined && title.length > 0;
}
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const overall = overallSection.starRating('overallRating')?.value();
const quality = categorySection.starRating('qualityRating')?.value();
const value = categorySection.starRating('valueRating')?.value();
const title = reviewSection.textbox('reviewTitle')?.value();
const recommend = recommendSection.thumbRating('wouldRecommend')?.value();
const pros = prosConsSection.suggestionChips('pros')?.value() || [];
const cons = prosConsSection.suggestionChips('cons')?.value() || [];
if (!overall || !title) return '';
let summary = `PRODUCT REVIEW\n`;
summary += `${'═'.repeat(26)}\n\n`;
summary += `"${title}"\n\n`;
summary += `Overall: ${'★'.repeat(overall)}${'☆'.repeat(5 - overall)} (${overall}/5)\n`;
if (quality) {
summary += `Quality: ${'★'.repeat(quality)}${'☆'.repeat(5 - quality)}\n`;
}
if (value) {
summary += `Value: ${'★'.repeat(value)}${'☆'.repeat(5 - value)}\n`;
}
summary += `\n`;
if (pros.length > 0) {
summary += `✓ Pros: ${pros.length} selected\n`;
}
if (cons.length > 0 && !cons.includes('none')) {
summary += `✗ Cons: ${cons.length} selected\n`;
}
if (recommend) {
summary += `\nRecommends: ${recommend === 'up' ? 'Yes 👍' : 'No 👎'}`;
}
return summary;
},
customStyles: () => {
const overall = overallSection.starRating('overallRating')?.value() || 0;
const baseStyles = {
padding: '16px',
borderRadius: '8px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '13px'
};
if (overall >= 4) {
return { ...baseStyles, backgroundColor: '#d1fae5', borderLeft: '4px solid #10b981' };
} else if (overall >= 3) {
return { ...baseStyles, backgroundColor: '#fef3c7', borderLeft: '4px solid #f59e0b' };
}
return { ...baseStyles, backgroundColor: '#fee2e2', borderLeft: '4px solid #ef4444' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Review',
isVisible: () => {
const rating = overallSection.starRating('overallRating')?.value();
const title = reviewSection.textbox('reviewTitle')?.value();
return rating !== null && title !== null && title !== undefined && title.length > 0;
}
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Review!',
message: 'Your feedback helps other shoppers make better decisions and helps us improve our products. Your review will be published after a quick review.'
});
}