Building a Custom Calendar with React and Day.js: A Step-by-Step Guide.
Tags: webdev, javascript, beginners, programming
Published: 2024-06-20 16:08:01

Welcome! 

This is the first of a **three-part** series on building a custom calendar with React and Day.js. We are going to start with a simple calendar in this first part and go all the way up to a date range picker in the third part. 

When you are done with this, you can check the second part here:

{% embed https://dev.to/oluwadahunsia/building-a-simple-date-picker-with-react-and-dayjs-4oop %}

And the third part here:

{% embed https://dev.to/oluwadahunsia/building-a-date-range-picker-with-react-and-dayjs-2b5a %}


Here, we will create a simple, yet functional calendar using React and Day.js, then we will add more features and functionalites in the subsequent parts. 

By the end of this part, you will have a basic calendar that looks like this:

![A simple Calendar](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y1sythz4q6c3lxlnoa4o.gif)

By the end of the third part, we will have a Date Range Picker created from this calendar. Here is a sneak peak:

![Custom Date Range Picker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rzhnws6beajdhmp25o9q.gif)


Try to follow along as much as you can. I have also provided the final version for this part at the end of this article. So, let us dive into creating a dynamic calendar application!


## Setting up our React project with Vite. 

To kickstart our React project using Vite, let's begin by opening our terminal and running the following command:

```
npm create vite@latest
```

If you prefer, you can name the project **“Calendar”**. Otherwise, you are free to choose a name that suits you. Also, make sure to select **Typescript** while setting up vite for your application.

```
Project name: Use any name you prefer.

Framework: React.

Language: TypeScript.

```

Once you are all set, create a `Calendar` folder within your `src` directory. Inside the `Calendar` folder, create two files: `Calendar.tsx` for building our Calendar component and `style.css` for our styling needs. Your folder structure should resemble the following:

```
src/
└── Calendar/
    ├── Calendar.tsx
    └── style.css

```

## Installing Day.js

As you already know, we will be using `Day.js` library for date manipulation, I recommend visiting their website to familiarize yourself with its capabilities. To install `Day.js` for our project, open your terminal and execute the following command:

```
npm install dayjs
```

Before proceeding, you might be wondering why we are choosing Day.js for date formatting instead of relying on the built-in Date object. The rationale behind using a third-party library like Day.js includes several advantages, one of which is the fact that Day.js gives simple APIs for date manipulation. I will show this with an example. 

Imagine you have to get a date in this format `DD.MM.YYYY HH:mm:sss`. Can you try to achieve this on your own using the built-in Date object?

One possible solution is to write a function that accepts a date and returns it in the format we desire. Let’s do that below. 

```typescript

const formatGivenDate = (date) => {

  const day = date.getDate(); 
  
  const month = date.getMonth() + 1; // Add 1 to month because it is zero based
  
  const year = date.getFullYear();
  
  const hours = date.getHours(); 
  
  const minutes = date.getMinutes();
  
  const seconds = date.getSeconds();
   
 // join with template literal and return formatted date
 
 return `${day < 10 ? "0" + day : day}.${month < 10 ? '0' + month : month}.${year} ${hours}:${minutes}:${seconds}`
 
}

const date = new Date();

console.log(formatGivenDate(date)) // 15.06.2024 21:48:13

```

That looks quite straightforward, right? But what if we can achieve the same thing with a lot less than that?

Let us see what it looks like with Day.js. 

```typescript
const date = dayjs();

const formattedDate = date.format('DD.MM.YYYY HH:mm:ss')

```

Yay, we got the same result in 2 lines of code.

Another reason why we are using Day.js is because it is a really lightweight library compared to a lot of the other available options — it is just 2kb in size. 

Okay, back to building our calendar.


## Starter files

To save time, I will provide you with the initial content of `Calendar.tsx` and the `style.css` files. 


```css

.calendar__container {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 25px;
  width: max-content;
  background: #ffffff;
  box-shadow: 5px 10px 10px #dedfe2;
}

.month-year__layout {
  display: flex;
  margin: 0 auto;
  width: 100%;
  flex-direction: row;
  align-items: center;
  justify-content: space-around;
}

.year__layout,
.month__layout {
  width: 150px;
  display: flex;
  padding: 10px;
  font-weight: 600;
  align-items: center;
  text-transform: capitalize;
  justify-content: space-between;
}

.back__arrow,
.forward__arrow {
  cursor: pointer;
  background: transparent;
  border: none;
}

.back__arrow:hover,
.forward__arrow:hover {
  scale: 1.1;
  transition: scale 0.3s;
}

.days {
  display: grid;
  grid-gap: 0;
  width: 100%;
  grid-template-columns: repeat(7, 1fr);
}

.day {
  flex: 1;
  font-size: 16px;
  padding: 5px 7px;
  text-align: center;
}

.calendar__content {
  position: relative;
  background-color: transparent;
}

.calendar__items-list {
  text-align: center;
  width: 100%;
  height: max-content;
  overflow: hidden;
  display: grid;
  grid-gap: 0;
  list-style-type: none;
  grid-template-columns: repeat(7, 1fr);
}

.calendar__items-list:focus {
  outline: none;
}

.calendar__day {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
}

.calendar__item {
  position: relative;
  width: 50px;
  height: 50px;
  cursor: pointer;
  background: transparent;
  border-collapse: collapse;
  background-color: white;

  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  border: 1px solid transparent;
  z-index: 200;
}

button {
  margin: 0;
  display: inline;
  box-sizing: border-box;
}

.calendar__item:focus {
  outline: none;
}

.calendar__item.selected {
  font-weight: 700;
  border-radius: 50%;
  background: #1a73e8;
  color: white;
  outline: none;
  border: none;
}

.calendar__item.selectDay {
  position: relative;
  background: #1a73e8;
  color: white;
  border-radius: 50%;
  border: none;
  z-index: 200;
}

.calendar__item.gray,
.calendar__item.gray:hover {
  color: #c4cee5;
  display: flex;
  justify-content: center;
  align-items: center;
}

.input__container {
  display: flex;
  justify-content: space-around;
}

.input {
  height: 30px;
  border-radius: 8px;
  text-align: center;
  align-self: center;
  border: 1px solid #1a73e8;
}

.shadow {
  position: absolute;
  display: inline-block;
  z-index: 10;
  top: 0;
  background-color: #f4f6fa;
  height: 50px;
  width: 50px;
}

.shadow.right {
  left: 50%;
}

.shadow.left {
  right: 50%;
}

```

```typescript
//Calendar.tsx

import backArrow from '../assets/images/back.svg';
import forwardArrow from '../assets/images/forward.svg';
import './style.css';

const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];

const daysListGenerator = {
  day: 15,
  prevMonthDays: [26, 27, 28, 29, 30],
  days: [
    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,
  ],
  remainingDays: [1, 2, 3, 4, 5],
};

export const Calendar = () => {
  return (
    <div className='calendar__container'>
      <div className='control__layer'>
        <div className='month-year__layout'>
          <div className='year__layout'>
            <button className='back__arrow'>
              <img src={backArrow} alt='back arrow' />
            </button>
            <div className='title'>2024</div>
            <button className='forward__arrow'>
              <img src={forwardArrow} alt='forward arrow' />
            </button>
          </div>
          <div className='month__layout'>
            <button className='back__arrow'>
              <img src={backArrow} alt='back arrow' />
            </button>
            <div className='new-title'>June</div>
            <button className='forward__arrow'>
              <img src={forwardArrow} alt='forward arrow' />
            </button>
          </div>
        </div>
        <div className='days'>
          {weekDays.map((el, index) => (
            <div key={`${el}-${index}`} className='day'>
              {el}
            </div>
          ))}
        </div>
        <div className='calendar__content'>
          <div className={'calendar__items-list'}>
            {daysListGenerator.prevMonthDays.map((el, index) => {
              return (
              <div key={`${el}/${index}`} className='calendar__day'>
                <button className='calendar__item gray'>
                  {el}
                </button>
              </div>
              );
            })}
            {daysListGenerator.days.map((el, index) => {
              return (
                <div key={`${index}-/-${el}`} className='calendar__day'>
                  <button
                    className={`calendar__item 
                      ${+el === +daysListGenerator.day ? 'selected' : ''}`}
                  >
                    <div className='day__layout'>
                      <div className='text'>{el.toString()}</div>
                    </div>
                  </button>
                </div>
              );
            })}

            {daysListGenerator.remainingDays.map((el, idx) => {
              return (
              <div key={`${idx}----${el}`} className='calendar__day'>
                <button className='calendar__item gray' >
                  {el}
                </button>
              </div>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
};

```

```typescript
// src/App.tsx

import { Calendar } from './Calendar/Calendar';

function App() {
  return (
    <>
      <Calendar />
    </>
  );
}

export default App;

```

You probably have noticed that I imported some svg files in the Calendar component, right? 

I got them from svg repo but don’t worry I won’t leave you to source for them yourself. Here you have it.

```typescript
//back.svg
<?xml version="1.0" encoding="utf-8"?>
<svg width="20px" height="20px" viewBox="0 0 1000 1000" class="icon"  version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M768 903.232l-50.432 56.768L256 512l461.568-448 50.432 56.768L364.928 512z" fill="#000000" /></svg>
```

```typescript
//forward.svg
<?xml version="1.0" encoding="utf-8"?>
<svg width="20px" height="20px" viewBox="0 0 1000 1000" class="icon"  version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M256 120.768L306.432 64 768 512l-461.568 448L256 903.232 659.072 512z" fill="#000000" /></svg>
```

For no particular reason — other than just following along — create an image folder inside your assets directory and put the two svg files in this folder. 

At this point, your file structure should look like this.

```
src/
└── assets/
     └──images/
         ├── back.svg
         └── forward.svg
    
└── Calendar/
    ├── Calendar.tsx
    └── style.css
```


The `daysListGenerator` object in the `Calendar.tsx` file holds the values needed to populate our calendar. Let us look at what each of the property in the object means:

 `day` is the current day or today. In the picture below, we can see it is `15`.

`prevMonthDays` array contains the days in the previous month that will show in the current month. These days are so important as they will also help to offset the days in the current month and ensure that the first day of the current month matches with the corresponding day of the week. In the picture below these days are: `[26, 27, 28, 29, 30]`

`days` array contains the days in the current month, the length of this array will range from 28 to 31. 

`remainingDays` array contains the days in the next month that will show in the current month. Since we have prevMonthDays, we can as well just have the remaining days as well. In the picture below, the remaining days are: `[1, 2, 3, 4, 5, 6, 7]`


Provided you have followed everything up to this point, if you start your application, you should have a calendar that looks like this:


![Initial Calendar](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dspfryxwtymztm8qk8e9.png)


The content of our calendar is currently hardcoded,so we need to fix this and make it as dynamic as we can.


## Adding functionalities to the calendar.


So far, we have successfully initialized our project, installed DayJs, and hardcoded a basic calendar. Now, the next step is to ensure everything functions correctly. Our calendar should be able to display different months and years, as well as the corresponding days. Let’s focus on implementing these features to ensure our calendar is fully operational and not perpetually stuck in the past.

You would agree with me that in order to achieve our aim, all we need to do is ensure that the `daysListGenerator` object is dynamic and each of the properties change with respect to today’s date.

```typescript
//

const daysListGenerator = {
  day: 15,
  prevMonthDays: [26, 27, 28, 29, 30],
  days: [
    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,
  ],
  remainingDays: [1, 2, 3, 4, 5],
};

//
```

So, instead of hardcoding the properties in this object, we will try to generate them based on our current date (or today’s date).

To do that, let us create a helper function. This function will be responsible for generating all the currently hardcoded values in our calendar, such as `day`, `prevMonthDays`, `days`, and `remainingDays`.

In your src directory, create a folder called **`helper`** , inside this folder, create a **`calendarObjectGenerator.ts`** file. Your file structure should now look similar to this:


```
src/
└── assets/
     └──images/
         ├── back.svg
         └── forward.svg
    
└── Calendar/
    ├── Calendar.tsx
    └── style.css
 
└── helper   
     └── calendarObjectGenerator.ts
```

Inside the `calendarObjectGenerator.ts` file, we will create a function called `calendarObjectGenerator` . This function will accept the currentDate or (today’s date), and will return an object containing calculated values, based on the current date, for all the properties we previously hardcoded. 

This function is provided below:

```typescript
//calendarObjectGenerator.ts

import dayjs, { Dayjs } from 'dayjs';
import isLeapYear from 'dayjs/plugin/isLeapYear';
import LocaleData from 'dayjs/plugin/localeData';
import customParseFormat from 'dayjs/plugin/customParseFormat';

dayjs.extend(customParseFormat);
dayjs.extend(LocaleData);

type GeneratedObjectType =  {
  days: number[];
  day: number;
  prevMonthDays: number[];
  remainingDays: number[];
  months: string[];
};


export const calendarObjectGenerator = (currentDate: Dayjs): GeneratedObjectType => {

  const numOfDaysInPrevMonth =  currentDate.subtract(1, 'month').daysInMonth();
  const firstDayOfCurrentMonth = currentDate.startOf('month').day()
  
  return {
  days: Array.from({ length: currentDate.daysInMonth() }, (_, index) => index + 1),
  day: Number(currentDate.format('DD')),
  months: currentDate.localeData().months(),
  
  //read explanation
  prevMonthDays: Array.from({length:firstDayOfCurrentMonth}, (_,index) => numOfDaysInPrevMonth - index).reverse(),
  
  remainingDays:  Array.from(
      { length: 6 - currentDate.endOf('month').day() },
      (_, index) => index + 1
    ),
}
```

Let me explain how the values for each of the property in the object is calculated. 

`days: Array.from({length: currentDate.daysInMonth()}, (_,index) => index + 1)` 

To get the number of days in a month, we can use the `daysInMonth()` method from the DayJs object. This method returns the number of days as a numerical value (e.g 30). We can then create an array of integers from 1 to the number of days in `currentDate.daysInMonth()`.

`day: Number(currentDate.format('DD'))` 

We can extract the day of the month from our Day.js object by calling format method on the object and specifying what we want to extract.

`months: currentDate.localeData().months()`

This returns an array of all the months of the year. 

`prevMonthDays: Array.from({length:firstDayOfCurrentMonth}, (_,index) => numOfDaysInPrevMonth - index).reverse()`

Now, let's consider the days from the previous month that we want to display. It's important to include these days as they will serve as an offset for the beginning of our current month, ensuring that the first day of the current month falls on the correct day of the week. Although getting the previous and remaining days can be a bit tricky, we can figure it out with some logic.

Let's break it down:

- The method **`dayjs().startOf('month').day()`** gives us the first day of the current month, where 0 = Sunday and 6 = Saturday.

- Using this value, we can create an array representing the number of days before the first day of the current month: **`Array.from({ length: dayjs().startOf('month').day() })`**.

- DayJs makes it easy to find the last day of the previous month. Simply subtract one month from the current month and get the number of days: **`dayjs().subtract(1, 'month').daysInMonth()`**.

- Putting it all together, we can generate the last few days of the previous month: **`Array.from({ length: dayjs().startOf('month').day() }, (_, index) => numOfDaysInPrevMonth - index)`**.

- Finally, reverse the array to sort the days in increasing order.



`remainingDays:  Array.from( { length: 6 - currentDate.endOf('month').day() }, (_, index) => index + 1 )`

To fill in the remaining days of our calendar, we can use one of two approaches:

- **Subtract from the Last Day of the Month:**

    - Subtract the value of the last day of the month (0 = Sunday to 6 = Saturday) from 6.

    - Using this result, create an array of numbers in increasing order.

- **Total Days in the Calendar:** 
    
     **`remainingDays: 42 - (firstDayOfCurrentMonth + currentDate.daysInMonth())`**
    
    - Determine the total number of days you want to display in the calendar, for example, 42.

    - Calculate the remaining days by subtracting the sum of the total offset and the total number of days in the current month from 42.
    - If you're unsure why 42 is used, count the number of days in the hardcoded calendar above. You can choose the total number of days you want to display on your calendar.


## Updating the days of the month.


Now that we have completed the `calendarObjectGenerator` function, let's put it to use to make our calendar dynamic.

Create a state to hold the current date:

`const [currentDate, setCurrentDate] = useState<Dayjs>(dayjs(Date.now()));`

Import `calendarObjectGenerator` into the `Calendar.tsx` file and replace the hardcoded object  assinged to the `daysListGenerator` variable with `calendarObjectGenerator(currentDate)`.


```typescript
import dayjs, { Dayjs } from 'dayjs';
import backArrow from '../assets/images/back.svg';
import forwardArrow from '../assets/images/forward.svg';
import dayjs, { Dayjs } from 'dayjs';
import { calendarObjectGenerator } from '../helper/calendarObjectGenerator'; // add this line
import './style.css';

const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];
 
 export const Calendar = () => {

 const [currentDate, setCurrentDate] = useState<Dayjs>(dayjs(Date.now())); // add line
 
 const daysListGenerator = calendarObjectGenerator(currentDate); //add this line
 



 ... // other lines are the same as the content of Calendar.tsx above
 }
```


Now your calendar should be updated and match the current month. 


## Enable click on month and year control arrows.


Even though, we have partly ensured that the calendar is not hardcoded anymore, and we will not get stuck in the past, there is still no way to peep into the future or travel back in time. 

So our next challenge is to ensure we can go into the previous and future months and years. 

That means we have to  activate our arrows to respond to clicks. 

Let’s create a function that will handle clicks on our arrows. We will call it **dateArrowHandler**. We will then use this function to control our months and years.


```typescript
import dayjs, { Dayjs } from 'dayjs';
import backArrow from '../assets/images/back.svg';
import forwardArrow from '../assets/images/forward.svg';
import dayjs, { Dayjs } from 'dayjs';
import { calendarObjectGenerator } from '../helper/calendarObjectGenerator'; 
import './style.css';

const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];
 
 export const Calendar = () => {

 const [currentDate, setCurrentDate] = useState<Dayjs>(dayjs(Date.now()));
 
 const daysListGenerator = calendarObjectGenerator(currentDate);
 
 //add this function
 
  const dateArrowHandler = (date:Dayjs) => {
    setCurrentDate(date);
  };
  
  return ( 
  <div className='calendar__container'>
      <div className='control__layer'>
        <div className='month-year__layout'>
          <div className='year__layout'>
            <button
              className='back__arrow'
 //add line   onClick={() => dateArrowHandler(currentDate.subtract(1, 'year'))} 
            >
              <img src={backArrow} alt='back arrow' />
            </button>
 //add line <div className='title'>{currentDate.year()}</div>
            <button
              className='forward__arrow'
 //add line   onClick={() => dateArrowHandler(currentDate.add(1, 'year'))}
            >
              <img src={forwardArrow} alt='forward arrow' />
            </button>
           </div>
 
 ... // other lines are the same as the content of Calendar.tsx above
 }
```

If you have been following, try making the months dynamic on your own before proceeding to the solution.  


```typescript
import dayjs, { Dayjs } from 'dayjs';
import backArrow from '../assets/images/back.svg';
import forwardArrow from '../assets/images/forward.svg';
import dayjs, { Dayjs } from 'dayjs';
import { calendarObjectGenerator } from '../helper/calendarObjectGenerator'; 
import './style.css';

const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];
 
 export const Calendar = () => {

 const [currentDate, setCurrentDate] = useState<Dayjs>(dayjs(Date.now()));
 
 const daysListGenerator = calendarObjectGenerator(currentDate);
 
 //add this function
 
  const dateArrowHandler = (date:Dayjs) => {
    setCurrentDate(date);
  };
  
  return ( 
  <div className='calendar__container'>
      <div className='control__layer'>
        <div className='month-year__layout'>
          <div className='year__layout'>
            <button
              className='back__arrow'
 //add line   onClick={() => dateArrowHandler(currentDate.subtract(1, 'year'))} 
            >
              <img src={backArrow} alt='back arrow' />
            </button>
 //add line <div className='title'>{currentDate.year()}</div>
            <button
              className='forward__arrow'
 //add line   onClick={() => dateArrowHandler(currentDate.add(1, 'year'))}
            >
              <img src={forwardArrow} alt='forward arrow' />
            </button>
          </div>
           <div className='month__layout'>
            <button
              className='back__arrow'
 //add line   onClick={() => dateArrowHandler(currentDate.subtract(1, 'month'))}
            >
              <img src={backArrow} alt='back arrow' />
            </button>
            <div className='new-title'>
 //add line  {daysListGenerator.months[currentDate.month()]}
            </div>
            <button
              className='forward__arrow'
 //add line   onClick={() => dateArrowHandler(currentDate.add(1, 'month'))}
            >
              <img src={forwardArrow} alt='forward arrow' />
            </button>
          </div>
 
 ... // other lines are the same as the content of Calendar.tsx above
 }
```




## Enable click on days.

Finally we want to allow the user to click on the days (numbers) on our calendar. We will be adding three main functions for this purspose. One for handling clicks on the `prevMonthDays`, the second for handling clicks on the `days` of the current month and the last one for handling clicks on the `remainingDays`.


```typescript
...

 const handlePreviousMonthClick = (day: number) => {
    const dayInPreviousMonth = currentDate.subtract(1, 'month').date(day);
    setCurrentDate(dayInPreviousMonth);
  };

  const handleCurrentMonthClick = (day: number) => {
    const dayInCurrentMonth = currentDate.date(day);
    setCurrentDate(dayInCurrentMonth);
 
  };

  const handleNextMonthClick = (day: number) => {
    const dayInNextMonth = currentDate.add(1, 'month').date(day);
    setCurrentDate(dayInNextMonth);

  };
  
  
 ...
```

As a little task for you, can you figure out where to put these functions in your code to enable clicks on the various days? Try to do that on your own.  And once you are done, ensure your calendar looks somewhat like this:


![The first calendar](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ojo2r8abfwpl42m426b7.gif)


That's all we need to do for this first part. I have provided the files containing everything we have written so far.

We will build upon this calendar in the subsequent parts. See you in the next one.


## Summary.

Below is the whole code for what we have so far:

The complete css file is at the beginning.


```typescript

// src/Calendar/Calendar.tsx

import dayjs, { Dayjs } from 'dayjs';
import backArrow from '../assets/images/back.svg';
import forwardArrow from '../assets/images/forward.svg';
import './style.css';
import { useState } from 'react';
import { calendarObjectGenerator } from '../helper/calendarObjectGenerator';

const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'];

export const Calendar = () => {
  const [currentDate, setCurrentDate] = useState<Dayjs>(dayjs(Date.now()));

  const daysListGenerator = calendarObjectGenerator(currentDate);

  const dateArrowHandler = (date: Dayjs) => {
    setCurrentDate(date);
  };

  const handlePreviousMonthClick = (day: number) => {
    const dayInPreviousMonth = currentDate.subtract(1, 'month').date(day);
    setCurrentDate(dayInPreviousMonth);
  };

  const handleCurrentMonthClick = (day: number) => {
    const dayInCurrentMonth = currentDate.date(day);
    setCurrentDate(dayInCurrentMonth);
  };

  const handleNextMonthClick = (day: number) => {
    const dayInNextMonth = currentDate.add(1, 'month').date(day);
    setCurrentDate(dayInNextMonth);
  };

  return (
    <div className='calendar__container'>
      <div className='control__layer'>
        <div className='month-year__layout'>
          <div className='year__layout'>
            <button
              className='back__arrow'
              onClick={() => dateArrowHandler(currentDate.subtract(1, 'year'))}
            >
              <img src={backArrow} alt='back arrow' />
            </button>
            <div className='title'>{currentDate.year()}</div>
            <button
              className='forward__arrow'
              onClick={() => dateArrowHandler(currentDate.add(1, 'year'))}
            >
              <img src={forwardArrow} alt='forward arrow' />
            </button>
          </div>
          <div className='month__layout'>
            <button
              className='back__arrow'
              onClick={() => dateArrowHandler(currentDate.subtract(1, 'month'))}
            >
              <img src={backArrow} alt='back arrow' />
            </button>
            <div className='new-title'>
              {daysListGenerator.months[currentDate.month()]}
            </div>
            <button
              className='forward__arrow'
              onClick={() => dateArrowHandler(currentDate.add(1, 'month'))}
            >
              <img src={forwardArrow} alt='forward arrow' />
            </button>
          </div>
        </div>
        <div className='days'>
          {weekDays.map((el, index) => (
            <div key={`${el}-${index}`} className='day'>
              {el}
            </div>
          ))}
        </div>
        <div className='calendar__content'>
          <div className={'calendar__items-list'}>
            {daysListGenerator.prevMonthDays.map((el, index) => {
              return (
                <button
                  key={`${el}/${index}`}
                  className='calendar__item gray'
                  onClick={() => handlePreviousMonthClick(el)}
                >
                  {el}
                </button>
              );
            })}
            {daysListGenerator.days.map((el, index) => {
              return (
                <div
                  key={`${index}-/-${el}`}
                  className='calendar__day'
                  onClick={() => handleCurrentMonthClick(el)}
                >
                  <button
                    className={`calendar__item 
                      ${+el === +daysListGenerator.day ? 'selected' : ''}`}
                  >
                    <div className='day__layout'>
                      <div className='text'>{el.toString()}</div>
                    </div>
                  </button>
                </div>
              );
            })}

            {daysListGenerator.remainingDays.map((el, idx) => {
              return (
                <button
                  className='calendar__item gray'
                  key={`${idx}----${el}`}
                  onClick={() => handleNextMonthClick(el)}
                >
                  {el}
                </button>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
};


```


```typescript
// src/helper/calendarObjectGenerator.ts

import dayjs, { Dayjs } from 'dayjs';

import LocaleData from 'dayjs/plugin/localeData';

dayjs.extend(LocaleData);

type GeneratedObjectType = {
  prevMonthDays: number[];
  days: number[];
  remainingDays: number[];
  day: number;
  months: string[];
};

export const calendarObjectGenerator = (
  currentDate: Dayjs
): GeneratedObjectType => {
  const numOfDaysInPrevMonth = currentDate.subtract(1, 'month').daysInMonth();
  const firstDayOfCurrentMonth = currentDate.startOf('month').day();
  return {
    days: Array.from(
      { length: currentDate.daysInMonth() },
      (_, index) => index + 1
    ),
    day: Number(currentDate.format('DD')),
    months: currentDate.localeData().months(),

    prevMonthDays: Array.from(
      { length: firstDayOfCurrentMonth },
      (_, index) => numOfDaysInPrevMonth - index
    ).reverse(),

    remainingDays: Array.from(
      { length: 6 - currentDate.endOf('month').day() },
      (_, index) => index + 1
    ),
  };
};

```