React Time Picker Component
Develop a functional and user-friendly time picker component in React using TypeScript. This component will allow users to select a specific time of day (hours and minutes) and will be a common building block for various applications requiring time input, such as appointment scheduling or event planning.
Problem Description
Your task is to create a reusable React component named TimePicker. This component should provide an intuitive interface for users to select hours (1-12, AM/PM) and minutes (0-59).
Key Requirements:
-
Hour Selection:
- Display hours from 1 to 12.
- Provide a mechanism (e.g., buttons, dropdown, or number input) to select the hour.
- Handle wrapping around from 12 to 1.
-
Minute Selection:
- Display minutes from 0 to 59.
- Provide a mechanism to select the minutes.
- Consider how to handle minute increments (e.g., 5-minute intervals or full minute selection). For this challenge, allow selection of every minute.
-
AM/PM Selection:
- Allow users to toggle between AM and PM.
- This selection should be linked to the hour selection (e.g., 12 AM is midnight, 12 PM is noon).
-
State Management:
- The component should manage its internal state for selected hour, minute, and AM/PM.
- It should accept an initial time value as a prop and update its internal state accordingly.
- It should expose the currently selected time to its parent component via a callback prop.
-
User Interface:
- The UI should be clear and easy to navigate.
- Visual feedback should be provided for the currently selected hour, minute, and AM/PM.
Expected Behavior:
- When the component mounts, it should display the initial time provided as a prop. If no initial time is provided, it should default to a sensible value (e.g., current time or 12:00 AM).
- Interacting with the hour, minute, or AM/PM selectors should update the component's internal state.
- When the selected time changes, the
onChangecallback prop should be invoked with the new time value. The format of the time value passed to the callback should be consistent (e.g., an object{ hours: number, minutes: number, period: 'AM' | 'PM' }).
Edge Cases to Consider:
- 12 AM/PM Logic: Correctly handle the transition from 11 AM to 12 PM, 12 PM to 1 PM, 11 PM to 12 AM, and 12 AM to 1 AM.
- Initial State: Ensure correct rendering and state management when an initial time is provided.
- Invalid Input (if applicable): Although not strictly required for this challenge's core UI, consider how invalid initial values might be handled.
Examples
Example 1:
Initial Time Prop: { hours: 3, minutes: 30, period: 'PM' }
Expected UI State:
- Hour display shows "3"
- Minute display shows "30"
- AM/PM selector shows "PM"
On User Interaction:
- User clicks the "increment hour" button.
- New UI State: Hour display shows "4".
onChangeCallback: Called with{ hours: 4, minutes: 30, period: 'PM' }.
Example 2:
Initial Time Prop: { hours: 12, minutes: 0, period: 'AM' }
Expected UI State:
- Hour display shows "12"
- Minute display shows "00"
- AM/PM selector shows "AM"
On User Interaction:
- User clicks the "decrement hour" button.
- New UI State: Hour display shows "11".
onChangeCallback: Called with{ hours: 11, minutes: 0, period: 'AM' }.
Example 3:
Initial Time Prop: { hours: 11, minutes: 59, period: 'PM' }
On User Interaction:
- User clicks the "increment hour" button.
- New UI State: Hour display shows "12", AM/PM selector changes to "AM".
onChangeCallback: Called with{ hours: 12, minutes: 59, period: 'AM' }.
- User clicks the "increment hour" button again.
- New UI State: Hour display shows "1", AM/PM selector remains "AM".
onChangeCallback: Called with{ hours: 1, minutes: 59, period: 'AM' }.
Constraints
- The component must be implemented using React and TypeScript.
- No external UI libraries (like Material UI, Ant Design, etc.) should be used for the core time picker logic and UI. You can use basic CSS for styling.
- The
onChangecallback should be debounced or throttled if performance becomes a significant concern with rapid selections, but for this challenge, a direct callback is sufficient. - The time representation for the
onChangecallback should be consistent and clearly defined.
Notes
- Consider how you will represent the time internally. An object
{ hours: number, minutes: number, period: 'AM' | 'PM' }is recommended. - Think about different UI approaches for selecting hours and minutes (e.g., scrollable lists, number inputs with +/- buttons, dropdowns). Choose one that you find most effective for a time picker.
- The challenge is to implement the core logic and UI. Styling is secondary but should make the component usable.
- For the purpose of this challenge, we will use a 12-hour format (AM/PM).