CS Forms - Ahead of Time Request

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

2 Likes

Hey @whitemedia,

Thank you for your feedback. We have added this to our list of feature request so it will have a chance to be included in a future version.

Stay tuned for updates.