export function repeatPurchase(form: FormTs) {
// Repeat Customer Survey - Loyalty drivers and retention insights
// Demonstrates: RatingScale (NPS), MatrixQuestion, StarRating, SuggestionChips,
// Slider, dynamic styling, conditional visibility, computed summaries
// ============================================
// STATE
// ============================================
const purchaseCount = form.state<string | null>(null);
const overallSatisfaction = form.state<number | null>(null);
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Welcome Back!',
computedValue: () => 'We\'d love to hear about your experience as a returning customer.',
customStyles: {
background: 'linear-gradient(135deg, #f59e0b 0%, #ea580c 100%)',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center',
fontSize: '14px'
}
});
});
// ============================================
// SECTION 1: PURCHASE HISTORY
// ============================================
const historySection = form.addSubform('historySection', {
title: 'Your Shopping History',
customStyles: {
backgroundColor: '#fffbeb',
padding: '16px',
borderRadius: '8px'
}
});
historySection.addRow(row => {
row.addRadioButton('purchaseFrequency', {
label: 'How many times have you purchased from us?',
options: [
{ id: '2', name: 'This is my 2nd purchase' },
{ id: '3-5', name: '3-5 purchases' },
{ id: '6-10', name: '6-10 purchases' },
{ id: '10+', name: 'More than 10 purchases' }
],
orientation: 'vertical',
onValueChange: (v) => purchaseCount.set(v ?? null)
});
});
historySection.addRow(row => {
row.addDropdown('shoppingDuration', {
label: 'How long have you been shopping with us?',
options: [
{ id: 'month', name: 'Less than a month' },
{ id: '1-6months', name: '1-6 months' },
{ id: '6-12months', name: '6-12 months' },
{ id: '1-2years', name: '1-2 years' },
{ id: '2+years', name: 'More than 2 years' }
],
placeholder: 'Select duration...'
});
});
// ============================================
// SECTION 2: LOYALTY DRIVERS
// ============================================
const driversSection = form.addSubform('driversSection', {
title: 'What Keeps You Coming Back?',
isVisible: () => purchaseCount() !== null,
customStyles: {
backgroundColor: '#fef3c7',
padding: '16px',
borderRadius: '8px'
}
});
driversSection.addRow(row => {
row.addMatrixQuestion('loyaltyDrivers', {
label: 'Rate how important each factor is in your decision to return:',
rows: [
{ id: 'quality', label: 'Product quality', isRequired: true },
{ id: 'price', label: 'Price & value' },
{ id: 'service', label: 'Customer service' },
{ id: 'convenience', label: 'Shopping convenience' },
{ id: 'selection', label: 'Product selection' },
{ id: 'delivery', label: 'Delivery experience' },
{ id: 'trust', label: 'Brand trust' }
],
columns: [
{ id: 'notImportant', label: 'Not Important' },
{ id: 'somewhat', label: 'Somewhat' },
{ id: 'important', label: 'Important' },
{ id: 'critical', label: 'Critical' }
],
fullWidth: true
});
});
driversSection.addRow(row => {
row.addSuggestionChips('topReasons', {
label: 'Top 3 reasons you keep shopping with us:',
suggestions: [
{ id: 'quality', name: 'Great quality' },
{ id: 'prices', name: 'Best prices' },
{ id: 'service', name: 'Amazing service' },
{ id: 'fast', name: 'Fast shipping' },
{ id: 'returns', name: 'Easy returns' },
{ id: 'rewards', name: 'Loyalty rewards' },
{ id: 'exclusive', name: 'Exclusive products' },
{ id: 'experience', name: 'Great experience' }
],
max: 3,
alignment: 'center'
});
});
// ============================================
// SECTION 3: SATISFACTION RATINGS
// ============================================
const satisfactionSection = form.addSubform('satisfactionSection', {
title: 'Your Satisfaction',
isVisible: () => purchaseCount() !== null
});
satisfactionSection.addRow(row => {
row.addStarRating('overallRating', {
label: 'Overall satisfaction with us as a repeat customer',
maxStars: 5,
size: 'lg',
alignment: 'center',
showConfettiOnMax: true,
onValueChange: (v) => overallSatisfaction.set(v ?? null)
});
});
satisfactionSection.addRow(row => {
row.addStarRating('productRating', {
label: 'Product quality consistency',
maxStars: 5,
size: 'md',
alignment: 'center'
}, '1fr');
row.addStarRating('serviceRating', {
label: 'Service quality over time',
maxStars: 5,
size: 'md',
alignment: 'center'
}, '1fr');
});
satisfactionSection.addRow(row => {
row.addEmojiRating('experienceMood', {
label: 'How do you feel about shopping with us?',
preset: 'satisfaction',
size: 'lg',
alignment: 'center'
});
});
// ============================================
// SECTION 4: NPS & RECOMMENDATION
// ============================================
const npsSection = form.addSubform('npsSection', {
title: 'Would You Recommend Us?',
isVisible: () => overallSatisfaction() !== null,
customStyles: () => {
const score = npsSection.ratingScale('npsScore')?.npsCategory();
if (score === 'promoter') return { backgroundColor: '#dcfce7', padding: '16px', borderRadius: '8px' };
if (score === 'passive') return { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '8px' };
if (score === 'detractor') return { backgroundColor: '#fee2e2', padding: '16px', borderRadius: '8px' };
return { padding: '16px', borderRadius: '8px', border: '1px dashed #cbd5e1' };
}
});
npsSection.addRow(row => {
row.addRatingScale('npsScore', {
label: 'How likely are you to recommend us to friends or family?',
preset: 'nps',
showSegmentColors: true,
showCategoryLabel: true,
showConfettiOnPromoter: true,
alignment: 'center'
});
});
npsSection.addRow(row => {
row.addTextarea('npsReason', {
label: () => {
const category = npsSection.ratingScale('npsScore')?.npsCategory();
if (category === 'promoter') return 'What would you tell them about us?';
if (category === 'detractor') return 'What would make you more likely to recommend us?';
return 'Any specific feedback?';
},
placeholder: 'Share your thoughts...',
rows: 3,
isVisible: () => npsSection.ratingScale('npsScore')?.value() !== null
});
});
// ============================================
// SECTION 5: COMPARISON & COMPETITION
// ============================================
const comparisonSection = form.addSubform('comparisonSection', {
title: 'How We Compare',
isVisible: () => npsSection.ratingScale('npsScore')?.value() !== null
});
comparisonSection.addRow(row => {
row.addRadioButton('competitorShopping', {
label: 'Do you also shop at our competitors?',
options: [
{ id: 'exclusively', name: 'No, I shop exclusively with you' },
{ id: 'mostly', name: 'Sometimes, but mostly here' },
{ id: 'equally', name: 'About equally' },
{ id: 'lessHere', name: 'I shop more elsewhere' }
],
orientation: 'vertical'
});
});
comparisonSection.addRow(row => {
row.addSlider('pricePerception', {
label: 'How do our prices compare to competitors?',
min: 1,
max: 5,
step: 1,
showValue: false,
defaultValue: 3
});
});
comparisonSection.addRow(row => {
row.addTextPanel('priceLabels', {
computedValue: () => {
const value = comparisonSection.slider('pricePerception')?.value() ?? 3;
const labels = ['Much higher', 'Slightly higher', 'About the same', 'Slightly lower', 'Much lower'];
return `Price perception: ${labels[value - 1]}`;
},
customStyles: {
textAlign: 'center',
fontSize: '13px',
color: '#6b7280'
}
});
});
// ============================================
// SECTION 6: FUTURE INTENT
// ============================================
const intentSection = form.addSubform('intentSection', {
title: 'Looking Ahead',
isVisible: () => comparisonSection.radioButton('competitorShopping')?.value() !== null
});
intentSection.addRow(row => {
row.addThumbRating('willReturn', {
label: 'Will you continue shopping with us?',
showLabels: true,
upLabel: 'Yes, definitely!',
downLabel: 'Probably not',
alignment: 'center',
size: 'lg'
});
});
intentSection.addRow(row => {
row.addCheckboxList('futureInterest', {
label: 'What would make you shop with us more?',
options: [
{ id: 'discounts', name: 'More discounts/promotions' },
{ id: 'loyalty', name: 'Better loyalty program' },
{ id: 'selection', name: 'Wider product selection' },
{ id: 'delivery', name: 'Faster/cheaper delivery' },
{ id: 'app', name: 'Better mobile app' },
{ id: 'personalization', name: 'More personalized recommendations' }
],
orientation: 'vertical',
max: 3
});
});
// ============================================
// SECTION 7: SUMMARY
// ============================================
const summarySection = form.addSubform('summarySection', {
title: 'Your Loyalty Profile',
isVisible: () => intentSection.thumbRating('willReturn')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('loyaltySummary', {
computedValue: () => {
const purchases = purchaseCount();
const satisfaction = overallSatisfaction();
const nps = npsSection.ratingScale('npsScore')?.value();
const npsCategory = npsSection.ratingScale('npsScore')?.npsCategory();
const willReturn = intentSection.thumbRating('willReturn')?.value();
let loyaltyLevel = 'Evaluating';
if (npsCategory === 'promoter' && willReturn === 'up') loyaltyLevel = 'Champion';
else if ((npsCategory === 'promoter' || npsCategory === 'passive') && willReturn === 'up') loyaltyLevel = 'Loyal';
else if (npsCategory === 'passive') loyaltyLevel = 'At Risk';
else if (npsCategory === 'detractor') loyaltyLevel = 'Needs Attention';
let emoji = '🏆';
if (loyaltyLevel === 'Loyal') emoji = '💎';
else if (loyaltyLevel === 'At Risk') emoji = '⚠️';
else if (loyaltyLevel === 'Needs Attention') emoji = '🔔';
let summary = `${emoji} Loyalty Profile\n`;
summary += `${'═'.repeat(25)}\n\n`;
summary += `📊 Purchase History: ${purchases || 'Not specified'}\n`;
summary += `⭐ Satisfaction: ${satisfaction ? satisfaction + '/5' : 'Not rated'}\n`;
summary += `📈 NPS Score: ${nps ?? 'Not rated'}${npsCategory ? ` (${npsCategory})` : ''}\n`;
summary += `🔄 Will Return: ${willReturn === 'up' ? 'Yes' : willReturn === 'down' ? 'No' : 'Undecided'}\n`;
summary += `\n${'─'.repeat(25)}\n`;
summary += `🎯 Loyalty Level: ${loyaltyLevel}`;
return summary;
},
customStyles: () => {
const npsCategory = npsSection.ratingScale('npsScore')?.npsCategory();
const willReturn = intentSection.thumbRating('willReturn')?.value();
const baseStyles = {
padding: '20px',
borderRadius: '12px',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px'
};
if (npsCategory === 'promoter' && willReturn === 'up') {
return { ...baseStyles, background: 'linear-gradient(135deg, #dcfce7 0%, #bbf7d0 100%)', borderLeft: '4px solid #22c55e' };
}
if (npsCategory === 'detractor' || willReturn === 'down') {
return { ...baseStyles, background: 'linear-gradient(135deg, #fee2e2 0%, #fecaca 100%)', borderLeft: '4px solid #ef4444' };
}
return { ...baseStyles, background: 'linear-gradient(135deg, #fef3c7 0%, #fde68a 100%)', borderLeft: '4px solid #f59e0b' };
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: () => {
const npsCategory = npsSection.ratingScale('npsScore')?.npsCategory();
if (npsCategory === 'promoter') return 'Submit & Thanks for Your Loyalty!';
return 'Submit Feedback';
},
isVisible: () => intentSection.thumbRating('willReturn')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: () => {
const npsCategory = npsSection.ratingScale('npsScore')?.npsCategory();
if (npsCategory === 'promoter') return 'Thank You, Valued Customer!';
if (npsCategory === 'detractor') return 'We Appreciate Your Honesty';
return 'Thank You for Your Feedback!';
},
message: () => {
const npsCategory = npsSection.ratingScale('npsScore')?.npsCategory();
if (npsCategory === 'promoter') {
return 'Your loyalty means the world to us! As a thank you, check your email for an exclusive offer.';
}
if (npsCategory === 'detractor') {
return 'We value your candid feedback. Our team will review your concerns and work to improve your experience.';
}
return 'Your insights help us serve you better. We\'re grateful for your continued support!';
}
});
}