mirror of
https://github.com/maciejpedzich/spotifyplaylistarchive.com.git
synced 2024-09-19 18:16:19 +02:00
Adapt date display logic to Vuepic component
This commit is contained in:
parent
5a5516e10f
commit
c22c382e02
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user