How to create a calendar in Vue
Tags: webdev, javascript, programming, vue
Published: 2023-03-12 09:25:49

## Calendar

In this article we will create a calendar using vue.js.

## Setup

First create a vue project using vite. After creating the project delete all unnecessary code and files created by vite.

```
npm init vite <project-name> // creates vue project using vite 
cd <project-name> // move in to the project created by vite
npm install // installs all necessary dependecies for our project
npm run dev // runs development server at http://localhost:5173/
```

## Creating calendar

Our calendar will be divided into two main components `Header` and `calendarGrid`. `Header` component will contain name of month, year and chevrons/arrows for changing date.`calendarGrid` component will contain days and their corresponding dates. And both of these components will live inside one `calendar` component. So, lets first create `calendar.vue` in `src/components` folder and import `Header` and `calendarGrid` components into it.

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

`calendar.vue`👇🏻
```html
<script setup>
    import Header from './Header.vue'
    import calendarGrid from './calendarGrid.vue'
</script>
<template>
    <main>
        <!-- Using Header and calendarGrid Component -->
        <Header/>
        <calendarGrid/>
    </main>
</template>
<style scoped lang="less">
    main{
        width: 500px;
        padding-bottom: 30px;
        border-radius: 5px;
        background-color: azure;
        box-shadow: 5px 5px 20px 0 rgba(0, 0, 0, 0.5);
        @media(max-width: 500px){
            width: 90vw;
        }
    }
</style>
```

For vue to compile our `calendar.vue` we need to import it into `App.vue` component because vue passes `App.vue` to `createApp` function in `main.js` for compiling. So, lets do that:

`App.vue`👇🏻
```html
<script setup>
    import calendar from './components/calendar.vue'
</script>
<template>
    <main>
        <!-- Using calendar Component -->
        <calendar/>
    </main>
</template>
```

Now, lets create `Header.vue` component in `src/components` folder. In `Header.vue` we will create a `div` with class `header` inside of which we will create further two `div` elements with classes `info` and `wrapper`. `.info` element will contain year and `.wrapper` element will contain chevrons and name of month. And at last we will add some styles to it.

`Header.vue`👇🏻
```html
<script setup>
    import chev from '../assets/chev.svg' // importing chevron image
</script>
<template>
    <div class="header">
        <div class="info">
            <div class="year">
                <p>2023</p>
            </div>
        </div>
        <div class="wrapper">
            <div class="left-chev chev">
            <img :src="chev" alt="left-chevron">
            </div>
            <div class="month">
                <h2>February</h2>
            </div>
            <div class="right-chev chev">
                <img :src="chev" alt="right-chevron">
            </div>
        </div>
    </div>
</template>
<style scoped lang="less">
    .header{
        display: flex;
        flex-direction: column;
        padding: 10px;
        background-color: antiquewhite;
        border-radius: 5px 5px 0 0;
        .wrapper{
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 20px 0;
            .month{
                h2{
                    font-size: 32px;
                    font-weight: bolder;
                    letter-spacing: 5.5px;
                }
            }
            .chev{
                user-select: none;
                width: 40px;
                height: 40px;
                border-radius: 50%;
                display: flex;
                justify-content: center;
                align-items: center;
                cursor: pointer;
                transition: background-color .5s;
                &:hover{
                    background-color: rgb(243, 206, 158);
                }
                img{
                    width: 100%;
                    height: auto;
                    transform: translateX(2px);
                }
            }
            .left-chev{
                transform: rotate(180deg);
            }
        }
    }
</style>
```

With that we have created `Header.vue`. Now, we will create `calendarGrid.vue` component.

In `calendarGrid` component we will create a `div` with `calendar-grid` class which will contains two `div` elements with classes `days-grid` and `date-grid`. `.days-grid` will contain 7 `div` elements with class `day` which will contain days of week sunday to saturday. But instead of creating indivisual `div` elements we will create an array of week days and we will loop over that in our `template` using `v-for` directive. `.date-grid` element will contain 31, 30, 28 or 29(depending on the month) `div` elements with class `date` which will contain dates in `.val` element. But for now we will render 31 days using `range` function and `v-for` directive for the sake of layout. We will change it when we will implement functionality for our calendar.

