export function spaWellnessFeedback(form: FormTs) {
// Spa & Wellness Feedback - Elegant review form for spas and wellness centers
// Demonstrates: StarRating, EmojiRating, MatrixQuestion, Slider, Datepicker, RatingScale, conditional visibility
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'โจ How Was Your Experience?',
computedValue: () => 'Your feedback helps us create the perfect escape',
customStyles: {
background: 'linear-gradient(135deg, #a855f7 0%, #ec4899 100%)',
color: 'white',
padding: '24px',
borderRadius: '16px',
textAlign: 'center'
}
});
});
// ============================================
// SECTION 1: Visit Details
// ============================================
const visitSection = form.addSubform('visitSection', {
title: 'Your Visit',
customStyles: {
backgroundColor: '#fdf4ff',
padding: '16px',
borderRadius: '12px'
}
});
visitSection.addRow(row => {
row.addDatepicker('visitDate', {
label: 'Date of visit',
maxDate: () => new Date().toISOString()
}, '1fr');
row.addDropdown('visitType', {
label: 'Visit type',
options: [
{ id: 'first', name: 'First visit' },
{ id: 'returning', name: 'Returning guest' },
{ id: 'regular', name: 'Regular member' },
{ id: 'package', name: 'Package/Membership holder' }
],
isRequired: true
}, '1fr');
});
visitSection.addRow(row => {
row.addCheckboxList('services', {
label: 'Services received (select all that apply)',
options: [
{ id: 'massage', name: 'Massage therapy' },
{ id: 'facial', name: 'Facial treatment' },
{ id: 'body-treatment', name: 'Body treatment/wrap' },
{ id: 'manicure', name: 'Manicure' },
{ id: 'pedicure', name: 'Pedicure' },
{ id: 'hair', name: 'Hair services' },
{ id: 'sauna', name: 'Sauna/Steam room' },
{ id: 'pool', name: 'Pool/Hydrotherapy' },
{ id: 'meditation', name: 'Meditation/Yoga class' },
{ id: 'other', name: 'Other service' }
],
orientation: 'vertical',
isRequired: true
});
});
// ============================================
// SECTION 2: Overall Experience
// ============================================
const experienceSection = form.addSubform('experienceSection', {
title: 'Overall Experience',
customStyles: { padding: '16px', borderRadius: '12px', border: '1px solid #f0abfc' }
});
experienceSection.addRow(row => {
row.addStarRating('overallRating', {
label: 'How would you rate your overall experience?',
maxStars: 5,
size: 'xl',
alignment: 'center',
filledColor: '#a855f7',
showConfettiOnMax: true
});
});
experienceSection.addRow(row => {
row.addEmojiRating('relaxationLevel', {
label: 'How relaxed do you feel after your visit?',
preset: 'mood',
size: 'lg',
showLabels: true,
alignment: 'center'
});
});
// ============================================
// SECTION 3: Treatment Quality (MatrixQuestion)
// ============================================
const treatmentSection = form.addSubform('treatmentSection', {
title: 'Treatment Quality',
isVisible: () => (visitSection.checkboxList('services')?.value()?.length ?? 0) > 0,
customStyles: { backgroundColor: '#fdf4ff', padding: '16px', borderRadius: '12px' }
});
treatmentSection.addRow(row => {
row.addMatrixQuestion('treatmentRatings', {
label: 'Please rate the following aspects:',
rows: [
{ id: 'skill', label: 'Therapist/practitioner skill', isRequired: true },
{ id: 'pressure', label: 'Pressure/technique (if applicable)' },
{ id: 'products', label: 'Quality of products used' },
{ id: 'timing', label: 'Treatment duration/pacing' },
{ id: 'customization', label: 'Personalization to your needs' }
],
columns: [
{ id: '1', label: 'Poor' },
{ id: '2', label: 'Fair' },
{ id: '3', label: 'Good' },
{ id: '4', label: 'Very Good' },
{ id: '5', label: 'Excellent' }
],
striped: true,
fullWidth: true
});
});
// ============================================
// SECTION 4: Ambiance & Facilities
// ============================================
const ambianceSection = form.addSubform('ambianceSection', {
title: 'Ambiance & Facilities',
customStyles: { padding: '16px', borderRadius: '12px', border: '1px solid #f0abfc' }
});
ambianceSection.addRow(row => {
row.addStarRating('cleanlinessRating', {
label: 'Cleanliness & hygiene',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#a855f7'
}, '1fr');
row.addStarRating('ambianceRating', {
label: 'Atmosphere & ambiance',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#a855f7'
}, '1fr');
});
ambianceSection.addRow(row => {
row.addStarRating('musicRating', {
label: 'Music & sound',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#a855f7'
}, '1fr');
row.addStarRating('scentRating', {
label: 'Aromatherapy & scents',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#a855f7'
}, '1fr');
});
ambianceSection.addRow(row => {
row.addSlider('temperatureComfort', {
label: 'Temperature comfort (was it too cold or too warm?)',
min: 1,
max: 5,
step: 1,
defaultValue: 3,
showValue: false
});
});
ambianceSection.addRow(row => {
row.addTextPanel('temperatureLabels', {
computedValue: () => {
const temp = ambianceSection.slider('temperatureComfort')?.value() ?? 3;
const labels = ['Too Cold', 'Slightly Cold', 'Perfect', 'Slightly Warm', 'Too Warm'];
return `Temperature: ${labels[temp - 1]}`;
},
customStyles: {
textAlign: 'center',
fontSize: '14px',
color: '#6b21a8'
}
});
});
// ============================================
// SECTION 5: Service & Staff
// ============================================
const serviceSection = form.addSubform('serviceSection', {
title: 'Service & Staff',
customStyles: { backgroundColor: '#fdf4ff', padding: '16px', borderRadius: '12px' }
});
serviceSection.addRow(row => {
row.addMatrixQuestion('serviceRatings', {
label: 'How would you rate our service?',
rows: [
{ id: 'booking', label: 'Booking process', isRequired: true },
{ id: 'checkin', label: 'Check-in experience' },
{ id: 'staff-friendliness', label: 'Staff friendliness' },
{ id: 'attentiveness', label: 'Attentiveness to needs' },
{ id: 'checkout', label: 'Check-out and payment' }
],
columns: [
{ id: '1', label: 'Poor' },
{ id: '2', label: 'Fair' },
{ id: '3', label: 'Good' },
{ id: '4', label: 'Very Good' },
{ id: '5', label: 'Excellent' }
],
striped: true,
fullWidth: true
});
});
serviceSection.addRow(row => {
row.addTextbox('therapistName', {
label: 'Your therapist/practitioner name (optional)',
placeholder: 'If you remember their name...'
});
});
serviceSection.addRow(row => {
row.addTextarea('therapistFeedback', {
label: 'Any specific feedback for your therapist?',
placeholder: 'Compliments or suggestions...',
rows: 2,
autoExpand: true,
isVisible: () => (serviceSection.textbox('therapistName')?.value()?.length ?? 0) > 0
});
});
// ============================================
// SECTION 6: Value & Recommendation
// ============================================
const valueSection = form.addSubform('valueSection', {
title: 'Value & Recommendation',
customStyles: { padding: '16px', borderRadius: '12px', border: '1px solid #f0abfc' }
});
valueSection.addRow(row => {
row.addRatingScale('valueForMoney', {
preset: 'likert-5',
label: 'The experience was good value for money',
lowLabel: 'Strongly Disagree',
highLabel: 'Strongly Agree',
alignment: 'center'
});
});
valueSection.addRow(row => {
row.addRatingScale('npsScore', {
preset: 'nps',
label: 'How likely are you to recommend us to friends or family?',
showCategoryLabel: true,
showSegmentColors: true,
showConfettiOnPromoter: true
});
});
// ============================================
// SECTION 7: Follow-up for Low Ratings
// ============================================
const concernsSection = form.addSubform('concernsSection', {
title: 'Help Us Improve',
isVisible: () => {
const overall = experienceSection.starRating('overallRating')?.value() ?? 0;
const nps = valueSection.ratingScale('npsScore')?.value() ?? 10;
return overall <= 3 || nps <= 6;
},
customStyles: { backgroundColor: '#fef3c7', padding: '16px', borderRadius: '12px' }
});
concernsSection.addRow(row => {
row.addSuggestionChips('issueAreas', {
label: 'What areas need improvement?',
suggestions: [
{ id: 'wait-time', name: 'Wait time' },
{ id: 'cleanliness', name: 'Cleanliness' },
{ id: 'treatment', name: 'Treatment quality' },
{ id: 'staff', name: 'Staff attitude' },
{ id: 'noise', name: 'Noise/Disturbances' },
{ id: 'value', name: 'Value for money' },
{ id: 'amenities', name: 'Amenities' },
{ id: 'communication', name: 'Communication' }
],
alignment: 'center'
});
});
concernsSection.addSpacer();
concernsSection.addRow(row => {
row.addTextarea('improvementSuggestions', {
label: 'Please share more details about your concerns',
placeholder: 'Your feedback helps us create a better experience...',
rows: 3,
autoExpand: true
});
});
// ============================================
// SECTION 8: Positive Highlights (for high ratings)
// ============================================
const highlightsSection = form.addSubform('highlightsSection', {
title: 'What Made Your Visit Special?',
isVisible: () => {
const overall = experienceSection.starRating('overallRating')?.value() ?? 0;
return overall >= 4;
},
customStyles: { backgroundColor: '#d1fae5', padding: '16px', borderRadius: '12px' }
});
highlightsSection.addRow(row => {
row.addSuggestionChips('bestParts', {
label: 'What stood out most?',
suggestions: [
{ id: 'relaxation', name: '๐ง Deep relaxation' },
{ id: 'therapist', name: '๐ Skilled therapist' },
{ id: 'ambiance', name: 'โจ Beautiful ambiance' },
{ id: 'products', name: '๐ฟ Quality products' },
{ id: 'service', name: '๐ Excellent service' },
{ id: 'cleanliness', name: '๐งน Spotless facilities' }
],
max: 3,
alignment: 'center'
});
});
highlightsSection.addSpacer();
highlightsSection.addRow(row => {
row.addTextarea('testimonial', {
label: 'Would you like to leave a testimonial? (may be used in marketing)',
placeholder: 'Share your experience in a few words...',
rows: 2,
autoExpand: true
});
});
// ============================================
// SECTION 9: Future Visits
// ============================================
const futureSection = form.addSubform('futureSection', {
title: 'Future Visits'
});
futureSection.addRow(row => {
row.addThumbRating('willReturn', {
label: 'Will you visit us again?',
showLabels: true,
upLabel: 'Definitely!',
downLabel: 'Unlikely',
alignment: 'center',
size: 'lg'
});
});
futureSection.addRow(row => {
row.addCheckboxList('interestedServices', {
label: 'Interested in trying next time?',
options: [
{ id: 'couples', name: 'Couples massage' },
{ id: 'hot-stone', name: 'Hot stone therapy' },
{ id: 'aromatherapy', name: 'Aromatherapy' },
{ id: 'facial', name: 'Signature facial' },
{ id: 'package', name: 'Day spa package' },
{ id: 'membership', name: 'Membership options' }
],
orientation: 'horizontal'
});
});
futureSection.addRow(row => {
row.addCheckbox('receiveOffers', {
label: 'Send me special offers and wellness tips'
});
});
futureSection.addRow(row => {
row.addEmail('email', {
label: 'Email address',
placeholder: 'your@email.com',
isVisible: () => futureSection.checkbox('receiveOffers')?.value() === true,
isRequired: () => futureSection.checkbox('receiveOffers')?.value() === true
});
});
// ============================================
// SUMMARY
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Feedback Summary',
isVisible: () => experienceSection.starRating('overallRating')?.value() !== null
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const overall = experienceSection.starRating('overallRating')?.value() ?? 0;
const relaxation = experienceSection.emojiRating('relaxationLevel')?.value();
const services = visitSection.checkboxList('services')?.value() || [];
const nps = valueSection.ratingScale('npsScore')?.value();
const npsCategory = valueSection.ratingScale('npsScore')?.npsCategory();
const willReturn = futureSection.thumbRating('willReturn')?.value();
const relaxLabels: Record<string, string> = {
'very-bad': '๐ฐ Stressed',
'bad': '๐ Tense',
'neutral': '๐ Okay',
'good': '๐ Relaxed',
'excellent': '๐ง Deeply Relaxed'
};
let summary = 'โจ Spa Visit Summary\n';
summary += 'โ'.repeat(22) + '\n\n';
summary += `Overall: ${'โ
'.repeat(overall)}${'โ'.repeat(5 - overall)}\n`;
summary += `Relaxation: ${relaxLabels[relaxation || ''] || 'Not rated'}\n`;
summary += `Services: ${services.length} received\n`;
if (nps !== null && nps !== undefined) {
summary += `\nNPS: ${nps}/10 (${npsCategory})\n`;
}
summary += `Return Visit: ${willReturn === 'up' ? 'Yes' : willReturn === 'down' ? 'Unlikely' : 'Not answered'}`;
return summary;
},
customStyles: {
padding: '16px',
borderRadius: '12px',
backgroundColor: '#fdf4ff',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '13px',
borderLeft: '4px solid #a855f7'
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: 'Submit Feedback',
isVisible: () => experienceSection.starRating('overallRating')?.value() !== null
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank You for Your Feedback!',
message: 'We appreciate you taking the time to share your experience. Your feedback helps us create the perfect sanctuary for relaxation and wellness.'
});
}