Created
June 29, 2020 16:26
-
-
Save codenamezjames/fea38f8b6bf68d69a7d2484a88e8c086 to your computer and use it in GitHub Desktop.
Revisions
-
codenamezjames created this gist
Jun 29, 2020 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,486 @@ <template> <div> <div class="row q-col-gutter-sm q-mb-md q-px-md q-pt-md"> <div class="col flex items-center q-gutter-sm"> <q-input v-model="zFromUs" label="From" outlined dense mask="##-##-####" style="width: 140px;" > <template #prepend> <q-icon :name="mdiCalendar" color="primary" /> </template> </q-input> <q-btn outline color="transition-2" :label="zStart" > <q-popup-proxy transition-show="scale" transition-hide="scale" @before-show="zStartPicker = zStart" > <q-time v-model="zStartPicker" mask="hh:mm A" > <div class="row items-center justify-end q-gutter-sm"> <div class="col"> <q-btn :icon="mdiClockTimeTwelveOutline" flat round @click="zStartPicker = '12:00 AM'" > <q-tooltip>Set time to start of day</q-tooltip> </q-btn> </div> <q-btn v-close-popup label="Cancel" color="primary" flat /> <q-btn v-close-popup label="OK" color="primary" flat @click="saveTime('zStart')" /> </div> </q-time> </q-popup-proxy> </q-btn> <div><hr style="width: 10px"></div> <!-- TODO: from and to should only be from past to future --> <q-input v-model="zToUs" label="To" outlined dense mask="##-##-####" style="width: 140px;" > <template #prepend> <q-icon :name="mdiCalendar" color="primary" /> </template> </q-input> <q-btn outline color="transition-2" :label="zEnd" > <q-popup-proxy transition-show="scale" transition-hide="scale" @before-show="zEndPicker = zEnd" > <q-time v-model="zEndPicker" mask="hh:mm A" > <div class="row items-center justify-end q-gutter-sm"> <div class="col"> <q-btn :icon="mdiClockTimeElevenOutline" flat round @click="zEndPicker = '11:59 PM'" > <q-tooltip>Set time to end of day</q-tooltip> </q-btn> </div> <q-btn v-close-popup label="Cancel" color="primary" flat /> <q-btn v-close-popup label="OK" color="primary" flat @click="saveTime('zEnd')" /> </div> </q-time> </q-popup-proxy> </q-btn> </div> </div> <q-separator /> <div class="row q-col-gutter-lg q-px-md"> <div class="col-auto"> <q-list dense class="q-my-md" > <q-item clickable :active="activeItemSelection === 'today'" @click="setRange('today')" > <q-item-section>Today</q-item-section> </q-item> <q-item clickable :active="activeItemSelection === 'yesterday'" @click="setRange('yesterday')" > <q-item-section>Yesterday</q-item-section> </q-item> <q-item clickable :active="activeItemSelection === 'thisWeek'" @click="setRange('thisWeek')" > <q-item-section>This Week</q-item-section> </q-item> <q-item clickable :active="activeItemSelection === 'lastWeek'" @click="setRange('lastWeek')" > <q-item-section>Last Week</q-item-section> </q-item> <q-item clickable :active="activeItemSelection === 'thisMonth'" @click="setRange('thisMonth')" > <q-item-section>This Month</q-item-section> </q-item> <q-item clickable :active="activeItemSelection === 'lastMonth'" @click="setRange('lastMonth')" > <q-item-section>Last Month</q-item-section> </q-item> <q-item clickable :active="activeItemSelection === 'thisYear'" @click="setRange('thisYear')" > <q-item-section>This Year</q-item-section> </q-item> <q-item clickable :active="activeItemSelection === 'lastYear'" @click="setRange('lastYear')" > <q-item-section>Last Year</q-item-section> </q-item> </q-list> </div> <div class="col-auto"> <q-separator vertical style="height: 100%" /> </div> <div class="col column"> <div class="row q-col-gutter-md col q-pt-md q-mb-md"> <div class="col"> <month-year-chooser :year.sync="cal1Year" :month.sync="cal1Month" class="q-mb-sm" /> <q-calendar v-model="cal1" view="month" locale="en-us" mini-mode no-active-date short-weekday-label animated :selected-start-end-dates="startEndDates" :day-class="classDay" @click:date="onClickDay" /> </div> <div class="col-auto"> <q-separator vertical style="height: 100%" /> </div> <div class="col"> <month-year-chooser :year.sync="cal2Year" :month.sync="cal2Month" class="q-mb-sm" /> <q-calendar v-model="cal2" view="month" locale="en-us" mini-mode no-active-date short-weekday-label animated :selected-start-end-dates="startEndDates" :day-class="classDay" @click:date="onClickDay" /> </div> </div> <q-separator class="q-mb-md" style="margin-left: -24px; margin-right: -24px; width: calc(100% + 40px);" /> <div class="row items-center q-mb-md q-col-gutter-md"> <div class="col-auto"> Range: {{ range }} </div> <div class="col"> <slot /> </div> </div> </div> </div> </div> </template> <script> import { mdiClose, mdiCalendar, mdiClockTimeTwelveOutline, mdiClockTimeElevenOutline } from '@quasar/extras/mdi-v5' import dayjs from 'dayjs' import { autoPluralize } from 'src/tools' import isEqual from 'lodash/isEqual' // import QCalendar from '@quasar/quasar-ui-qcalendar' const todayFrom = dayjs() const todayTo = dayjs() export default { components: { monthYearChooser: () => import('src/modules/month-year-chooser/index.vue') }, constants: { mdiClose, mdiCalendar, mdiClockTimeTwelveOutline, mdiClockTimeElevenOutline }, props: { value: { default: () => [ dayjs().toISOString(), dayjs().toISOString() ], validator (input) { if (input) return Array.isArray(input) && input.length === 2 return true } } }, data () { return { zStartPicker: '00:00', zEndPicker: '00:00', zFrom: dayjs(this.value[0]).format('YYYY-MM-DD'), zTo: dayjs(this.value[1]).format('YYYY-MM-DD'), zStart: dayjs(this.value[0]).format('hh:mm A'), zEnd: dayjs(this.value[1]).format('hh:mm A'), clicked: false, cal1: dayjs().subtract(1, 'month').format('YYYY-MM-DD'), cal2: dayjs().format('YYYY-MM-DD'), timeFrames: { today: { from: todayFrom, to: todayTo }, yesterday: { from: todayFrom.add(-1, 'day'), to: todayTo.add(-1, 'day') }, thisWeek: { from: todayFrom.startOf('w'), to: todayTo }, lastWeek: { from: todayFrom.add(-1, 'w').startOf('w'), to: todayTo.add(-1, 'w').endOf('w') }, thisMonth: { from: todayFrom.startOf('M'), to: todayTo }, lastMonth: { from: todayFrom.add(-1, 'M').startOf('M'), to: todayTo.add(-1, 'M').endOf('M') }, thisYear: { from: todayFrom.startOf('y'), to: todayTo }, lastYear: { from: todayFrom.add(-1, 'y').startOf('y'), to: todayTo.add(-1, 'y').endOf('y') } } } }, computed: { activeItemSelection () { const from = dayjs(this.zFrom, 'YYYY-MM-DD') const to = dayjs(this.zTo, 'YYYY-MM-DD') let active = '' ;['lastYear', 'thisYear', 'lastMonth', 'thisMonth', 'lastWeek', 'thisWeek', 'yesterday', 'today'].forEach((name) => { if (to.isSame(this.timeFrames[name].to, 'date') && from.isSame(this.timeFrames[name].from, 'date')) active = name }) return active }, range () { const days = Math.abs(dayjs(this.zFrom, 'YYYY-MM-DD').diff(this.zTo, 'day')) + 1 return days + autoPluralize(days, ' Days') }, cal1Month: { get () { return (+dayjs(this.cal1, 'YYYY-MM-DD').format('MM')) - 1 }, set (month) { const newDate = dayjs(this.cal1).month(month) if (newDate.isValid()) this.cal1 = newDate.format('YYYY-MM-DD') } }, cal1Year: { get () { return dayjs(this.cal1, 'YYYY-MM-DD').format('YYYY') }, set (year) { const newDate = dayjs(this.cal1).year(year) if (newDate.isValid()) this.cal1 = newDate.format('YYYY-MM-DD') } }, cal2Month: { get () { return (+dayjs(this.cal2, 'YYYY-MM-DD').format('MM')) - 1 }, set (month) { const newDate = dayjs(this.cal2, 'YYYY-MM-DD').month(month) if (newDate.isValid()) this.cal2 = newDate.format('YYYY-MM-DD') } }, cal2Year: { get () { return dayjs(this.cal2, 'YYYY-MM-DD').format('YYYY') }, set (year) { const newDate = dayjs(this.cal2, 'YYYY-MM-DD').year(year) if (newDate.isValid()) this.cal2 = newDate.format('YYYY-MM-DD') } }, zFromUs: { get () { return dayjs(this.zFrom, 'YYYY-MM-DD').format('MM-DD-YYYY') }, set (date) { if (dayjs(date, 'MM-DD-YYYY').isValid()) this.zFrom = dayjs(date).format('YYYY-MM-DD') this.cal1 = this.zFrom if (dayjs(this.zFrom, 'YYYY-MM-DD').isSame(dayjs(this.zTo, 'YYYY-MM-DD'), 'M')) { this.cal1 = dayjs(this.zFrom, 'YYYY-MM-DD').add(-1, 'M').format('YYYY-MM-DD') } } }, zToUs: { get () { return dayjs(this.zTo, 'YYYY-MM-DD').format('MM-DD-YYYY') }, set (date) { if (dayjs(date, 'MM-DD-YYYY').isValid()) this.zTo = dayjs(date).format('YYYY-MM-DD') this.cal2 = this.zTo if (dayjs(this.zFrom, 'YYYY-MM-DD').isSame(dayjs(this.zTo, 'YYYY-MM-DD'), 'M')) { this.cal1 = dayjs(this.zFrom, 'YYYY-MM-DD').add(-1, 'M').format('YYYY-MM-DD') } } }, startEndDates () { const dates = [] if (this.zFromUnix !== false && this.zToUnix !== false) { if (this.zFromUnix <= this.zToUnix) { dates.push(this.zFrom, this.zTo) } else { dates.push(this.zTo, this.zFrom) } } return dates }, zFromUnix () { if (this.zFrom !== '') { return dayjs(this.zFrom, 'YYYY-MM-DD').unix() } return false }, zToUnix () { if (this.zTo !== '') { return dayjs(this.zTo, 'YYYY-MM-DD').unix() } return false } }, watch: { startEndDates () { this.runUpdate() }, zStart () { this.runUpdate() }, zEnd () { this.runUpdate() }, value () { if (isEqual(this.value.map(d => dayjs(d).format('YYYY-MM-DD')), this.startEndDates)) return this.zFrom = dayjs(this.value[0]).format('YYYY-MM-DD') this.zTo = dayjs(this.value[1]).format('YYYY-MM-DD') } }, created () { this.cal1 = this.zFrom this.cal2 = this.zTo if (dayjs(this.zFrom, 'YYYY-MM-DD').isSame(dayjs(this.zTo, 'YYYY-MM-DD'), 'M')) { this.cal1 = dayjs(this.zFrom, 'YYYY-MM-DD').add(-1, 'M').format('YYYY-MM-DD') } }, methods: { runUpdate () { const startEndISO = [ dayjs(`${this.startEndDates[0]} ${this.zStart}`, 'YYYY-MM-DD hh:mm A').toISOString(), dayjs(`${this.startEndDates[1]} ${this.zEnd}`, 'YYYY-MM-DD hh:mm A').toISOString() ] if (isEqual(this.value, startEndISO)) return this.$emit('input', startEndISO) }, saveTime (model) { this[model] = this[`${model}Picker`] }, classDay (timestamp) { if (this.zFromUnix !== false && this.zToUnix !== false) { return this.getBetween(timestamp) } }, getBetween ({ date }) { const nowIdentifier = dayjs(date, 'YYYY-MM-DD').unix() const lower = Math.min(this.zFromUnix, this.zToUnix) const higher = Math.max(this.zFromUnix, this.zToUnix) return { 'q-selected-day-first': lower === nowIdentifier, 'q-selected-day': lower <= nowIdentifier && higher >= nowIdentifier, 'q-selected-day-last': higher === nowIdentifier } }, onClickDay ({ date }) { if (this.clicked === false) { this.zFrom = date this.zTo = date this.clicked = true return } // mouse is down, start selection and capture current this.clicked = false this.zTo = date }, setRange (when) { const doWhen = this.timeFrames[when] this.zFrom = doWhen.from.format('YYYY-MM-DD') this.zTo = doWhen.to.format('YYYY-MM-DD') this.cal1 = this.zFrom this.cal2 = this.zTo if (dayjs(this.zFrom, 'YYYY-MM-DD').isSame(dayjs(this.zTo, 'YYYY-MM-DD'), 'M')) { this.cal1 = dayjs(this.zFrom, 'YYYY-MM-DD').add(-1, 'M').format('YYYY-MM-DD') } } } } </script> <style lang="scss" scoped></style>