Skip to content

Instantly share code, notes, and snippets.

@djave-co
Last active March 8, 2018 15:41
Show Gist options
  • Save djave-co/05808c8d8151fa0f22e289ed9cdef3d9 to your computer and use it in GitHub Desktop.
Save djave-co/05808c8d8151fa0f22e289ed9cdef3d9 to your computer and use it in GitHub Desktop.
Vue calendar component
<template>
<div class="calendar">
<nav class="calendar__nav">
<a @click="decMonth" class="calendar__chevron btn btn-primary">
&larr;
</a>
<b>{{ monthName }}</b>
<b>{{ year }}</b>
<a @click="incMonth" class="calendar__chevron btn btn-primary">
&rarr;
</a>
</nav>
<div class="calendar__labels">
<span class="calendar__label" v-for="label in dayLabels">{{ label }} </span>
</div>
<div class="calendar__month">
<div v-for="week in weeks" class="calendar__week">
<span class="calendar__day" v-for="day in week" v-bind:class="[selectedClass(day), dayClass(day), betweenClass(day)]" @click="select(day)">
<span v-if="day.date">
{{ day.date }}
</span>
</span>
</div>
</div>
<input required="required" name="start_date" type="text" :value="startDate ? dateFormat(startDate) : ''">
<input required="required" name="end_date" type="text" :value="endDate ? dateFormat(endDate) : ''">
</div>
</template>
<script>
import moment from 'moment';
export default {
data(){
return {
dayLabels: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
month : moment().month(),
year : moment().year(),
startDate : false,
endDate : false,
}
},
computed : {
firstDate() {
return new Date(this.year, this.month, 1);
},
monthName(){
return moment().month(this.month).format('MMMM');
},
daysInMonth() {
return moment().month(this.month).year(this.year).daysInMonth();
},
firstDayIndex() {
return this.firstDate.getDay(); // 5
},
lastDate() {
return this.firstDayIndex + this.daysInMonth;
},
weeks() {
var squareIndex = 0;
var dateOfMonth = 1;
var weeks = [];
while (squareIndex < (this.lastDate)) {
var week = [];
for (var d = 0; d < 7; d++) {
if (squareIndex < this.firstDayIndex || squareIndex >= (this.lastDate)) {
week.push({ date : false }); //4
} else {
week.push({
date : dateOfMonth,
data : {
day : dateOfMonth,
month : this.month,
year : this.year
}
});
dateOfMonth++;
}
squareIndex++;
}
weeks.push(week);
}
return weeks;
}
},
methods: {
incMonth: function() {
if (this.month == 11) { //
this.year++;
this.month = 0;
return true;
}
this.month++;
},
decMonth: function() {
if (this.month == 0) {
this.year--;
this.month = 11;
return true;
}
this.month--;
},
select : function(day){
if( ! this.isDay(day) ) return false;
if(this.startDate && this.endDate){
this.setStartDate(day.data);
this.endDate = false;
return;
}
if(this.startDate){
if(this.isBefore(day.data, this.startDate)){
this.setEndDate(this.startDate);
this.setStartDate(day.data);
return;
}
this.setEndDate(day.data);
return;
}
return this.setStartDate(day.data);
},
setStartDate(day){
this.startDate = JSON.parse(JSON.stringify(day));
},
setEndDate(day){
this.endDate = JSON.parse(JSON.stringify(day));
},
isSelected : function(calendarDate){
if( ! this.startDate && ! this.endDate){
return false;
}
if(calendarDate.date === false){
return false;
}
// Is it the first date?
if( moment( this.dateFormat(calendarDate.data) ).isSame(this.dateFormat(this.startDate), 'day')){
return true;
}
if( moment( this.dateFormat(calendarDate.data) ).isSame(this.dateFormat(this.endDate), 'day')){
return true;
}
if( this.isBetweenSelectedDates(calendarDate.data)){
return true;
}
return false;
},
selectedClass : function(day){
if(this.isSelected(day)){
return 'selected';
}
return '';
},
dayClass : function(day){
if(this.isDay(day)){
return 'day';
}
return '';
},
betweenClass(calendarDate){
if(this.isDay(calendarDate) && this.isBetweenSelectedDates(calendarDate.data)){
return 'between';
}
},
isBetweenSelectedDates(day){
if( ! this.startDate || ! this.endDate) return false;
var date = moment(this.dateFormat(day), "YYYY-MM-DD");
var start = moment(this.dateFormat(this.startDate), "YYYY-MM-DD");
var end = moment(this.dateFormat(this.endDate), "YYYY-MM-DD");
var between = date.isBetween( start, end );
return between;
},
isBefore(thisDate, isBeforeThis){
return moment(this.dateFormat(thisDate), 'YYYY-MM-DD').isBefore( moment(this.dateFormat(isBeforeThis), 'YYYY-MM-DD') );
},
isDay : function(day){
return day.date !== false;
},
dateFormat(day){
return day.year + '-' + (day.month + 1) + '-' + day.day;
}
}
}
</script>
<style lang="scss">
.calendar__week, .calendar__labels{
display:flex;
}
.calendar__day, .calendar__label{
flex:1;
box-sizing:border-box;
text-align:center;
padding:10px;
&:hover{
background:#eaeaea;
}
&.selected{
background:#33fa33;
}
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment