Build a Digital Pet Game - Build a Digital Pet Game

Tell us what’s happening:

I can’t get test 4 to pass. (4. When the input is given a value and the button is pressed, the form should no longer be visible).
I’ve tried many methods for the form view to game view switch but the test isn’t picking up on it. Therefore most of the tests after 4 also keep failing.

Your code so far

/* file: index.tsx */

const { useState } = React;

export enum PetAction {
  EAT = 'EAT',
  PLAY = 'PLAY',
  SLEEP = 'SLEEP',
}

export enum PetMood {
  Happy = 'Happy',
  Excited = 'Excited',
  Content = 'Content',
  Sad = 'Sad',
  Tired = 'Tired',
  Sick = 'Sick',
  Hungry = 'Hungry',
}

export const MOOD_VISUALS: Record<PetMood, string> = {
  [PetMood.Happy]: '😀',
  [PetMood.Excited]: '🤩',
  [PetMood.Content]: '🙂',
  [PetMood.Sad]: '😢',
  [PetMood.Tired]: '🥱',
  [PetMood.Sick]: '🤢',
  [PetMood.Hungry]: '🤤',
};

interface PetStats {
  hunger: number;
  happiness: number;
  energy: number;
}

export const PetGame = () => {
  
  const [isGameStarted, setIsGameStarted] = useState<boolean>(false);
  const [petName, setPetName] = useState<string>('');
  const [errorMsg, setErrorMsg] = useState<string>('');

  const [stats, setStats] = useState<PetStats>({
    hunger: 50,
    happiness: 50,
    energy: 50,
  });

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>): void => {
    e.preventDefault();
    if (petName.trim() === '') {
      setErrorMsg('Please name your pet before starting.');
      return;
    }
    setErrorMsg('');
    setIsGameStarted(true);
  };

  const clamp = (val: number): number => Math.max(0, Math.min(100, val));

  const handleAction = (action: PetAction): void => {
    setStats((prev) => {
      switch (action) {
        case PetAction.EAT:
          return {
            ...prev,
            hunger: clamp(prev.hunger - 15),
            energy: clamp(prev.energy + 10),
          };
        case PetAction.PLAY:
          return {
            ...prev,
            energy: clamp(prev.energy - 15),
            happiness: clamp(prev.happiness + 20),
          };
        case PetAction.SLEEP:
          return {
            ...prev,
            hunger: clamp(prev.hunger + 10),
            energy: clamp(prev.energy + 30),
          };
        default:
          return prev;
      }
    });
  };

  const getPetMood = (): PetMood => {
    if (stats.hunger > 70) return PetMood.Hungry;
    if (stats.energy < 30) return PetMood.Tired;
    if (stats.happiness < 30) return PetMood.Sad;
    if (stats.happiness > 80 && stats.energy > 70) return PetMood.Excited;
    if (stats.happiness > 60) return PetMood.Happy;
    return PetMood.Content;
  };

  const currentMood: PetMood = getPetMood();

  return (
    <div style={{ fontFamily: 'sans-serif', maxWidth: '400px', margin: '20px auto', textAlign: 'center' }}>
      <h1>Digital Pet Game</h1>

      {/* Form View */}
      {!isGameStarted ? (
        <form onSubmit={handleSubmit} style={{ border: '1px solid #ccc', padding: '20px', borderRadius: '8px' }}>
          <label htmlFor="pet-name" style={{ display: 'block', marginBottom: '10px', fontWeight: 'bold' }}>
            What is your pet's name?
          </label>
          <input
            id="pet-name"
            type="text"
            value={petName}
            onChange={(e: React.ChangeEvent<HTMLInputElement>) => setPetName(e.target.value)}
            style={{ padding: '8px', width: '80%', marginBottom: '10px' }}
          />
          {errorMsg && <p style={{ color: 'red', margin: '5px 0' }}>{errorMsg}</p>}
          <button type="submit" style={{ padding: '8px 16px', cursor: 'pointer' }}>
            Start Game
          </button>
        </form>
      ) : (
        /* Game View */
        <div style={{ border: '1px solid #4CAF50', padding: '20px', borderRadius: '8px' }}>
          <h2 className="pet-name" style={{ textTransform: 'capitalize' }}>{petName}</h2>
       
          <div style={{ fontSize: '4rem', margin: '10px 0' }}>
            {MOOD_VISUALS[currentMood]}
          </div>
          <p style={{ fontWeight: 'bold' }}>Mood: {currentMood}</p>

          <div style={{ textAlign: 'left', background: '#f9f9f9', padding: '10px', borderRadius: '4px', margin: '15px 0' }}>
            <div style={{ margin: '5px 0' }}>Hunger: <strong>{stats.hunger}</strong></div>
            <div style={{ margin: '5px 0' }}>Happiness: <strong>{stats.happiness}</strong></div>
            <div style={{ margin: '5px 0' }}>Energy: <strong>{stats.energy}</strong></div>
          </div>

          <div style={{ display: 'flex', justifyContent: 'space-around', marginTop: '15px' }}>
            <button id="eat-action" onClick={() => handleAction(PetAction.EAT)} style={{ padding: '8px 12px' }}>
              Eat
            </button>
            <button id="play-action" onClick={() => handleAction(PetAction.PLAY)} style={{ padding: '8px 12px' }}>
              Play
            </button>
            <button id="sleep-action" onClick={() => handleAction(PetAction.SLEEP)} style={{ padding: '8px 12px' }}>
              Sleep
            </button>
          </div>
        </div>
      )}
    </div>
  );
};

/* file: styles.css */Left as provided by assignment


```html (also untouched)`````````
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Digital Pet Game</title>

    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Tektur:wght@400..900&display=swap" rel="stylesheet">

        <link rel="stylesheet" href="styles.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.development.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.26.5/babel.min.js"></script>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      src="index.tsx"
    ></script>
  </head>
  <body>
    <div id="root"></div>
    <script
      data-plugins="transform-modules-umd"
      type="text/babel"
      data-presets="react"
      data-type="module"
    >
      import { PetGame } from './index.tsx';
      ReactDOM.createRoot(document.getElementById('root')).render(<PetGame />);
    </script>
  </body>
</html>


```

### Your browser information:

User Agent is: <code>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/ (KHTML, like Gecko) Chrome/145.0.0.0 Safari/</code>

### Challenge Information:
Build a Digital Pet Game - Build a Digital Pet Game
https://www.freecodecamp.org/learn/front-end-development-libraries-v9/lab-digital-pet-game/lab-digital-pet-game
GitHub Link: https://github.com/freeCodeCamp/freeCodeCamp/blob/main/curriculum/challenges/english/blocks/lab-digital-pet-game/68c362b379059c388d3874f2.md

Hey @Akeem

So I went through the lab file and found out that test sets the input value using DOM API
document.querySelector('#pet-name').value = 'Fluffy';, but your input is a controlled component. That direct DOM manipulation does not fire React’s onChange so petName stays as “” and you fail the test. So read the value directly from the DOM inside instead of relying on react state.