Files
solidtime/resources/js/packages/ui/src/FullCalendar/useCalendarNavigation.ts
2026-07-21 18:54:05 +02:00

110 lines
3.1 KiB
TypeScript

import { computed, ref } from 'vue';
import type { Dayjs } from 'dayjs';
import { getLocalizedDayJs } from '../utils/time';
import { getWeekStartDayNumber } from '../utils/settings';
export function useCalendarNavigation(callbacks: {
onDatesChange: (payload: { start: Dayjs; end: Dayjs }) => void;
scrollToCurrentTime: () => void;
initialDate?: Dayjs | null;
}) {
const activeView = ref('timeGridWeek');
const currentDate = ref(callbacks.initialDate ?? getLocalizedDayJs());
function getFirstDay(): number {
return getWeekStartDayNumber();
}
const viewDays = computed<Dayjs[]>(() => {
const numDays = activeView.value === 'timeGridWeek' ? 7 : 1;
if (numDays === 1) {
return [currentDate.value.startOf('day')];
}
const firstDay = getFirstDay();
const today = currentDate.value.startOf('day');
const offset = (today.day() - firstDay + 7) % 7;
const weekStart = today.subtract(offset, 'day');
const days: Dayjs[] = [];
for (let i = 0; i < numDays; i++) {
days.push(weekStart.add(i, 'day'));
}
return days;
});
const viewTitle = computed(() => {
if (activeView.value === 'timeGridDay') {
return currentDate.value.format('MMMM YYYY');
}
const days = viewDays.value;
if (days.length === 0) return '';
const first = days[0]!;
const last = days[days.length - 1]!;
if (first.year() !== last.year()) {
return `${first.format('MMM YYYY')} \u2013 ${last.format('MMM YYYY')}`;
}
if (first.month() !== last.month()) {
return `${first.format('MMM')} \u2013 ${last.format('MMM YYYY')}`;
}
return first.format('MMMM YYYY');
});
function emitDatesChange() {
const days = viewDays.value;
if (days.length === 0) return;
const start = days[0]!;
const end = days[days.length - 1]!.add(1, 'day');
callbacks.onDatesChange({ start, end });
}
function handlePrev() {
if (activeView.value === 'timeGridWeek') {
currentDate.value = currentDate.value.subtract(7, 'day');
} else {
currentDate.value = currentDate.value.subtract(1, 'day');
}
emitDatesChange();
callbacks.scrollToCurrentTime();
}
function handleNext() {
if (activeView.value === 'timeGridWeek') {
currentDate.value = currentDate.value.add(7, 'day');
} else {
currentDate.value = currentDate.value.add(1, 'day');
}
emitDatesChange();
callbacks.scrollToCurrentTime();
}
function handleToday() {
currentDate.value = getLocalizedDayJs();
emitDatesChange();
callbacks.scrollToCurrentTime();
}
function handleChangeView(view: string) {
activeView.value = view;
emitDatesChange();
callbacks.scrollToCurrentTime();
}
return {
activeView,
currentDate,
viewDays,
viewTitle,
emitDatesChange,
handlePrev,
handleNext,
handleToday,
handleChangeView,
};
}