`calendarGrid.vue`👇🏻
```html
<script setup>
    const DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
</script>
<template>
    <div class="calendar-grid">
        <div class="days-grid">
            <div
                v-for="day, index in DAYS"
                :key="index"
                class="day"
                :title="day"
            >{{ day[0] }}</div>
        </div>
        <div class="date-grid">
            <div class="date"
                v-for="date in range(31)"
            >
                <div 
                    class="val">
                    {{ date }}
                </div>
            </div>
        </div>
    </div>
</template>
<style scoped lang="less">
    .calendar-grid{
        margin-top: 15px;
        display: grid;
        gap: 20px;
        user-select: none;
        .days-grid{
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            justify-content: space-between;
            align-items: center;
            .day{
                text-align: center;
                font-weight: bold;
                &.today{
                    color: blueviolet;
                }
            }
        }
        .date-grid{
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            justify-content: space-between;
            align-items: center;
            row-gap: 20px;
            .date{
                display: flex;
                justify-content: center;
                cursor: pointer;
                .val{
                    width: 20px;
                    height: 20px;
                    text-align: center;
                    border-radius: 50%;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    padding: 15px;
                    position: relative;
                    background-color: antiquewhite;
                }
            }
        }
    }
</style>
```

And with that layout of our calendar is completed.

## Adding Functionality

Basic functionality of our app includes changing dates and to highlight current day and date and also to arrange dates in correct order with respect to their corresponding days. For that we have to create quite a few reactive states and then we have to pass those states from one component to another and evetually we will extend the functionality of our app for adding events for which we have to pass state between sibling components which makes state management bit difficult. So, to manage state easily we will manage states at global level so that any component can access that state. To manage state at global level we can use state managers like `vuex` or `pinia` but this app not that big and complex so we will use vue's built in provide/inject functions.

### **Provide function**

Vue's provide function allows us to share state/data from higher component to the lower components. E.g: If we have five components `A, B C, D and E` where `B and C` are children of `A`, `D` is child of `C` and `E` is child of `D`. Component `A` contains a state `x` which we want to use in component `E` which we can do by passing state `x` from `A` to `C`, `C` to `D`, `D` to `E`. In this example, for using state `x` in component `E` we had to pass it to components `C` and `D` which do not need this state.This process of passing data/state from parent component to child component (where child component can be at any depth in component tree) as props is known prop drilling.

`Component tree with prop drilling`

```
                                      A ----> contains state 'x'
                                      |x <---- passing 'x' from A -> C
                                      |x x x
                                ------------x
                                |          |x
                                |          |x
                                B          C <--- Doest not use 'x'
                                            \x <---- passing 'x' from C -> D
                                             \x
                                              D <--- Doest not use 'x'
                                               \x<---- passing 'x' from D -> E
                                                \x
                                                 E ----> uses state 'x'

```

provide function helps us to avoid prop drilling meaning we can pass state `x` directly from `A` to `E` without prop drilling. Lets see how to do it.

Provide function takes two arguments first is key and second is the state that we want to share. Key is used to access the shared state in child component.

` In component A`
```js
import {ref, provide} from 'vue'
const x = ref(0)
provide('store', x) // sharing state x and setting 'store' as key
```

*Note:* value in provide function can be of any type like string, number, array, object e.t.c

### **Inject Function**

Vue's inject functions allows us to use state shared by parent component in child component. Inject function takes one argument which is the key that we passed to provide function in parent component.

` In component E`
```js
import {inject} from 'vue'
const x = inject('store') // accessing state 'x'
console.log(x.value) // prints 0
```

`Component tree without prop drilling`

```
                                      A ----> contains state 'x' and share it using provide
                                      |
                                      |
                                ------------
                                |          |
                                |          |
                                B          C
                                            \
                                             \
                                              D
                                               \
                                                \
                                                 E ----> uses state 'x' using inject 

```

Lets see how to use provide/inject in our calendar app. Our app have a state called `date` which is used in almost every component so, lets make it a global state or app level state. To create app level state we will use provide function inside `main.js`.

