Hone logo
Hone
Problems

React Calendar Component with Day Selection

This challenge requires you to build a functional calendar component in React using TypeScript. This component will allow users to view a calendar month and select specific days, which is a fundamental building block for many date-picking functionalities.

Problem Description

Your task is to create a reusable React component, CalendarComponent, that displays a calendar for a given month and year. The component should allow users to navigate between months and select individual days.

Key Requirements:

  • Display Month and Year: The component should clearly display the current month and year being viewed.
  • Navigation: Implement "Previous" and "Next" buttons to allow users to move to the preceding and succeeding months, respectively.
  • Day Grid: Render a grid of days for the current month. Each day should be displayed in its appropriate cell.
  • Day Selection: Users should be able to click on a day to select it. The selected day should be visually highlighted.
  • State Management: The component should manage its internal state for the currently displayed month and year, as well as the selected day.
  • Props: The component should accept an optional initialDate prop (a Date object) to set the initial month and year to display. It should also accept an onDaySelect prop (a callback function) that is called with the selected Date object whenever a day is clicked.

Expected Behavior:

  1. When the component mounts, it should display the current month and year by default, or use the initialDate if provided.
  2. Clicking the "Previous" button should decrement the displayed month by one.
  3. Clicking the "Next" button should increment the displayed month by one.
  4. Clicking on a specific day within the calendar grid should mark that day as selected. Only one day can be selected at a time.
  5. The onDaySelect callback should be invoked with the Date object of the selected day.
  6. The previously selected day should be de-selected when a new day is chosen.

Edge Cases:

  • Month Boundaries: Ensure correct navigation across year boundaries (e.g., going from December to January and vice-versa).
  • Days in Month: Accurately display the correct number of days for each month, considering leap years for February.
  • Initial Date: Handle the initialDate prop correctly, ensuring the calendar displays the correct month and year upon initial render.
  • No Selection: The component should gracefully handle scenarios where no day is initially selected.

Examples

Example 1: Initial Render (Current Month)

Input: No initialDate prop provided.
Output:
(Component displays the current month and year, e.g., "October 2023". Days of the month are rendered in a grid. No day is initially selected.)

Explanation: When no initial date is provided, the calendar defaults to the current month and year.

Example 2: Navigating to Previous Month

Input: User clicks the "Previous" button while viewing "October 2023".
Output:
(Component now displays "September 2023". Days of September are rendered. No day is selected unless it was already selected in the previous month's view and the selection logic persists.)

Explanation: Clicking "Previous" moves the calendar back one month.

Example 3: Selecting a Day

Input: User clicks on the 15th day of the month.
Output:
(The cell for the 15th day is visually highlighted. The `onDaySelect` callback is called with a `Date` object representing October 15th of the current year.)

Explanation: Clicking a day triggers selection and calls the provided callback function.

Example 4: Selecting a Different Day

Input: User had previously selected October 15th, and now clicks on October 22nd.
Output:
(The highlight is removed from the 15th day's cell. The cell for the 22nd day is now visually highlighted. The `onDaySelect` callback is called with a `Date` object representing October 22nd of the current year.)

Explanation: Selecting a new day deselects the previously selected one and updates the callback.

Example 5: Initial Date Prop

Input: initialDate prop is set to `new Date(2024, 0, 1)` (January 1st, 2024).
Output:
(Component displays "January 2024". Days of January are rendered. No day is initially selected.)

Explanation: The `initialDate` prop dictates the starting month and year for the calendar.

Constraints

  • Date Handling: Use standard JavaScript Date objects for all date manipulations.
  • React Version: Assume a modern version of React (e.g., React 18+).
  • TypeScript: All code must be written in TypeScript.
  • Styling: While specific styling is not the primary focus, the selected day should be visually distinct. You can use inline styles or CSS classes.
  • No External Libraries: Avoid using external date utility libraries like Moment.js or date-fns for core logic. Native JavaScript Date methods should suffice.

Notes

  • Consider how you will determine the starting day of the week for a given month (e.g., Sunday or Monday). For simplicity, you might assume Sunday is the first day of the week for layout purposes.
  • Think about how to represent days that fall outside the current month but are needed to complete the grid. These days can be visually distinct (e.g., grayed out) and not selectable.
  • The onDaySelect callback is crucial for making the component useful in a larger application, as it allows the parent component to be aware of the user's selection.
  • You will need to implement logic to calculate the number of days in a month and the day of the week for the first day of the month.
Loading editor...
typescript