All files / Hungry-Hippo-Game/src/pages/AacPage AacPage.tsx

0% Statements 0/103
0% Branches 0/1
0% Functions 0/1
0% Lines 0/103

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103                                                                                                                                                                                                             
import React, { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import AacInterface from '../../aac/AacInterface';
import { useWebSocket } from '../../contexts/WebSocketContext';
import { EventBus } from '../../game/EventBus';

/**
 * Route parameters from the URL.
 */
interface RouteParams {
  sessionId?: string;
  userId?: string;
  role?: string;
  [key: string]: string | undefined; 
}

/**
 * AacPage component.
 *
 * Renders the AAC interface
 * for selecting food items within a given session.
 *
 * @component
 * @returns {JSX.Element} The AAC interface or a message if sessionId is missing.
 */
const AacPage: React.FC = () => {
  /**
   * Extracts the sessionId, userId, role from the URL parameters.
   */
  const { sessionId, userId, role } = useParams<RouteParams>();

  /**
   * Use the useNavigate hook from react-router-dom to navigate programmatically.
   */
  const navigate = useNavigate();
  
  /**
   * Get last message and connectedUsers from WebSocket context.
   */
  const { lastMessage, connectedUsers, clearLastMessage } = useWebSocket();

  /**
   * State to hold scores for the game.
   */
  const [scores, setScores] = useState<Record<string, number>>({});

  // --- ERROR HANDLING ---
  useEffect(() => {
    if (lastMessage?.type === 'ERROR_MESSAGE' && lastMessage?.payload?.code === 'SESSION_NOT_FOUND') {
      alert(`An error occurred: ${lastMessage.payload.message}`);
      clearLastMessage?.();
      navigate('/');
    }
  }, [lastMessage, navigate, clearLastMessage]);

  /**
   * Effect hook to listen for score updates from the EventBus.
   * Updates the scores state when a 'scoreUpdate' event is emitted.
   */
  useEffect(() => {
    const handleScoreUpdate = ({ scores }: { scores: Record<string, number> }) => {
      setScores(scores);
    };

    EventBus.on('scoreUpdate', handleScoreUpdate);
    return () => {
      EventBus.off('scoreUpdate', handleScoreUpdate);
    };
  }, []);

  /**
   * If GAME_OVER use the navigate function to navigate to different routes.
   */
  useEffect(() => {
    if (lastMessage?.type === 'GAME_OVER' && sessionId) {
      console.log('[AacPage] GAME_OVER received. Navigating to Victory screen.');

      const colors = Object.fromEntries(
        connectedUsers
          .filter(user => user.color)
          .map(user => [user.userId, user.color])
      );

      navigate(`/victory/${sessionId}`, { state: { scores, colors, sessionId, userId } });
    }
  }, [lastMessage, sessionId, navigate, scores, connectedUsers]);

  /**
   * If sessionId is not present, display an error message.
   */
  if (!sessionId) return <p>Session ID not found</p>;

  /**
   * Render the AAC interface with the provided sessionId.
   */
  return (
    <div id="aac-page">
      <AacInterface sessionId={sessionId} userId={userId} role={role} />
    </div>
  );
};

export default AacPage;