Last active
May 26, 2021 13:03
-
-
Save buroz/e6ec239762e316f53f4c57432148b25b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Document</title> | |
<style> | |
.startDate { | |
border-left: 3px solid #d1d5db; | |
} | |
.endDate { | |
border-right: 3px solid #d1d5db; | |
} | |
.day.is-valid:hover { | |
color: white !important; | |
} | |
</style> | |
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet" /> | |
</head> | |
<body> | |
<div id="app" class="container mx-auto"> | |
<div class="flex w-full flex-col justify-center items-center"> | |
<button | |
class="bg-blue-500 hover:bg-blue-700 text-white p-2 rounded shadow" | |
@click="toggleUniversal" | |
> | |
{{ universal ? "Universal" : "Local" }} | |
</button> | |
<p> | |
{{ selected.startDate && selected.startDate.format('DD/MM/YYYY') || "-" }} to {{ | |
selected.endDate && selected.endDate.format('DD/MM/YYYY') || "-" }} | |
</p> | |
</div> | |
<section class="w-full flex justify-between justify-items-center content-center items-center"> | |
<button | |
class="bg-blue-500 hover:bg-blue-700 text-white p-2 rounded shadow text-xs" | |
@click="handlePrevious" | |
:disabled="isSameOrBefore(start)" | |
> | |
Previous | |
</button> | |
<button | |
class="bg-blue-500 hover:bg-blue-700 text-white p-2 rounded shadow text-xs" | |
@click="handleNext" | |
> | |
Next | |
</button> | |
</section> | |
<div | |
class="p-12 w-full flex-col flex md:flex-row justify-between justify-items-center content-center items-start" | |
> | |
<section class="w-full md:w-1/2 md:mr-4"> | |
<h4 class="font-bold text-xl text-gray-400"> | |
{{ start.format('MMM') }} {{ start.format('YYYY') }} | |
</h4> | |
<table class="w-full"> | |
<thead> | |
<tr> | |
<th | |
class="font-light text-sm p-2 text-center text-gray-300" | |
scope="col" | |
class="font-light text-sm" | |
v-for="(dayStr, i) in days" | |
v-bind:key="i" | |
> | |
{{dayStr}} | |
</th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr v-for="(week, i) in range" v-bind:key="i"> | |
<td | |
class="day" | |
:class="[ | |
isBefore(day) ? 'text-gray-300' : 'is-valid cursor-pointer hover:bg-blue-700', | |
day && isSelectedDate(day) && 'bg-blue-700 text-white', | |
day && inRange(day) && 'bg-blue-200', | |
day && isStartOrEnd(day), | |
'p-2 text-center' | |
]" | |
v-for="(day, j) in week" | |
v-bind:key="j" | |
@click="!isBefore(day) && selectDate(day)" | |
@mouseover="!isBefore(day) && paintOnHover(day)" | |
@mouseleave="!isBefore(day) && paintOnHover(day)" | |
> | |
{{ day ? day.format("DD") : "" }} | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
</section> | |
<section class="w-full md:w-1/2 md:mt-0 mt-8 md:ml-4"> | |
<h4 class="font-bold text-xl text-gray-400"> | |
{{ next.format('MMM') }} {{ next.format('YYYY') }} | |
</h4> | |
<table class="w-full"> | |
<thead> | |
<tr> | |
<th | |
class="font-light text-sm p-2 text-center text-gray-300" | |
scope="col" | |
v-for="(dayStr, i) in days" | |
v-bind:key="i" | |
> | |
{{dayStr}} | |
</th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr v-for="(week, i) in nextRange" v-bind:key="i"> | |
<td | |
class="day" | |
:class="[ | |
isBefore(day) ? 'text-gray-300' : 'is-valid cursor-pointer hover:bg-blue-700', | |
day && isSelectedDate(day) && 'bg-blue-700 text-white', | |
day && inRange(day) && 'bg-blue-200', | |
day && isStartOrEnd(day), | |
'p-2 text-center' | |
]" | |
v-for="(day, j) in week" | |
v-bind:key="j" | |
@click="!isBefore(day) && selectDate(day)" | |
@mouseover="day && !isBefore(day) && paintOnHover(day)" | |
@mouseleave="day && !isBefore(day) && paintOnHover(day)" | |
> | |
{{ day ? day.format("DD") : "" }} | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
</section> | |
</div> | |
</div> | |
<script src="https://momentjs.com/downloads/moment.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-range/4.0.2/moment-range.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script> | |
<script> | |
window['moment-range'].extendMoment(moment); | |
</script> | |
<script> | |
const today = moment().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }); | |
const app = new Vue({ | |
el: '#app', | |
data: { | |
start: today, | |
next: moment(today).add(1, 'month'), | |
range: [], | |
nextRange: [], | |
universal: false, | |
selected: { | |
startDate: null, | |
endDate: null, | |
}, | |
}, | |
watch: { | |
universal() { | |
this.calculateRanges(); | |
}, | |
}, | |
computed: { | |
days() { | |
let days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; | |
if (!this.universal) { | |
return days; | |
} | |
const lastDay = days[days.length - 1]; | |
days.pop(); | |
days.unshift(lastDay); | |
return days; | |
}, | |
}, | |
methods: { | |
sliceIntoDays(days) { | |
const daysOfWeek = 7; | |
return [].concat.apply( | |
[], | |
days.map((elem, i) => (i % daysOfWeek ? [] : [days.slice(i, i + daysOfWeek)])), | |
); | |
}, | |
getToday() { | |
const date = moment(); | |
date.set({ hour: 0, minute: 0, second: 0, millisecond: 0 }); | |
return date; | |
}, | |
isBefore(day) { | |
if (day) { | |
return day.isBefore(this.getToday()); | |
} | |
return false; | |
}, | |
isSameOrBefore(day) { | |
return day.isSameOrBefore(this.getToday()); | |
}, | |
isSelectedDate(day) { | |
return day.isSame(this.selected.startDate) || day.isSame(this.selected.endDate); | |
}, | |
isStartOrEnd(day) { | |
if (day.isSame(this.selected.startDate)) { | |
return 'startDate'; | |
} else if (day.isSame(this.selected.endDate)) { | |
return 'endDate'; | |
} | |
}, | |
inRange(day) { | |
return day.isAfter(this.selected.startDate) && day.isBefore(this.selected.endDate); | |
}, | |
paintOnHover(day) { | |
/* | |
if (this.selected.startDate && day.isAfter(this.selected.startDate)) { | |
day.painted = true; | |
} | |
*/ | |
// console.log(day); | |
}, | |
handleNext() { | |
this.start.add(2, 'month'); | |
this.next.add(2, 'month'); | |
this.calculateRanges(); | |
}, | |
handlePrevious() { | |
this.start.subtract(2, 'month'); | |
this.next.subtract(2, 'month'); | |
this.calculateRanges(); | |
}, | |
checkIfThisMoth(month) { | |
const thisYear = this.getToday().year(); | |
const thisMonth = this.getToday().month(); | |
return month.year() === thisYear && month.month() === thisMonth; | |
}, | |
calculateRanges() { | |
this.range = this.calculateTable(this.start); | |
this.nextRange = this.calculateTable(this.next); | |
}, | |
calculateTable(month) { | |
let range = this.getToday().range( | |
moment(month).startOf('month'), | |
moment(month).endOf('month'), | |
); | |
range = [...range.by('days')]; | |
const firstDay = range[0].startOf('month').day(); | |
const nthDay = this.universal ? firstDay + 1 : firstDay; | |
const emptyDays = nthDay >= 1 ? nthDay - 1 : 6; | |
range.unshift(...Array(emptyDays)); | |
return this.sliceIntoDays(range); | |
}, | |
toggleUniversal() { | |
this.universal = !this.universal; | |
}, | |
selectDate(day) { | |
const startDate = this.selected.startDate; | |
const endDate = this.selected.endDate; | |
if (!startDate && !endDate) { | |
this.selected.startDate = day; | |
return; | |
} | |
if (startDate && !endDate) { | |
if (day.isBefore(startDate)) { | |
this.selected.startDate = day; | |
return; | |
} | |
this.selected.endDate = day; | |
return; | |
} | |
if (!startDate && endDate) { | |
if (day.isBefore(endDate)) { | |
this.selected.startDate = day; | |
return; | |
} | |
if (day.isAfter(endDate)) { | |
this.selected.startDate = day; | |
this.selected.endDate = null; | |
return; | |
} | |
this.selected.startDate = day; | |
this.selected.endDate = null; | |
return; | |
} | |
if (startDate && endDate) { | |
if (day.isBefore(startDate)) { | |
this.selected.startDate = day; | |
this.selected.endDate = null; | |
return; | |
} | |
if (day.isSame(startDate)) { | |
this.selected.startDate = null; | |
return; | |
} | |
if (!(day.isAfter(this.selected.startDate) && day.isBefore(this.selected.endDate))) { | |
this.selected.startDate = day; | |
this.selected.endDate = null; | |
return; | |
} | |
this.selected.endDate = day; | |
return; | |
} | |
}, | |
}, | |
mounted() { | |
this.calculateRanges(); | |
}, | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment