Files
bab-app/src/components/scheduling/boat/CalendarHeaderComponent.vue

243 lines
5.4 KiB
Vue

<template>
<div class="title-bar" style="display: flex">
<button
tabindex="0"
class="date-button direction-button direction-button__left"
@click="onPrev"
>
<span class="q-calendar__focus-helper" tabindex="-1" />
</button>
<div class="dates-holder">
<div :key="parsedStart?.date" class="internal-dates-holder">
<div v-for="day in days" :key="day.date" :style="dayStyle">
<button
tabindex="0"
style="width: 100%"
:class="dayClass(day)"
@click="selectedDate = day.date"
>
<span class="q-calendar__focus-helper" tabindex="-1" />
<div style="width: 100%; font-size: 0.9em">
{{ monthFormatter(day, true) }}
</div>
<div style="width: 100%; font-size: 1.2em; font-weight: 700">
{{ dayFormatter(day, false) }}
</div>
<div style="width: 100%; font-size: 1em">
{{ weekdayFormatter(day, true) }}
</div>
</button>
</div>
</div>
</div>
<button
tabindex="0"
class="date-button direction-button direction-button__right"
@click="onNext"
>
<span class="q-calendar__focus-helper" tabindex="-1" />
</button>
</div>
</template>
<script setup lang="ts">
import {
Timestamp,
addToDate,
createDayList,
createNativeLocaleFormatter,
getEndOfWeek,
getStartOfWeek,
getWeekdaySkips,
parseTimestamp,
today,
} from '@quasar/quasar-ui-qcalendar';
import { ref, reactive, computed } from 'vue';
const selectedDate = defineModel<string>();
const weekdays = reactive([0, 1, 2, 3, 4, 5, 6]),
locale = ref('en-CA'),
monthFormatter = monthFormatterFunc(),
dayFormatter = dayFormatterFunc(),
weekdayFormatter = weekdayFormatterFunc();
const weekdaySkips = computed(() => {
return getWeekdaySkips(weekdays);
});
const parsedStart = computed(() =>
getStartOfWeek(
parseTimestamp(selectedDate.value || today()) as Timestamp,
weekdays,
today2.value as Timestamp
)
);
const parsedEnd = computed(() =>
getEndOfWeek(
parseTimestamp(selectedDate.value || today()) as Timestamp,
weekdays,
today2.value as Timestamp
)
);
const today2 = computed(() => {
return parseTimestamp(today());
});
const days = computed(() => {
if (parsedStart.value && parsedEnd.value) {
return createDayList(
parsedStart.value,
parsedEnd.value,
today2.value as Timestamp,
weekdaySkips.value
);
}
return [];
});
const dayStyle = computed(() => {
const width = 100 / weekdays.length + '%';
return {
width,
};
});
function onPrev() {
const ts = addToDate(parsedStart.value, { day: -7 });
selectedDate.value = ts.date;
}
function onNext() {
const ts = addToDate(parsedStart.value, { day: 7 });
selectedDate.value = ts.date;
}
function dayClass(day: Timestamp) {
return {
'date-button': true,
'selected-date-button': selectedDate.value === day.date,
};
}
function monthFormatterFunc() {
const longOptions = { timeZone: 'UTC', month: 'long' };
const shortOptions = { timeZone: 'UTC', month: 'short' };
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
short ? shortOptions : longOptions
);
}
function weekdayFormatterFunc() {
const longOptions = { timeZone: 'UTC', weekday: 'long' };
const shortOptions = { timeZone: 'UTC', weekday: 'short' };
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
short ? shortOptions : longOptions
);
}
function dayFormatterFunc() {
const longOptions = { timeZone: 'UTC', day: '2-digit' };
const shortOptions = { timeZone: 'UTC', day: 'numeric' };
return createNativeLocaleFormatter(locale.value, (_tms, short) =>
short ? shortOptions : longOptions
);
}
</script>
<style lang="sass">
.title-bar
position: relative
width: 100%
height: 70px
background: white
display: flex
flex-direction: row
flex: 1 0 100%
justify-content: space-between
align-items: center
overflow: hidden
border-radius: 3px
user-select: none
margin: 2px 0px 2px
.dates-holder
position: relative
width: 100%
align-items: center
display: flex
justify-content: space-between
color: #fff
overflow: hidden
user-select: none
.internal-dates-holder
position: relative
width: 100%
display: inline-flex
flex: 1 1 100%
flex-direction: row
justify-content: space-between
overflow: hidden
user-select: none
.direction-button
background: white
color: $primary
width: 40px
max-width: 50px !important
.direction-button__left
&:before
content: '<'
display: inline-flex
flex-direction: column
justify-content: center
height: 100%
font-weight: 900
font-size: 3em
.direction-button__right
&:before
content: '>'
display: inline-flex
flex-direction: column
justify-content: center
height: 100%
font-weight: 900
font-size: 3em
.date-button
color: $primary
background: white
z-index: 2
height: 100%
outline: 0
cursor: pointer
border-radius: 3px
display: inline-flex
flex: 1 0 auto
flex-direction: column
align-items: stretch
position: relative
border: 0
vertical-align: middle
padding: 0
font-size: 14px
line-height: 1.715em
text-decoration: none
font-weight: 500
text-transform: uppercase
text-align: center
user-select: none
.selected-date-button
color: white !important
background: $primary !important
</style>