`main.js 👇🏻`
```js
import { createApp, ref } from 'vue'
import './less/global.less'
import App from './App.vue'

const date = ref({date: {
        str: new Date(),
        dateString: new Date().toDateString()
    }})
createApp(App)
    .provide('store', date) // providing date state to every component in our app.
    .mount('#app')

```

`date` is simply an object which contains two properties `str` and `dateString`. `str` store a date object which gives us current date and `dateString` gives us date in more simpler format like this 'Sat Feb 27 2023'. But other than `date` we have more states in our app that we want to make global. For that we will create a single object which will contain all of our global states. And to keep our `main.js` clean and clutter free we will create our global state in different file and then we will import that file into `main.js`.

Create `store.js` in `src/store` folder. `store.js` will contain global state.

`store.js👇🏻`
```js
import { ref } from 'vue'
export const state = ref({
    date: {
        str: new Date(),
        dateString: new Date().toDateString()
    }
})
```

`state` in `store.js` is a single global reactive state that contains all states for our app. Now, lets import `state` in `main.js`.

```js
import { createApp } from 'vue'
import './less/global.less'
import App from './App.vue'
import { state } from './store/store.js'

createApp(App)
    .provide('store', state) // providing single global state object to every component in our app.
    .mount('#app')
```

Now, we can use state object in any component of our app. Lets use `state` in `Header.vue`. In `Header.vue` we need `month` and `year` which we can extract from `dateString` property of `date` object inside `state`. We will also create a component level state `current` which will contain `month` and `year` that we will extract from `dateString`. One thing to note that `dateString` gives only first 3 intials of month name meaning for `January` it will give `Jan` and so on. But we want full month names so, we will create a `MONTHS` object with months first 3 initials as key and months fullname as value that way we can get fullname of months from first 3 initials.

`Header.vue👇🏻`
```html
<script setup>
    import { ref, inject } from 'vue'
    import chev from '../assets/chev.svg'
    
    const MONTHS = {
        Jan: "January",
        Feb: "February",
        Mar: "March",
        Apr: "April",
        May: "May",
        Jun: "June",
        Jul: "July",
        Aug: "August",
        Sep: "September",
        Oct: "October",
        Nov: "November",
        Dec: "December"
    }
    const state = inject('store') // accessing state using inject function
    const [ _, month, __, year ] = state.value.date.dateString.split(' ') // extracting month & year from dateString
    const current = ref({
        month: MONTHS[month], // getting month fullname from MONTHS object using months first 3 initials
        year
    })
</script>

<template>
    <div class="header">
        <div class="info">
            <div class="year">
                <p>{{ current.year }}</p> <!-- Using year from current state above -->
            </div>
        </div>
        <div class="wrapper">
            <div class="left-chev chev">
            <img :src="chev" alt="left-chevron">
            </div>
            <div class="month">
                <h2>{{ current.month }}</h2> <!-- Using month from current state above -->
            </div>
            <div class="right-chev chev">
                <img :src="chev" alt="right-chevron">
            </div>
        </div>
    </div>
</template>
<style scoped lang="less">
    /* styling goes here */
</style>
```

Until now our calendar is only showing current month and year but we want it to change month and year depending on the chevron we click E.g: if we click on right chevron and current month is february calendar should change it to march and if month is december and year is 2023 then calendar should change month to january and year to 2024. And reverse should happen if we click on left chevron. Now all of this to happen we have to update `date` object inside global reactive `state`. We can update `date` in `Header.vue` component but vue documentation recommends not to change global reactive state in child components rather create a function at global level which will be responsible for updaing/changing global state. We will create and export this function from `store.js` file and we will name it `dispatch` and after that we will import it in `main.js` and then instead of passing `state` as value to `provide` function we will pass an object which contains `state` and `dispatch` function as properties to `provide` function because of which we can access `dispatch` in components for updating/changing global state.

`store.js👇🏻`
```js
import { ref } from 'vue'
export const state = ref({
    date: {
        str: new Date(),
        dateString: new Date().toDateString()
    }
})

export const dispatch = () => {} // we will implement it in a bit
```

