Hi Charlie,
I hope you are well. A small thought for the soon-to-be CS Forms, in case the idea has not hit your radar.
Something I have been requested to do is to create a Q&A choice form to determine the right choice for a potential (big spending) client. In this case, we are talking high-end landscape gardening, where we are trying to help the potential customer understand the difference between a natural swimming pond and a natural swimming pool - and which is best suited to their wishes. The end result would summarise the answers to the questions and give a link to the pool / pond page best suited to the result.
Towards the bottom of this post is some code suggested by Claude.
Obviously, the code, as is, will not render in a Raw Element, but I think you may get the gist of it. I suspect CS Forms could be the perfect vehicle for this sort of thing? What are your thoughts?
import React, { useState } from 'react';
import { ChevronRight, Droplets, Leaf, Users, Home, Clock, Heart } from 'lucide-react';
const SwimmingChoiceCalculator = () => {
const [currentQuestion, setCurrentQuestion] = useState(0);
const [answers, setAnswers] = useState({});
const [showResult, setShowResult] = useState(false);
const questions = [
{
id: 'aesthetic',
question: 'Which aesthetic appeals to you more?',
icon: <Home className="w-6 h-6" />,
options: [
{ value: 'pool', text: 'Clean, structured lines that look like a traditional pool', score: { pool: 3, pond: 0 } },
{ value: 'natural', text: 'Naturalistic appearance that blends with the landscape', score: { pool: 1, pond: 2 } },
{ value: 'wild', text: 'Wild, pond-like with plants and seasonal changes', score: { pool: 0, pond: 3 } }
]
},
{
id: 'wildlife',
question: 'How do you feel about wildlife in your swimming area?',
icon: <Leaf className="w-6 h-6" />,
options: [
{ value: 'avoid', text: 'I prefer to avoid fish, frogs, and insects', score: { pool: 3, pond: 0 } },
{ value: 'minimal', text: 'A little wildlife is fine, but I want clear sight lines', score: { pool: 2, pond: 1 } },
{ value: 'embrace', text: 'I love the idea of swimming alongside nature', score: { pool: 0, pond: 3 } }
]
},
{
id: 'maintenance',
question: 'What\'s your preferred approach to maintenance?',
icon: <Clock className="w-6 h-6" />,
options: [
{ value: 'predictable', text: 'Regular, predictable maintenance tasks', score: { pool: 2, pond: 1 } },
{ value: 'minimal', text: 'Minimal intervention - let nature take its course', score: { pool: 0, pond: 3 } },
{ value: 'seasonal', text: 'Seasonal tasks that connect me with the pond\'s cycle', score: { pool: 1, pond: 2 } }
]
},
{
id: 'family',
question: 'Who will be using this swimming area?',
icon: <Users className="w-6 h-6" />,
options: [
{ value: 'young_children', text: 'Young children who need clear, safe sight lines', score: { pool: 3, pond: 0 } },
{ value: 'mixed_family', text: 'Mixed ages - children and adults', score: { pool: 2, pond: 1 } },
{ value: 'adults', text: 'Primarily adults who appreciate natural experiences', score: { pool: 1, pond: 2 } },
{ value: 'nature_lovers', text: 'Nature enthusiasts of all ages', score: { pool: 0, pond: 3 } }
]
},
{
id: 'experience',
question: 'What swimming experience do you prefer?',
icon: <Droplets className="w-6 h-6" />,
options: [
{ value: 'traditional', text: 'Familiar pool experience with natural benefits', score: { pool: 3, pond: 0 } },
{ value: 'natural', text: 'Swimming in nature, but with some structure', score: { pool: 1, pond: 2 } },
{ value: 'wild', text: 'Wild swimming experience that changes with seasons', score: { pool: 0, pond: 3 } }
]
},
{
id: 'priorities',
question: 'What\'s most important to you?',
icon: <Heart className="w-6 h-6" />,
options: [
{ value: 'safety', text: 'Safety and predictability for family use', score: { pool: 3, pond: 0 } },
{ value: 'balance', text: 'Balance between natural benefits and familiar design', score: { pool: 2, pond: 1 } },
{ value: 'ecology', text: 'Supporting local ecology and biodiversity', score: { pool: 0, pond: 3 } },
{ value: 'experience', text: 'Authentic connection with natural water environments', score: { pool: 0, pond: 3 } }
]
}
];
const handleAnswer = (optionValue, score) => {
const newAnswers = { ...answers, [questions[currentQuestion].id]: { value: optionValue, score } };
setAnswers(newAnswers);
if (currentQuestion < questions.length - 1) {
setCurrentQuestion(currentQuestion + 1);
} else {
calculateResult(newAnswers);
}
};
const calculateResult = (finalAnswers) => {
const scores = Object.values(finalAnswers).reduce(
(acc, answer) => ({
pool: acc.pool + answer.score.pool,
pond: acc.pond + answer.score.pond
}),
{ pool: 0, pond: 0 }
);
setTimeout(() => setShowResult({ scores, recommendation: scores.pool > scores.pond ? 'pool' : 'pond' }), 500);
};
const resetQuiz = () => {
setCurrentQuestion(0);
setAnswers({});
setShowResult(false);
};
if (showResult) {
const { scores, recommendation } = showResult;
const isPool = recommendation === 'pool';
return (
<div className="max-w-2xl mx-auto p-6 bg-white rounded-xl shadow-lg">
<div className="text-center mb-8">
<div className={`inline-flex items-center justify-center w-16 h-16 rounded-full mb-4 ${isPool ? 'bg-blue-100 text-blue-600' : 'bg-green-100 text-green-600'}`}>
{isPool ? <Droplets className="w-8 h-8" /> : <Leaf className="w-8 h-8" />}
</div>
<h2 className="text-2xl font-bold text-gray-800 mb-2">
Your Recommendation: Natural Swimming {isPool ? 'Pool' : 'Pond'}
</h2>
<div className="flex justify-center space-x-8 text-sm text-gray-600 mb-6">
<div>Pool Score: {scores.pool}</div>
<div>Pond Score: {scores.pond}</div>
</div>
</div>
<div className={`p-6 rounded-lg mb-6 ${isPool ? 'bg-blue-50 border-l-4 border-blue-500' : 'bg-green-50 border-l-4 border-green-500'}`}>
{isPool ? (
<div>
<h3 className="font-semibold text-blue-800 mb-3">Natural Swimming Pool is perfect for you because:</h3>
<ul className="space-y-2 text-blue-700">
<li>• You prefer the familiar, safe appearance of traditional pools</li>
<li>• Clear sight lines and unobstructed swimming areas appeal to you</li>
<li>• You want natural water benefits without the wildlife concerns</li>
<li>• Your priority is family-friendly swimming in a controlled environment</li>
</ul>
</div>
) : (
<div>
<h3 className="font-semibold text-green-800 mb-3">Natural Swimming Pond is perfect for you because:</h3>
<ul className="space-y-2 text-green-700">
<li>• You embrace the beauty of natural ecosystems and seasonal changes</li>
<li>• Swimming alongside wildlife and aquatic plants appeals to you</li>
<li>• You prefer minimal intervention and self-sustaining systems</li>
<li>• Your priority is authentic connection with natural water environments</li>
</ul>
</div>
)}
</div>
<div className="flex flex-col sm:flex-row gap-4">
<button
onClick={resetQuiz}
className="flex-1 px-6 py-3 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 transition-colors"
>
Take Quiz Again
</button>
<button
className={`flex-1 px-6 py-3 rounded-lg text-white font-medium transition-colors ${isPool ? 'bg-blue-600 hover:bg-blue-700' : 'bg-green-600 hover:bg-green-700'}`}
>
Learn More About {isPool ? 'Natural Swimming Pools' : 'Natural Swimming Ponds'}
</button>
</div>
</div>
);
}
const question = questions[currentQuestion];
const progress = ((currentQuestion + 1) / questions.length) * 100;
return (
<div className="max-w-2xl mx-auto p-6 bg-white rounded-xl shadow-lg">
<div className="mb-6">
<div className="flex items-center justify-between mb-4">
<h2 className="text-xl font-semibold text-gray-800">Find Your Perfect Swimming Solution</h2>
<span className="text-sm text-gray-500">{currentQuestion + 1} of {questions.length}</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-2">
<div
className="bg-gradient-to-r from-blue-500 to-green-500 h-2 rounded-full transition-all duration-300"
style={{ width: `${progress}%` }}
></div>
</div>
</div>
<div className="mb-8">
<div className="flex items-center mb-4">
<div className="flex items-center justify-center w-10 h-10 bg-gray-100 rounded-full mr-3">
{question.icon}
</div>
<h3 className="text-lg font-medium text-gray-800">{question.question}</h3>
</div>
<div className="space-y-3">
{question.options.map((option, index) => (
<button
key={index}
onClick={() => handleAnswer(option.value, option.score)}
className="w-full p-4 text-left bg-gray-50 hover:bg-gray-100 rounded-lg border border-gray-200 hover:border-gray-300 transition-all duration-200 group"
>
<div className="flex items-center justify-between">
<span className="text-gray-700 group-hover:text-gray-900">{option.text}</span>
<ChevronRight className="w-5 h-5 text-gray-400 group-hover:text-gray-600" />
</div>
</button>
))}
</div>
</div>
<div className="text-center text-sm text-gray-500">
This quiz will help determine whether a Natural Swimming Pool or Natural Swimming Pond better suits your preferences and lifestyle.
</div>
</div>
);
};
export default SwimmingChoiceCalculator;
As ever, have a great day and thanks for your help!
Christopher