Skip to content

04-interactive-exercises

Chapter 4: Interactive Learning Exercises

In our journey so far, we've covered the app's structure with the EI Content Model, its visual style with the Reusable UI System (Shadcn/ui), and how we measure progress with the Assessment & Scoring Engine. We know what users learn and how they're tested.

But learning isn't just about reading and taking tests. True growth comes from applying what you've learned to your own life. This is where Interactive Learning Exercises come in.

The Problem: From Knowing to Doing

Imagine reading a fantastic cookbook. You learn all about the science of baking and the theory behind a perfect cake. But until you actually go into the kitchen, crack some eggs, and get flour on your hands, you haven't really learned how to bake.

Our app is the same. The lessons are the cookbook, but the Interactive Learning Exercises are the kitchen. They are the practical "homework" assignments that bridge the gap between theory and real-world practice. They allow users to track emotions, reflect on values, and set goals, making the learning process active, personal, and transformative.

Our Toolkit for Personal Growth

Our app provides several hands-on tools. Think of them as a personal development toolkit:

  • FeelingsTracker: A daily emotional journal.
  • BackwardGlanceExercise: A deep reflection on what you truly value.
  • Goal Setting: A structured way to plan and track your personal development.

Let's take a closer look at one of these tools, the BackwardGlanceExercise, to see how it works.

A Look Inside: The BackwardGlanceExercise

The "Backward Glance" is a powerful exercise. It asks you to imagine you're at the end of your life, looking back. It then asks you to rank a list of 10 values (like Health, Family, Wealth) from two perspectives:

  1. Vision: How you wish you had prioritized them.
  2. Reality: How you actually spend your time and energy today.

The gap between these two columns reveals powerful insights about your life.

Building this exercise is surprisingly straightforward. We use our "Lego blocks" from the Reusable UI System (Shadcn/ui) to create the layout.

The core of the UI is simply a loop that displays each value next to two input boxes.

// client/src/components/backward-glance-exercise.tsx

// A list of values to reflect on
const VALUES = [
  "Wealth (the amount of money you have)",
  "Family (however you define it)",
  // ... more values
];

// ... inside the component
{VALUES.map((value, index) => (
  <div key={index} className="grid grid-cols-12 items-center">
    <Input /* for Vision rank */ />
    <Label>{value}</Label>
    <Input /* for Reality rank */ />
  </div>
))}

This tiny snippet is responsible for creating the main part of the form. It takes our array of VALUES and, for each one, creates a row with an input for "Vision," the value's description, and an input for "Reality."

Making it Interactive: Remembering Your Answers

An exercise isn't very useful if it forgets your answers the moment you type them. We need a way to store the user's input right in the browser. For this, we use a fundamental React concept called "state."

Think of state as the component's short-term memory.

// client/src/components/backward-glance-exercise.tsx

// Create empty "memory boxes" to store the user's rankings
const [visionRankings, setVisionRankings] = useState({});
const [actualRankings, setActualRankings] = useState({});

// A function to update our memory when the user types
const handleVisionChange = (index: number, value: string) => {
  setVisionRankings(prev => ({ ...prev, [index]: value }));
};
  • useState({}) creates an empty object in the browser's memory to hold the rankings.
  • When a user types a number into a "Vision" input box, the handleVisionChange function is called. It takes the user's input (value) and saves it into our visionRankings memory box.

This ensures that the component remembers what you've typed as you fill out the form. But what happens when you close the page? To save your work permanently, we need to send it to the server.

Under the Hood: Saving Your Reflections

When you click the "Save" button, we need to take the rankings stored in the component's "state" and send them to our server to be stored in the database. This ensures you can come back later and see your previous reflections.

Here’s the journey your data takes:

Loading diagram...

To perform this "save" action, we use a special tool that we'll explore fully in the Server State Management (React Query) chapter. For now, just think of useMutation as a dedicated function for changing data on the server.

// client/src/components/backward-glance-exercise.tsx

// A helper for saving data to the server
const saveMutation = useMutation({
  mutationFn: async (data) => {
    // This function tells our helper HOW to save the data
    await fetch('/api/users/1/backward-glance', {
      method: 'POST',
      body: JSON.stringify(data),
    });
  }
});

This code sets up our "save helper." The mutationFn is the specific instruction: when it's time to save, send the data to the /api/users/1/backward-glance URL. This URL is one of our API Endpoints & Session Management definitions.

Finally, we connect this helper to the "Save" button.

// client/src/components/backward-glance-exercise.tsx

const saveResponses = () => {
  // Tell our helper to save the current rankings
  saveMutation.mutate({ visionRankings, actualRankings });
};
// ...
<Button onClick={saveResponses}>
  Save
</Button>

When the user clicks the button, it calls saveResponses, which triggers our saveMutation helper, sending the data on its journey to the server where it's kept safe by our Server-Side Storage Abstraction (IStorage).

Conclusion

Interactive Learning Exercises are the soul of the app. They transform it from a passive information source into an active, personal growth partner. By providing hands-on tools like the FeelingsTracker and BackwardGlanceExercise, we empower users to apply EI concepts directly to their own lives, bridging the critical gap between knowing and doing. These exercises are where the real-world change happens.

So far, we've explored the content, the UI, the tests, and the exercises. But how do we protect all of this valuable content and ensure only authorized users can access it?

In the next chapter, we'll dive into how we manage access to different parts of our application with the Application Router & Auth Guard.


Documented by [Jonny Scott]