Windows 10 calendar (Vue)

Here i created a windows 10 calendar using vue

by maxell4o

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/locale/bg.js"></script>
<link rel="stylesheet" href="//use.fontawesome.com/releases/v5.6.1/css/all.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.47/vue.cjs.js"></script>
<div id="app">
    <div class="calendar">
        <!-- Current time section -->
        <div class="time">
            <div class="clock">
                {{getClock}}
            </div>
            <div class="date">
                {{getTimeDate}}
            </div>
        </div>
        <!-- Calendar actions /current-month, prev-month, next-month/ -->
        <div class="controls">
            <div class="date">
                {{getSelectorDate}}
            </div>
            <div class="selector">
                <!-- Reset calendar view to current month -->
                <i class="fas fa-calendar-day" @click="goToToday" :disabled="isResetDisabled" title="Reset to current month"></i>
				<!-- Move to previous month -->
                <i class="fas fa-chevron-up" @click="goToPrevMonth" title="Previous month"></i>
				<!-- Move to next month -->
                <i class="fas fa-chevron-down" @click="goToNextMonth" title="Next month"></i>
            </div>
        </div>
		<!-- Calendar grid table -->
        <div class="table-container" ref="tableContainer">
            <table>
                <tr>
                    <th v-for="head in heads">{{head}}</th>
                </tr>
                <tr v-for="(week, wIndex) in grid">
                    <td v-for="(day, dIndex) in week" :class="dayClasses(day)" @click="selectDay(day)">
                        {{day.date.getDate()}}
                    </td>
                </tr>
            </table>
			<!-- Hover light effect -->
            <div class="light-mask" ref="light"></div>
        </div>
    </div>
</div>

SCSS

@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400');

body {
    background: #505050;
    padding: 20px;
    font-family: Helvetica;
    color: #fff;
	font-family: 'Open Sans', sans-serif;
}

.calendar{
	background: #222;
	width: 350px;
	margin: auto;
	user-select: none;
	padding-bottom: 10px;
	.time{
		padding: 10px 20px;
		border-bottom: 1px #555 solid;;
		.clock{
			font-size: 40px;
			font-weight: 300;
			color: #eee;
		}
		.date{
			font-size: 14px;
			color: #2795ee;
		}
	}
	.controls{
		padding: 10px 20px 3px;
		display: flex;
		justify-content: space-between;
		.date{
			font-size: 14px;
			color: #eee;
		}
		.selector{
			i{
				width: 30px;
				height: 30px;
				text-align: center;
				cursor: pointer;
				&.fa-calendar-day{
					color: #2795ee;
					&[disabled]{
						color: #777;
					}
				}
			}
		}
	}
	.table-container{
		position: relative;
		overflow: hidden;
		margin: 0 10px;
		table{
			width: 100%; 
			font-size: 14px;
			border-spacing: 2px;
			border-collapse: separate;
			background: #222;
			td{
				position: relative;
				z-index: 2;
				height: 40px;
				border: 2px transparent solid;
				transition: background .05s linear;
				background: #222;
				background-clip: padding-box;
				outline: 2px #222 solid;
				&.today {
					border-color: #186bd6;
					box-shadow: inset 0 0 0 2px #222;
					background: #186bd6;
				}
				&.selected {
					border-color: #186bd6;
				}
				&.prev-month,
				&.next-month{
					color: #777;
				}
				&:hover{
					&:not(.current-month){
						border-color: #666;
					}
					&.current-month:not(.today){
						border-color: #777;
						background: #333;
					}
					&.today{
						border-color: #2795ee;
					}
				}
			}
			th{
				font-size: 11px;
				text-align: center;
				padding: 3px 0;
				text-transform: lowercase;
				color: #ccc;
				background: #222;
				z-index: 2;
				position: relative;
				outline: 2px #222 solid;
			}
			td{
				font-size: 14px;
				text-align:...

Vue

new Vue({
  el: "#app", 
  data: {
  	heads: ["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Нд"],
	calendar: [],
  	date: new Date(),
	time: new Date()
  },
  computed: {
  	grid() {
		let grid = [];
		let _calendar = this.calendar.slice(0);
		while(_calendar.length){
			grid.push(_calendar.splice(0, 7));
		}
		return grid;
	},
	getClock() {
		let t = this.time;
		return moment(t).format('HH:mm:ss');
	},
	getTimeDate() {
		let t = this.time;
		return `${t.getDate()} ${moment(t).format('MMMM')} ${moment(t).format('YYYY')} г.`;
	},
	getSelectorDate() {
		let d = this.date;
		return `${moment(d).format('MMMM')} ${moment(d).format('YYYY')} г.`;
	},
	isResetDisabled() {
		if(this.time.getFullYear() == this.date.getFullYear() &&
			this.time.getMonth() == this.date.getMonth()){
			return true;
		}
		return false;
	}
  },
  methods: {
  	draw() {
		let currentMonth = new Date(this.date.getFullYear(), this.date.getMonth() + 1, 0);
		let prevMonth = new Date(this.date.getFullYear(), this.date.getMonth(), 0);
		let prevMonthCounter = prevMonth.getDay();
		let nextMonthCounter = 1;
		let calendar = [];
		
		// Add days from previous month
		while(prevMonthCounter){
			calendar.push(
				this.dayFormatter(
					new Date(
						this.date.getFullYear(),
						this.date.getMonth()-1, 
						prevMonth.getDate() - prevMonthCounter + 1
					),
					{
						prevMonth: true
					}
				)
			);
			--prevMonthCounter;
		}
		
		// Add days from current month
		calendar.push(...Array(currentMonth.getDate()).fill().map((v, index) => {
			return this.dayFormatter(
				new Date(
					this.date.getFullYear(),
					this.date.getMonth(), 
					index + 1
				),
				{
					currentMonth: true
				}
			);
		}));
		
		// Add days from next month
		while(this.isFloat(calendar.length / 7)){
			calendar.push(this.dayFormatter(
				new Date(
					this.date.getFullYear(),
					this.date.getMonth()+1, 
					nextMonthCounter++
				),
				{
					nextMonth: true
				}
			));
		}
		this.calendar =...