`main.js👇🏻`
```js
import { createApp } from 'vue'
import './less/global.less'
import App from './App.vue'
import { state, dispatch } from './store/store.js' // importing dispatch

createApp(App)
    .provide('store', { state, dispatch }) // providing an object containing global state and function to update/change global state to every component in our app.
    .mount('#app')
```

Now, lets understand how `dispatch` function will work. In our app we will change date in different ways E.g; clicking on right chevron will change date in inreasing order and clicking on left chevron will change date in decreasing order and we may perform different actions on our app which can change calendar in different ways then how a single function is able to handle every type of change and the answer is that we will create separate functions for each type of action we perform on calendar and `dispatch` function will only decide which function to execute. Lets say we have a function `increase` which increases the date when we click on right chevron but we cannot invoke `increase` function directly because to increase date we have to update date object which is in global `state` object and to update global state we have to use `dispatch` function so, when user clicks on right chevron we will call `dispatch` and then `dispatch` will call `increase` function and same thing will happen when user clicks left chevron but instead of calling `increase` function `dispatch` will call `decrease` function which decreases the date. So, how does `dispatch` knows which function to invoke when user performs any action? When we call `dispatch` function we will pass an argument known as `action` to it. Based on this argument `dispatch` is able to decide which function to call. `action` is simply an object with property `type` whose value is simply a string which describes what the action is. If we want to increase date by clicking on right chevron for that we will first call `dispatch` and pass `action` object as an argument like this `dispatch({type: 'INCREASE'})` and in `dispatch` function we will recieve this action as parameter and inside that function we will check the `type` of `action` object and if it is `INCREASE` it will call `increase` function which increases the date. In addition to `type` we can also add more properties to `action` object if we want to send additional data to `dispatch` function.

Lets add click event listeners on right and left chevrons in `Header.vue` component. When user clicks on any of the chevron it calls a `handleClick` function and we also pass an argument to this function and that argument is 'next-month' or 'previous-month' depending on the chevron user clicked. In `handleClick` function we call `dispatch` and pass an `action` as argument and that argument looks like this

```js
const handleClick = (direction) => dispatch({type: 'updateDate', payload: {direction}})
```

In above code `handleClick` function recieves a parameter `direction` which is either 'next-month' or 'previous-month' depending on the chevron user clicked and inside the function we are calling `dispatch` with an object as argument and this argument is an action which contains two properties `type` and `payload`. The value of `type` specifies what type of action is being performed meaning in this case user has clicked one of the chevrons so we have to update date either in increasing or decreasing order that is why value of `type` is 'updateDate' and `payload` is an object which is used to send additional data to our `dispatch` function.

Now, inside `dispatch` function we have to check the type of the action and based on that we will call an appropriate function for updating date.

`store.js👇🏻`
```js
import { ref } from 'vue'
export const state = ref({
    date: {
        str: new Date(),
        dateString: new Date().toDateString()
    }
})

export const dispatch = (action) => {
    // checking the type of action
    if(action.type === 'updateDate'){
        const newDate = updateDate(state.value.date, action.payload) // calling updateDate function for updating date
        state.value = {...state.value, date: newDate} // updating state
    }
}
```

In above code we are checking if `action.type` is equal to 'updateDate' and if it is we are calling an `updateDate` function which updates date by increasing or decreasing depending on the value of `direction` which we passed in `payload` object of `action`. If value of direction is 'next-month' then `updateDate` function will increase date and if value is 'previous-month' then date will be decreased.

Lets implement `updateDate` function

```js
const updateDate = (date, payload) => {
    const year = date.str.getFullYear()
    const month = date.str.getMonth() + 1
    let newDate = {}
    if(payload.direction === 'next-month') {
        newDate = increase(month, year)
    }
    else newDate = decrease(month, year)
    return newDate
}
```

`updateDate` function takes 2 parameters `date` and `payload`. `date` is current date which we will use to get the next date or previous date and `payload` is the object which we passed with action to `dispatch` and `payload` have a `direction` property which is used to decide whether to increase the date or decrease. First, we will get current year and month using `getFullYear` and `getMonth` methods on `date.str` and note that `getMonth` returns a month number from 0 to 11, 0 -> January & 11 -> December that is why we adding 1 to month. Then we check if `direction` equals to 'next-month' and if yes then we increase the date by calling `increase` funtion with current month and year as arguments else we decrease date by calling `decrease` in same way. And the result object returned by these function is store in newDate variable which is then returned.

