React Hydration Tracker
This challenge focuses on building a simple hydration tracker using React and TypeScript. Maintaining adequate hydration is crucial for health, and this application will allow users to log their water intake throughout the day and visualize their progress towards a daily goal. This exercise will test your understanding of React state management, event handling, and basic UI component creation.
Problem Description
You are tasked with creating a React component that allows a user to track their daily water intake. The component should:
- Display a Daily Goal: Show a configurable daily hydration goal (in ounces). This goal should be stored in the component's state.
- Allow Water Logging: Provide a button or input field that allows the user to log water intake in ounce increments (e.g., 8oz, 16oz, or a custom amount).
- Track Progress: Maintain a state variable representing the current water intake. Update this variable each time the user logs water.
- Visualize Progress: Display a visual representation of the user's progress towards their daily goal. This could be a simple progress bar, a percentage, or any other clear visual indicator.
- Handle Goal Completion: When the user reaches or exceeds their daily goal, display a congratulatory message.
- Reset Functionality: Provide a button to reset the current intake to zero, allowing the user to start tracking again.
Key Requirements:
- The solution must be written in TypeScript.
- The component should be functional (using React Hooks).
- The UI should be reasonably clean and user-friendly.
- The code should be well-structured and easy to understand.
Expected Behavior:
- The component should render correctly on initial load, displaying the daily goal and an initial progress indicator (likely 0%).
- Clicking the "Log Water" button (or entering a value and submitting) should increment the current intake by the specified amount.
- The progress indicator should update dynamically to reflect the current intake.
- A congratulatory message should appear when the intake reaches or exceeds the goal.
- The "Reset" button should set the intake back to zero and clear the congratulatory message.
Edge Cases to Consider:
- Invalid Input: If the user enters a non-numeric value for the water intake, handle it gracefully (e.g., display an error message or ignore the input).
- Negative Intake: Prevent the user from logging negative water intake.
- Goal Value: Consider what happens if the goal is set to zero or a negative value. Handle this gracefully (e.g., display a message or default to a reasonable goal).
Examples
Example 1:
Input: Daily Goal = 64oz, User logs 16oz, then 8oz.
Output: Current Intake = 24oz, Progress Bar = 37.5% (24/64 * 100), No congratulatory message.
Explanation: The intake is updated incrementally, and the progress bar reflects the percentage of the goal achieved.
Example 2:
Input: Daily Goal = 128oz, User logs 128oz.
Output: Current Intake = 128oz, Progress Bar = 100%, Congratulatory message: "Congratulations! You've reached your daily hydration goal!"
Explanation: The intake reaches the goal, the progress bar is at 100%, and the congratulatory message is displayed.
Example 3: (Edge Case)
Input: Daily Goal = 0oz, User logs 32oz.
Output: Current Intake = 0oz, Progress Bar = 0%, No congratulatory message.
Explanation: The goal is zero, so the progress remains at 0% regardless of intake.
Constraints
- Goal Value: The daily goal should be a number between 0 and 500 ounces (inclusive).
- Intake Increment: The water intake increment should be a positive number.
- UI Responsiveness: The UI should update within a reasonable timeframe (e.g., less than 200ms) after each interaction.
- Component Size: The component should be relatively small and focused, avoiding unnecessary complexity.
Notes
- Consider using a progress bar library or creating a simple one yourself for the visual representation.
- Think about how to handle user input for the water intake amount. A simple button with predefined amounts (8oz, 16oz) or a text input field are both viable options.
- Focus on clear state management and updating the UI efficiently.
- Error handling for invalid input is important for a robust application.
- You can use any styling approach you prefer (CSS, styled-components, etc.).