JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.19.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<div id="app">
<div class="event-calendar__grid">
<div class="days-of-week">
<div>Mo</div>
<div>Tu</div>
<div>We</div>
<div>Th</div>
<div>Fr</div>
<div>Sa</div>
<div>Su</div>
</div>
<div class="week" v-for="week in month" :key="week.week">
<div class="day" :class="{ 'is-today': isToday(day) }" v-for="(day, index) in week.days" :key="index">
<div class="day__header">{{ day.format('DD') }}</div>
<div class="day__events">
<div class="event" v-for="event in eventsOf(day)" :key="event.id">{{ event.name }}</div>
</div>
</div>
</div>
</div>
</div>
CSS
.days-of-week {
display: flex;
text-align: center;
}
.days-of-week > div {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
height: 50px;
border-bottom: 1px solid rgba(0,0,0,0.1);
}
.event-calendar__grid {
border: 1px solid rgba(0, 0, 0, 0.1);
}
.week {
display: flex;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.week:last-child {
border-bottom: none;
}
.week > .day {
flex: 1;
height: 130px;
padding: 5px;
box-sizing: border-box;
border-right: 1px solid rgba(0, 0, 0, 0.1);
}
.week > .day:last-child {
border-right: none;
}
.day.is-today {
background-color: #ddd;
}
JavaScript
let events = {
"2017-10-30":[
{"id":26,"name":"Icie Williamson","starts_at":"2017-10-30 15:21:28"}
],
"2017-10-27":[
{"id":1,"name":"Olaf Hintz","starts_at":"2017-10-27 15:21:28"},
{"id":10,"name":"Mr. Sanford Kassulke","starts_at":"2017-10-27 15:21:28"}
],
"2017-10-26":[
{"id":19,"name":"Gretchen Harber","starts_at":"2017-10-26 15:21:28"},
{"id":27,"name":"Layla Gaylord","starts_at":"2017-10-26 15:21:28"}
],
"2017-10-25":[
{"id":18,"name":"Joseph Vandervort III","starts_at":"2017-10-25 15:21:28"}
],
"2017-10-24":[
{"id":4,"name":"Mrs. Tiara Mertz","starts_at":"2017-10-24 15:21:28"},
{"id":8,"name":"Connor Ryan","starts_at":"2017-10-24 15:21:28"}
],
"2017-10-14":[
{"id":2,"name":"Juana Schmitt","starts_at":"2017-10-14 15:21:28"},
{"id":6,"name":"Vito Simonis","starts_at":"2017-10-14 15:21:28"},
{"id":14,"name":"Lisette McLaughlin","starts_at":"2017-10-14 15:21:28"}
]
};
new Vue({
el: '#app',
data() {
return {
events: events,
date: moment()
};
},
computed: {
startWeek() {
return this.date.month() === 0 ? 0 : this.date.clone().startOf('month').week();
},
endWeek() {
return this.date.clone().endOf('month').week();
},
month() {
const month = [];
for (let week = this.startWeek; week <= this.endWeek; week++) {
month.push({
week: week,
days: [,,,,,,,].fill(0).map((n, i) => {
return this.date
.clone()
.week(week)
.startOf('week')
.add(i, 'day');
})
});
}
return month;
}
},
...