State Management
Relevant source files
The following files were used as context for generating this wiki page:Introduction
State management in the AI for Thai EMS application is handled at the component level using React's built-in useState hook. The application does not employ a global state management library (like Redux or Zustand), opting instead for a localized approach where each interactive component manages its own state. This includes UI state (e.g., visibility of a widget), data fetched from the Gemini AI service, and the state of user interactions like simulations and chat conversations.
The primary stateful components are AiDemo.tsx and Chatbot.tsx, which manage complex interactions. The root App.tsx component is largely stateless, serving as a structural container that passes static data from constants.ts down to its children via props.
Component-Level State
App.tsx: Root Component Data Flow
The App component acts as the main layout and composition root. It does not manage dynamic state with useState. Instead, it imports static arrays and objects (e.g., projectObjectives, researchTeam) from constants.ts and passes them as props to child components like Card and Timeline. This represents the simplest form of data flow in the application.
Sources: App.tsx:7-10, App.tsx:39-43, constants.ts
AiDemo.tsx: Simulation State
The AiDemo component orchestrates a simulated emergency call to demonstrate the AI's analysis capabilities. Its state is self-contained and crucial for managing the simulation's lifecycle, transcript progression, and the display of AI analysis results.
State Variables
The component uses several useState hooks to manage its internal state.
| State Variable | Type | Description |
|---|---|---|
simulationState | 'idle' | 'running' | 'finished' | Controls the current phase of the simulation. |
transcript | { speaker: string; text: string }[] | An array holding the conversation transcript, which grows as the simulation runs. |
analysis | AiAnalysisResult | Stores the structured data returned from the Gemini AI analysis. Initialized with initialAnalysis. |
isAnalyzing | boolean | A loading flag that is true while waiting for a response from the AI service. |
error | string | null | Holds any error message that occurs during the AI analysis API call. |
Sources: components/AiDemo.tsx:37-42, types.ts:11-19
State Flow and Logic
The simulation's state transitions are managed by user actions and timed events.
- Initialization: The component starts with
simulationStateas'idle'. - Start: The user clicks the "Start Simulation" button, which calls
handleStart. This function resets all state variables to their initial values and setssimulationStateto'running'. - Running: A
useEffecthook triggers whensimulationStateis'running'. It usessetIntervalto add new lines to thetranscriptstate from a predefinedfullTranscript. - Analysis: When a line from the 'Caller' is added to the transcript, the
runAnalysisfunction is called. It setsisAnalyzingtotrue, callsanalyzeEmergencyCallWithGemini, and updates theanalysisstate with the result. - Finish/Error: The simulation moves to the
'finished'state when the transcript is complete or if an error occurs during analysis.
Sources: components/AiDemo.tsx:55-66, components/AiDemo.tsx:70-86, components/AiDemo.tsx:92-98
This diagram illustrates the lifecycle of the simulationState.
Chatbot.tsx: Interactive Chat State
The Chatbot component provides a floating chat interface for users to interact directly with the Gemini AI. It manages the conversation history, user input, API loading states, and configuration toggles for the AI service.
State Variables
| State Variable | Type | Description |
|---|---|---|
isOpen | boolean | Toggles the visibility of the chat widget. |
messages | Message[] | An array of message objects ({id, text, sender, sources?}) representing the chat history. |
input | string | The current value of the user's text input field. |
isLoading | boolean | A flag indicating that a message is being sent or a response is being received. |
error | string | null | Stores error messages related to API calls or audio processing. |
isThinkingMode | boolean | A toggle to select between gemini-2.5-pro (true) and gemini-2.5-flash (false). |
useSearch | boolean | A toggle to enable the Google Search tool for the AI model. |
useMaps | boolean | A toggle to enable the Google Maps tool for the AI model. |
isRecording | boolean | A flag to manage the state of microphone audio recording. |
Sources: components/Chatbot.tsx:24-36
Message Handling and State Updates
The handleSendMessage function is the core of the chat logic. It orchestrates a series of state updates to create an interactive, streaming experience.
The following sequence diagram shows the flow when a user sends a message.
The component optimistically updates the UI by first adding the user's message to the messages array. It then creates a new, empty message object for the model's response. As chunks of data arrive from the streaming API call, it continuously updates this message object, causing the text to appear word-by-word in the UI.
Sources: components/Chatbot.tsx:68-78
Shared Data Structures
The shape of the state is defined by interfaces in types.ts and type aliases within components. These structures ensure type safety and consistency.
AiAnalysisResult
This interface defines the JSON structure expected from the analyzeEmergencyCallWithGemini function. The analysis state in AiDemo.tsx conforms to this type.
// From types.ts
export interface AiAnalysisResult {
incidentType: string | null;
location: string | null;
severity: 'Critical' | 'Urgent' | 'Non-Urgent' | null;
recommendedAction: string | null;
extractedData: {
name: string;
age: string;
condition: string;
}
}
Sources: types.ts:11-19, services/geminiService.ts:8-27
Message
This type, defined in Chatbot.tsx, structures each entry in the chat history. The sender property is aligned with the Gemini API's role names ('user' or 'model') for easier history mapping.
// From components/Chatbot.tsx
type Message = {
id: number;
text: string;
sender: 'user' | 'model';
sources?: any[];
};
Sources: components/Chatbot.tsx:11-16
Summary
The AI for Thai EMS application utilizes a decentralized state management pattern, leveraging React's useState hook within individual components. This approach is well-suited for the application's scope, where complex state logic is encapsulated within the AiDemo and Chatbot components without the need for a global state container. State transitions are driven by user events, timers, and asynchronous API calls, with loading and error states handled explicitly to provide a responsive user experience.