As we can see that we are using `increase` and `decrease` functions inside `updateDate` which are responsible for increasing and decreasing date respectively. So, lets implement these functions.

```js
const increase = (month, year) => {
    const obj = {}
    // checking month is not December👇🏻
    if(month !== 11){
        obj.str = new Date(`${year}-${month+1}`)
        obj.dateString = new Date(`${year}-${month+1}`).toDateString()
    }else{
        obj.str = new Date(`${year+1}-01`)
        obj.dateString = new Date(`${year+1}-01`).toDateString()
    }
    return obj
}
const decrease = (month, year) => {
    const obj = {}
    // checking month is not January👇🏻
    if(month !== 0){
        obj.str = new Date(`${year}-${month-1}`)
        obj.dateString = new Date(`${year}-${month-1}`).toDateString()
    }else{
        obj.str = new Date(`${year-1}-12`)
        obj.dateString = new Date(`${year-1}-12`).toDateString()
    }
    return obj
}
```

In `increase` function we are checking if `month` is not December and if it is not then we just have to increase month and year will be same but `month` is December then we have to increase year and change month to '01' and the result is stored in `obj` object which is then returned. And reverse happens in `decrease` function.

Now, when user clicks on any of the chevron it will update date correctly but we will not be able to see those changes on our screen because in `Header.vue` we are storing date in component level state known as `current` and this state do not know that date has updated so, whenever date updates we also have to update `current` for that we have to watch date object in global state so, lets do that using `watch` function.

```html
<script setup>
    import { ref, inject, watch } from 'vue'
    import chev from '../assets/chev.svg'
    
    const MONTHS = {
        Jan: "January",
        Feb: "February",
        Mar: "March",
        Apr: "April",
        May: "May",
        Jun: "June",
        Jul: "July",
        Aug: "August",
        Sep: "September",
        Oct: "October",
        Nov: "November",
        Dec: "December"
    }
    const state = inject('store') // accessing state using inject function
    const [ _, month, __, year ] = state.value.date.dateString.split(' ') // extracting month & year from dateString
    const current = ref({
        month: MONTHS[month], // getting month fullname from MONTHS object using monts first 3 initials
        year
    })

    // watching date so that we can update current 👇🏻
    watch(()=>state.value.date, (updatedDate) => {
        const [ _, month, __, year ] = updatedDate.dateString.split(' ') // extracting updated month and year

        // updating current👇🏻
        current.value = {
            month: MONTHS[month],
            year
        }
    })
</script>

<template>
    <div class="header">
        <div class="info">
            <div class="year">
                <p>{{ current.year }}</p> <!-- Using year from current state above -->
            </div>
        </div>
        <div class="wrapper">
            <div class="left-chev chev">
            <img :src="chev" alt="left-chevron">
            </div>
            <div class="month">
                <h2>{{ current.month }}</h2> <!-- Using month from current state above -->
            </div>
            <div class="right-chev chev">
                <img :src="chev" alt="right-chevron">
            </div>
        </div>
    </div>
</template>
<style scoped lang="less">
    /* styling goes here */
</style>
```

`watch` function takes 2 arguments first argument is dependency state meaning what state we want to watch and second argument is a function which gets executed when dependency state changes this function takes a parameter which is updated version of dependency state.

Now, we can see the changes on screen

![Calendar Gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/co6ts8o5zchb3n3pm6gl.gif)

Now, lets add functionality to `CalenderGrid.vue` component. In this component we first have to render correct number of days for each month and then we have to make sure that each date falls under correct day in every month. E.g; In 01-february-2023 was 'wednesday' so, in calendar '1' should be under day 'wednesday'. If we dont arrange dates in each month in correct order then in every month '1' will fall under day 'sunday'.

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

To get the correct number of dates in each month we will create a state called `dateGrid` with initial value of empty array inside global reactive state in `store.js`. `dateGrid` array will be updated with current number of dates every time date changes by clicking on any chevrons in header. To update `dateGrid` we will create a function `updateDateGrid` which will update `dateGrid` whenever date changes.

