Adapt date display logic to Vuepic component

This commit is contained in:
Maciej Pędzich 2022-07-20 21:42:25 +02:00
parent 5a5516e10f
commit c22c382e02

View File

@ -1,21 +1,11 @@
<!-- eslint-disable vue/multi-word-component-names --> <!-- eslint-disable vue/multi-word-component-names -->
<script setup lang="ts"> <script setup lang="ts">
import { useMediaQuery } from '@vueuse/core';
import ProgressSpinner from 'primevue/progressspinner'; import ProgressSpinner from 'primevue/progressspinner';
import Calendar from 'primevue/calendar'; import Datepicker from '@vuepic/vue-datepicker';
import { CalendarEntry } from '~~/models/calendar-entry'; import { CalendarEntry } from '~~/models/calendar-entry';
// Moving these interfaces to separate files makes TypeScript scream at you // Moving this interfaces to separate files makes TypeScript scream at you
interface PrimeVueDate {
day: number;
month: number;
year: number;
today: boolean;
otherMonth: boolean;
}
interface DateChangePayload { interface DateChangePayload {
month: number; month: number;
year: number; year: number;
@ -26,13 +16,13 @@ defineProps<{ page: 'snapshot-pick' | 'compare' }>();
const route = useRoute(); const route = useRoute();
const playlistId = route.params.playlistId; const playlistId = route.params.playlistId;
const isPortableScreen = useMediaQuery('(max-width: 768px)'); const now = new Date();
const minDate = new Date('2021-12-01');
const queryMonth = ref(now.getMonth());
const queryYear = ref(now.getFullYear());
const displayDate = reactive({ month: queryMonth, year: queryYear });
const calendarDisplayDate = ref(new Date()); const hoursOffset = -(now.getTimezoneOffset() / 60);
const queryMonth = ref(calendarDisplayDate.value.getMonth());
const queryYear = ref(calendarDisplayDate.value.getFullYear());
const hoursOffset = -(calendarDisplayDate.value.getTimezoneOffset() / 60);
const sinceDateParam = computed(() => const sinceDateParam = computed(() =>
new Date(queryYear.value, queryMonth.value, 1, hoursOffset).toISOString() new Date(queryYear.value, queryMonth.value, 1, hoursOffset).toISOString()
); );
@ -64,12 +54,19 @@ const {
const snapshotLinkMap = computed<Record<string, string>>(() => const snapshotLinkMap = computed<Record<string, string>>(() =>
(calendarEntries.value || []).reduce((map, entry) => { (calendarEntries.value || []).reduce((map, entry) => {
const dateCapturedKey = entry.dateCaptured.substring(0, 10); const dayCapturedKey = entry.dateCaptured.substring(8, 10);
map[dateCapturedKey] = `./snapshots/show/${entry.commitSha}`;
map[dayCapturedKey] = `./snapshots/show/${entry.commitSha}`;
return map; return map;
}, {}) }, {})
); );
const allowedDates = computed(() =>
Object.keys(JSON.parse(JSON.stringify(snapshotLinkMap.value))).map(
(dayKey) =>
new Date(queryYear.value, queryMonth.value, Number(dayKey), hoursOffset)
)
);
const updateQueryAndReload = async ({ month, year }: DateChangePayload) => { const updateQueryAndReload = async ({ month, year }: DateChangePayload) => {
queryMonth.value = month; queryMonth.value = month;
@ -78,18 +75,12 @@ const updateQueryAndReload = async ({ month, year }: DateChangePayload) => {
await reloadCalendarEntries(); await reloadCalendarEntries();
}; };
const primeVueDateToString = ({ year, month, day }: PrimeVueDate) => const getSnapshotLinkFromDate = (day: number) =>
// PrimeVue Calendar dates' months are zero-based snapshotLinkMap.value[day.toString().padStart(2, '0')];
// Just like in JavaScript date objects
[year, month + 1, day]
.map((num) => num.toString().padStart(2, '0'))
.join('-');
const getSnapshotLinkFromDate = (calendarDate: PrimeVueDate) => const isDayCaptured = (day: number) => !!getSnapshotLinkFromDate(day);
snapshotLinkMap.value[primeVueDateToString(calendarDate)];
const isDateCaptured = (calendarDate: PrimeVueDate) => const isQueryMonth = (date: Date) => date.getMonth() === queryMonth.value;
!!getSnapshotLinkFromDate(calendarDate);
</script> </script>
<template> <template>
@ -105,40 +96,59 @@ const isDateCaptured = (calendarDate: PrimeVueDate) =>
> >
Something went wrong while fetching archive entries Something went wrong while fetching archive entries
</p> </p>
<!-- Changing v-show to v-if breaks month/year change handling --> <Datepicker
<Calendar
v-show="!loadingCalendarEntries" v-show="!loadingCalendarEntries"
v-model="calendarDisplayDate" v-model="displayDate"
:disabled="loadingCalendarEntries" :min-date="minDate"
:touch-u-i="isPortableScreen" :max-date="now"
:allowed-dates="allowedDates"
:enable-time-picker="false"
:month-change-on-arrows="false"
:month-change-on-scroll="false"
no-today
prevent-min-max-navigation
inline inline
@month-change="updateQueryAndReload" dark
@year-change="updateQueryAndReload" @update-month-year="updateQueryAndReload"
> >
<template #date="{ date }"> <template #day="{ day, date }">
<NuxtLink <NuxtLink
v-if="isDateCaptured(date as PrimeVueDate)" v-if="isQueryMonth(date) && isDayCaptured(day)"
:to="getSnapshotLinkFromDate(date as PrimeVueDate)" class="w-full h-full"
:to="getSnapshotLinkFromDate(day)"
> >
<span class="bg-primary hover:bg-green-400 text-0 p-3 border-round"> <div
{{ (date as PrimeVueDate).day }} class="w-full h-full flex justify-content-center align-items-center bg-primary hover:bg-green-400 text-0 border-round"
</span> >
{{ day }}
</div>
</NuxtLink> </NuxtLink>
<span v-else> <div v-else class="m-2">
{{ (date as PrimeVueDate).day }} {{ day }}
</span> </div>
</template> </template>
</Calendar> </Datepicker>
</ClientOnly> </ClientOnly>
</NuxtLayout> </NuxtLayout>
</template> </template>
<style scoped> <style scoped>
:deep(.p-datepicker table td.p-datepicker-today > span.p-highlight) { :deep(div.dp__calendar_header) {
background-color: transparent; width: 100%;
padding: 0.4rem 0.2rem;
} }
:deep(.p-datepicker table.p-datepicker-calendar td > span.p-highlight) { :deep(div.dp__cell_inner) {
background-color: transparent; margin: 0.5rem;
padding: 0;
}
:deep(div.dp__overlay_cell_active) {
background-color: var(--primary-color);
color: var(--surface-0);
}
:deep(div.dp__action_row:last-of-type) {
display: none;
} }
</style> </style>