`store.js👇🏻`
```js
import { ref } from 'vue'
export const state = ref({
    date: {
        str: new Date(),
        dateString: new Date().toDateString()
    },
    dateGrid: []
})

export const dispatch = (action) => {
    // checking the type of action
    if(action.type === 'updateDate'){
        const newDate = updateDate(state.value.date, action.payload) // calling updateDate function for updating date
        state.value = {...state.value, date: newDate} // updating state
    }
}
```

Now, lets implement `updateDateGrid` function. This function recieves an argument which is current date object then we are extracting month name and year from `dateString` property of date object. After that we need to know number of days in current month for that we are using `getNumberOfDays` function and we are passing month name as an argument to this function. After recieving number of days in `numberOfDays` variable from `getNumberOfDays` function and then we are creating `currentMonthDates` array which will contain dates of current month. Each element in `currentMonthDates` array will be an object with three properties `id`, `dt`, `day`. `dt`is date from 1 to `numberOfDays`, `day` is simply day on particular date `dt`.

```js
const DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
const updateDateGrid = date => {
    const [ _, monthName, __, year ] = date.dateString.split(' ') // extracting month name and year
    const numberOfDays = getNumberOfDays(monthName, year) // recieving number of days
    const currentMonthDates = [] // will contain dates of current month
    const monthNumber = date.str.getMonth() + 1 // current month number 1 - 12
    for(let i = 0; i < numberOfDays; i++){
        const item = {} // creating an object that will contain day & date
        const day = new Date(`${year}-${monthNumber}-${i+1}`).getDay() // getting day number 0 - 6
        item.id = i + 1
        item.dt = i + 1
        item.day = DAYS[day] // getting day from DAYS array
        currentMonthDates.push(item) // adding item object containing day and date to currentMonthDates array
    }
    return currentMonthDates
}
```

In above code you can see that we are using `getNumberOfDays` function which returns number of days in given month lets implement this function.

```js
const getNumberOfDays = (month, year) => {
    const thirtyOneDays = ['Jan', 'Mar', 'May', 'Jul', 'Aug', 'Oct', 'Dec'] // months having 31 days
    if(thirtyOneDays.includes(month)) return 31
    else if(month === 'Feb') return isLeapYear(year) ? 29 : 28 // checking if year is a leap year
    return 30
}
```

First we are creating an array of months `thirtyOneDays` that have 31 days then we are checking that if the given month is in this array and if it is then we are returning `31` but if it is not in this array then we are checking that if month is February and if it is then we have to check that if the year is leap year or not if it is leap year then we are returning `29` else we are returning `28` but if month is not February then we return `30`.

In above code we have used `isLeapYear` function which returns `true` if the year is a leap year else it returns `false`. Now, lets implement it.

```js
const isLeapYear = year => {
    const firstCondition = year % 4 === 0 && year % 100 !== 0 // If a year is divisible by 4 and is not divisible by 100
    const secondCondition = year % 4 === 0 && year % 100 === 0 && year % 400 === 0 // If a year is divisible by 4 and 100 and 400
    if(firstCondition || secondCondition) return true
    return false
}
```

A year is leap if it specifies two condition:
- If a year is divisible by 4 and is not divisible by 100.
- If a year is divisible by 4 and 100 and 400.

Now, our calendar renders correct number of days for each month but there is still a problem which is that these days are not in correct order meaning the first date of every month comes under sunday as shown in picture above.

Now, lets arrange these dates in correct order and for that we will create a function which takes `currentMonthDates` as a parameter then it first checks the day on first date which it gets from first element of array. Then we will get index of that day from `DAYS` array which will let us know at which position we have to render the first date in our calendar. E.g: day on first date of February is `Wednesday` so the date `1` should be under `W` in calendar for that we will first get the index of `Wed` from `DAYS` array and the index is `3`. So, we will prepend 3 empty objects in `currentMonthDates` array so that when we loop over `currentMonthDates` array it will render 3 empty objects which will leave first 3 blocks in calendar empty and the date `1` will be rendered on 4th block which is under `W` and all other dates automatically falls under correct day. And same process will be repeated for each month.

Lets implement this function

```js
const DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
const arrangeGridAccordingToDays = currentMonthDates => {
    let newDateGrid = []
    const firstDay = DAYS.indexOf(currentMonthDates[0].day) // getting index of first day
    for(let i = 0; i <= firstDay; i++){
        if(i < firstDay){
            newDateGrid = [...newDateGrid, {
                id: Math.random(),
                dt: '', //  adding empty date value
                day: DAYS[i]
            }]
        }else{
            newDateGrid = [...newDateGrid, ...currentMonthDates]
        }
    }
    return newDateGrid
}
```

Now, use above function in `updateDateGrid` function.

```js
const DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
const updateDateGrid = date => {
    const [ _, monthName, __, year ] = date.dateString.split(' ') // extracting month name and year
    const numberOfDays = getNumberOfDays(monthName, year) // recieving number of days
    const currentMonthDates = [] // will contain dates of current month
    const monthNumber = date.str.getMonth() + 1 // current month number 1 - 12
    for(let i = 0; i < numberOfDays; i++){
        const item = {} // creating an object that will contain day & date
        const day = new Date(`${year}-${monthNumber}-${i+1}`).getDay() // getting day number 0 - 6
        item.id = i + 1
        item.dt = i + 1
        item.day = DAYS[day] // getting day from DAYS array
        currentMonthDates.push(item) // adding item object containing day and date to currentMonthDates array
    }
    return arrangeGridAccordingToDays(currentMonthDates) // arranging dates in correct order
}
```

`CalenderGrid.vue 👇🏻`

```html
<script setup>
    import { ref, computed, inject } from 'vue'
    
    const DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
    const {state, dispatch} = inject('store')
    const current = ref({
        currentDay: DAYS[new Date().getDay()],
        currentDate: new Date().getDate(),
        currentMonth: new Date().getMonth(),
        currentYear: new Date().getFullYear()
    })

    // Checking current month and year 👇🏻
    const isCurrentMonthAndYear = computed(() => (
        state.value.date.str.getMonth() === current.value.currentMonth && 
        state.value.date.str.getFullYear() === current.value.currentYear
    ))
</script>

<template>
    <div class="calender-grid">
        <div class="days-grid">
            <div
                v-for="day, index in DAYS"
                :key="index"
                :class="['day', {today: day === current.currentDay && isCurrentMonthAndYear}]"
                :title="day"
            >{{ day[0] }}</div>
        </div>
        <div class="date-grid">
            <div class="date"
                v-for="date in state.dateGrid" // Looping over dateGrid
                :key="date.id"
            >
                <div 
                    :class="['val', {today: date.dt === current.currentDate && isCurrentMonthAndYea}]" 
                    v-if="date.dt">
                    {{ date.dt }}
                </div>
                <div v-else>&#10060;</div>
            </div>
        </div>
    </div>
</template>

<style scoped lang="less">
    .calender-grid{
        margin-top: 15px;
        display: grid;
        gap: 20px;
        user-select: none;
        .days-grid{
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            justify-content: space-between;
            align-items: center;
            .day{
                text-align: center;
                font-weight: bold;
                &.today{
                    color: blueviolet;
                }
            }
        }
        .date-grid{
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            justify-content: space-between;
            align-items: center;
            row-gap: 20px;
            .date{
                display: flex;
                justify-content: center;
                cursor: pointer;
                .val{
                    width: 20px;
                    height: 20px;
                    text-align: center;
                    border-radius: 50%;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    padding: 15px;
                    position: relative;
                    background-color: antiquewhite;
                    &.today{
                        color: blueviolet;
                        font-weight: bold;
                    }
                    &.event{
                        // border: 1px solid salmon;
                        background-color: antiquewhite;
                        font-weight: bold;
                        &::before{
                            content: '';
                            width: 5px;
                            height: 5px;
                            border-radius: 50%;
                            background-color: salmon;
                            position: absolute;
                            top: 2px;
                            right: 2px;
                        }
                    }
                }
            }
        }
    }
</style>
```

And with that our basic calendar is ready.

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