Date cleanup / refactoring
This commit is contained in:
@@ -25,7 +25,8 @@ import {
|
||||
getLocalizedWeekdayNames,
|
||||
getLocaleWeekendDays,
|
||||
getLocaleFirstDay,
|
||||
isoWeekInfo,
|
||||
getISOWeek,
|
||||
getISOWeekYear,
|
||||
fromLocalString,
|
||||
toLocalString,
|
||||
mondayIndex,
|
||||
@@ -85,7 +86,7 @@ const updateVisibleWeeks = () => {
|
||||
const topDisplayIndex = Math.floor(scrollTop / rowHeight.value)
|
||||
const topVW = topDisplayIndex + minVirtualWeek.value
|
||||
const monday = getMondayForVirtualWeek(topVW)
|
||||
const { year } = isoWeekInfo(monday)
|
||||
const year = getISOWeekYear(monday)
|
||||
if (calendarStore.viewYear !== year) {
|
||||
calendarStore.setViewYear(year)
|
||||
}
|
||||
@@ -102,7 +103,7 @@ const updateVisibleWeeks = () => {
|
||||
|
||||
const newVisibleWeeks = []
|
||||
for (let vw = startVW; vw <= endVW; vw++) {
|
||||
newVisibleWeeks.push({ virtualWeek: vw, monday: getMondayForVirtualWeek(vw) })
|
||||
newVisibleWeeks.push({ virtualWeek: vw, monday: getMondayForVirtualWeek(vw) })
|
||||
}
|
||||
visibleWeeks.value = newVisibleWeeks
|
||||
}
|
||||
@@ -126,7 +127,7 @@ const handleWheel = (e) => {
|
||||
|
||||
const navigateToYear = (targetYear, weekIndex) => {
|
||||
const monday = getMondayForVirtualWeek(weekIndex)
|
||||
const { week } = isoWeekInfo(monday)
|
||||
const week = getISOWeek(monday)
|
||||
const jan4 = new Date(targetYear, 0, 4)
|
||||
const jan4Monday = addDays(jan4, -mondayIndex(jan4))
|
||||
const targetMonday = addDays(jan4Monday, (week - 1) * 7)
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { useCalendarStore } from '@/stores/CalendarStore'
|
||||
import { getLocalizedWeekdayNames, reorderByFirstDay, isoWeekInfo } from '@/utils/date'
|
||||
import {
|
||||
getLocalizedWeekdayNames,
|
||||
reorderByFirstDay,
|
||||
getISOWeek,
|
||||
getISOWeekYear,
|
||||
} from '@/utils/date'
|
||||
import Numeric from '@/components/Numeric.vue'
|
||||
import { addDays } from 'date-fns'
|
||||
|
||||
@@ -27,7 +32,7 @@ const topVirtualWeek = computed(() => {
|
||||
const currentYear = computed(() => {
|
||||
const weekStart = addDays(baseDate.value, topVirtualWeek.value * 7)
|
||||
const anchor = addDays(weekStart, (4 - weekStart.getDay() + 7) % 7)
|
||||
return isoWeekInfo(anchor).year
|
||||
return getISOWeekYear(anchor)
|
||||
})
|
||||
|
||||
function virtualWeekOf(d) {
|
||||
@@ -53,10 +58,10 @@ function changeYear(y) {
|
||||
// Anchor Thursday of current calendar week
|
||||
const curCalWeekStart = addDays(baseDate.value, vw * 7)
|
||||
const curAnchorThu = addDays(curCalWeekStart, (4 - curCalWeekStart.getDay() + 7) % 7)
|
||||
let { week: isoW } = isoWeekInfo(curAnchorThu)
|
||||
let isoW = getISOWeek(curAnchorThu)
|
||||
// Build Monday of ISO week
|
||||
let weekMon = isoWeekMonday(y, isoW)
|
||||
if (isoWeekInfo(weekMon).year !== y) {
|
||||
if (getISOWeekYear(weekMon) !== y) {
|
||||
isoW--
|
||||
weekMon = isoWeekMonday(y, isoW)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import CalendarWeek from '@/components/CalendarWeek.vue'
|
||||
import Jogwheel from '@/components/Jogwheel.vue'
|
||||
import SettingsDialog from '@/components/SettingsDialog.vue'
|
||||
import {
|
||||
isoWeekInfo,
|
||||
getLocalizedMonthName,
|
||||
monthAbbr,
|
||||
lunarPhaseSymbol,
|
||||
@@ -17,6 +16,7 @@ import {
|
||||
getMondayOfISOWeek,
|
||||
getOccurrenceIndex,
|
||||
getVirtualOccurrenceEndDate,
|
||||
getISOWeek,
|
||||
} from '@/utils/date'
|
||||
import { toLocalString, fromLocalString, DEFAULT_TZ } from '@/utils/date'
|
||||
import { addDays, differenceInCalendarDays } from 'date-fns'
|
||||
@@ -134,7 +134,7 @@ function getFirstDayForVirtualWeek(virtualWeek) {
|
||||
function createWeek(virtualWeek) {
|
||||
const firstDay = getFirstDayForVirtualWeek(virtualWeek)
|
||||
const isoAnchor = addDays(firstDay, (4 - firstDay.getDay() + 7) % 7)
|
||||
const weekNumber = isoWeekInfo(isoAnchor).week
|
||||
const weekNumber = getISOWeek(isoAnchor)
|
||||
const days = []
|
||||
let cur = new Date(firstDay)
|
||||
let hasFirst = false
|
||||
@@ -149,7 +149,7 @@ function createWeek(virtualWeek) {
|
||||
}
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const dateStr = toLocalString(cur, DEFAULT_TZ)
|
||||
const dateStr = toLocalString(cur, DEFAULT_TZ)
|
||||
const storedEvents = []
|
||||
|
||||
// Find all non-repeating events that occur on this date
|
||||
@@ -175,19 +175,19 @@ function createWeek(virtualWeek) {
|
||||
}
|
||||
|
||||
// Check if any virtual occurrence spans this date
|
||||
const baseStart = fromLocalString(base.startDate, DEFAULT_TZ)
|
||||
const baseEnd = fromLocalString(base.endDate, DEFAULT_TZ)
|
||||
const spanDays = Math.max(0, differenceInCalendarDays(baseEnd, baseStart))
|
||||
const currentDate = fromLocalString(dateStr, DEFAULT_TZ)
|
||||
const baseStart = fromLocalString(base.startDate, DEFAULT_TZ)
|
||||
const baseEnd = fromLocalString(base.endDate, DEFAULT_TZ)
|
||||
const spanDays = Math.max(0, differenceInCalendarDays(baseEnd, baseStart))
|
||||
const currentDate = fromLocalString(dateStr, DEFAULT_TZ)
|
||||
|
||||
let occurrenceFound = false
|
||||
|
||||
// Walk backwards within span to find occurrence start
|
||||
for (let offset = 0; offset <= spanDays && !occurrenceFound; offset++) {
|
||||
const candidateStart = addDays(currentDate, -offset)
|
||||
const candidateStartStr = toLocalString(candidateStart, DEFAULT_TZ)
|
||||
const candidateStart = addDays(currentDate, -offset)
|
||||
const candidateStartStr = toLocalString(candidateStart, DEFAULT_TZ)
|
||||
|
||||
const occurrenceIndex = getOccurrenceIndex(base, candidateStartStr, DEFAULT_TZ)
|
||||
const occurrenceIndex = getOccurrenceIndex(base, candidateStartStr, DEFAULT_TZ)
|
||||
if (occurrenceIndex !== null) {
|
||||
// Calculate the end date of this occurrence
|
||||
const virtualEndDate = getVirtualOccurrenceEndDate(base, candidateStartStr, DEFAULT_TZ)
|
||||
@@ -252,18 +252,18 @@ function createWeek(virtualWeek) {
|
||||
dateStr <= addDaysStr(selection.value.startDate, selection.value.dayCount - 1),
|
||||
events: dayEvents,
|
||||
})
|
||||
cur = addDays(cur, 1)
|
||||
cur = addDays(cur, 1)
|
||||
}
|
||||
|
||||
let monthLabel = null
|
||||
if (hasFirst && monthToLabel !== null) {
|
||||
if (labelYear && labelYear <= calendarStore.config.max_year) {
|
||||
let weeksSpan = 0
|
||||
const d = addDays(cur, -1)
|
||||
const d = addDays(cur, -1)
|
||||
|
||||
for (let i = 0; i < 6; i++) {
|
||||
const probe = addDays(cur, -1 + i * 7)
|
||||
d.setTime(probe.getTime())
|
||||
const probe = addDays(cur, -1 + i * 7)
|
||||
d.setTime(probe.getTime())
|
||||
if (d.getMonth() === monthToLabel) weeksSpan++
|
||||
}
|
||||
|
||||
@@ -337,7 +337,7 @@ function calculateSelection(anchorStr, otherStr) {
|
||||
if (forward) {
|
||||
return { startDate: anchorStr, dayCount: limit }
|
||||
} else {
|
||||
const startDate = addDaysStr(anchorStr, -(limit - 1), DEFAULT_TZ)
|
||||
const startDate = addDaysStr(anchorStr, -(limit - 1), DEFAULT_TZ)
|
||||
return { startDate, dayCount: limit }
|
||||
}
|
||||
}
|
||||
@@ -441,7 +441,7 @@ watch(
|
||||
() => calendarStore.config.first_day,
|
||||
() => {
|
||||
const currentTopVW = Math.floor(scrollTop.value / rowHeight.value) + minVirtualWeek.value
|
||||
const currentTopDate = getFirstDayForVirtualWeek(currentTopVW)
|
||||
const currentTopDate = getFirstDayForVirtualWeek(currentTopVW)
|
||||
requestAnimationFrame(() => {
|
||||
const newTopWeekIndex = getWeekIndex(currentTopDate)
|
||||
const newScroll = (newTopWeekIndex - minVirtualWeek.value) * rowHeight.value
|
||||
|
||||
@@ -4,7 +4,13 @@ import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
|
||||
import BaseDialog from './BaseDialog.vue'
|
||||
import WeekdaySelector from './WeekdaySelector.vue'
|
||||
import Numeric from './Numeric.vue'
|
||||
import { addDaysStr, getMondayOfISOWeek, fromLocalString, toLocalString, DEFAULT_TZ } from '@/utils/date'
|
||||
import {
|
||||
addDaysStr,
|
||||
getMondayOfISOWeek,
|
||||
fromLocalString,
|
||||
toLocalString,
|
||||
DEFAULT_TZ,
|
||||
} from '@/utils/date'
|
||||
import { addDays, addMonths } from 'date-fns'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -318,9 +324,9 @@ function openEditDialog(payload) {
|
||||
// Compute occurrenceDate based on occurrenceIndex rather than parsing instanceId
|
||||
if (event.isRepeating) {
|
||||
if (event.repeat === 'weeks' && occurrenceIndex >= 0) {
|
||||
const pattern = event.repeatWeekdays || []
|
||||
const baseStart = fromLocalString(event.startDate, DEFAULT_TZ)
|
||||
const baseEnd = fromLocalString(event.endDate, DEFAULT_TZ)
|
||||
const pattern = event.repeatWeekdays || []
|
||||
const baseStart = fromLocalString(event.startDate, DEFAULT_TZ)
|
||||
const baseEnd = fromLocalString(event.endDate, DEFAULT_TZ)
|
||||
if (occurrenceIndex === 0) {
|
||||
occurrenceDate = baseStart
|
||||
weekday = baseStart.getDay()
|
||||
@@ -334,7 +340,7 @@ function openEditDialog(payload) {
|
||||
const diff = Math.floor((blk - baseBlockStart) / WEEK_MS)
|
||||
return diff % interval === 0
|
||||
}
|
||||
let cur = addDays(baseEnd, 1)
|
||||
let cur = addDays(baseEnd, 1)
|
||||
let found = 0 // number of repeat occurrences found so far
|
||||
let safety = 0
|
||||
while (found < occurrenceIndex && safety < 20000) {
|
||||
@@ -349,8 +355,8 @@ function openEditDialog(payload) {
|
||||
weekday = cur.getDay()
|
||||
}
|
||||
} else if (event.repeat === 'months' && occurrenceIndex >= 0) {
|
||||
const baseDate = fromLocalString(event.startDate, DEFAULT_TZ)
|
||||
occurrenceDate = addMonths(baseDate, occurrenceIndex)
|
||||
const baseDate = fromLocalString(event.startDate, DEFAULT_TZ)
|
||||
occurrenceDate = addMonths(baseDate, occurrenceIndex)
|
||||
}
|
||||
}
|
||||
dialogMode.value = 'edit'
|
||||
@@ -556,7 +562,7 @@ const formattedOccurrenceShort = computed(() => {
|
||||
const ev = calendarStore.getEventById(editingEventId.value)
|
||||
if (ev?.startDate) {
|
||||
try {
|
||||
return fromLocalString(ev.startDate, DEFAULT_TZ)
|
||||
return fromLocalString(ev.startDate, DEFAULT_TZ)
|
||||
.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
|
||||
.replace(/, /, ' ')
|
||||
} catch {
|
||||
@@ -584,7 +590,7 @@ const headerDateShort = computed(() => {
|
||||
const ev = calendarStore.getEventById(editingEventId.value)
|
||||
if (ev?.startDate) {
|
||||
try {
|
||||
return fromLocalString(ev.startDate, DEFAULT_TZ)
|
||||
return fromLocalString(ev.startDate, DEFAULT_TZ)
|
||||
.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
|
||||
.replace(/, /, ' ')
|
||||
} catch {
|
||||
@@ -616,16 +622,16 @@ const finalOccurrenceDate = computed(() => {
|
||||
// Convert to Monday-first index
|
||||
// We'll just check store pattern
|
||||
if (pattern[startWeekdaySun]) occs = 1
|
||||
let cursor = new Date(start)
|
||||
let cursor = new Date(start)
|
||||
while (occs < count && occs < 10000) {
|
||||
cursor = addDays(cursor, 1)
|
||||
cursor = addDays(cursor, 1)
|
||||
if (pattern[cursor.getDay()]) occs++
|
||||
}
|
||||
if (occs === count) return cursor
|
||||
return null
|
||||
} else if (uiDisplayFrequency.value === 'months') {
|
||||
const monthsToAdd = displayInterval.value * (count - 1)
|
||||
return addMonths(start, monthsToAdd)
|
||||
const monthsToAdd = displayInterval.value * (count - 1)
|
||||
return addMonths(start, monthsToAdd)
|
||||
} else if (uiDisplayFrequency.value === 'years') {
|
||||
const yearsToAdd = displayInterval.value * (count - 1)
|
||||
const d = new Date(start)
|
||||
|
||||
@@ -141,9 +141,9 @@ function resetAll() {
|
||||
if (typeof calendarStore.$reset === 'function') {
|
||||
calendarStore.$reset()
|
||||
} else {
|
||||
const now = new Date()
|
||||
calendarStore.today = now.toISOString().slice(0, 10)
|
||||
calendarStore.now = now.toISOString()
|
||||
const now = new Date()
|
||||
calendarStore.today = now.toISOString().slice(0, 10)
|
||||
calendarStore.now = now.toISOString()
|
||||
calendarStore.events = new Map()
|
||||
calendarStore.weekend = [6, 0]
|
||||
calendarStore.config.first_day = 1
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
<!-- Event spans will be rendered here -->
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="monthLabel" class="month-name-label" :style="{ height: `${monthLabel.weeksSpan * 64}px` }">
|
||||
<div
|
||||
v-if="monthLabel"
|
||||
class="month-name-label"
|
||||
:style="{ height: `${monthLabel.weeksSpan * 64}px` }"
|
||||
>
|
||||
<span>{{ monthLabel.name }} '{{ monthLabel.year }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -16,19 +20,23 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import DayCell from './DayCell.vue'
|
||||
import { isoWeekInfo, toLocalString, getLocalizedMonthName, monthAbbr, DEFAULT_TZ } from '@/utils/date'
|
||||
import {
|
||||
toLocalString,
|
||||
getLocalizedMonthName,
|
||||
monthAbbr,
|
||||
DEFAULT_TZ,
|
||||
getISOWeek,
|
||||
} from '@/utils/date'
|
||||
import { addDays } from 'date-fns'
|
||||
|
||||
const props = defineProps({
|
||||
week: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const weekNumber = computed(() => {
|
||||
return isoWeekInfo(props.week.monday).week
|
||||
})
|
||||
const weekNumber = computed(() => getISOWeek(props.week.monday))
|
||||
|
||||
const days = computed(() => {
|
||||
const d = new Date(props.week.monday)
|
||||
@@ -41,7 +49,7 @@ const days = computed(() => {
|
||||
dayOfMonth: d.getDate(),
|
||||
month: d.getMonth(),
|
||||
isFirstDayOfMonth: d.getDate() === 1,
|
||||
monthClass: monthAbbr[d.getMonth()]
|
||||
monthClass: monthAbbr[d.getMonth()],
|
||||
})
|
||||
d.setTime(addDays(d, 1).getTime())
|
||||
}
|
||||
@@ -49,19 +57,19 @@ const days = computed(() => {
|
||||
})
|
||||
|
||||
const monthLabel = computed(() => {
|
||||
const firstDayOfMonth = days.value.find(d => d.isFirstDayOfMonth)
|
||||
const firstDayOfMonth = days.value.find((d) => d.isFirstDayOfMonth)
|
||||
if (!firstDayOfMonth) return null
|
||||
|
||||
const month = firstDayOfMonth.month
|
||||
const year = firstDayOfMonth.date.getFullYear()
|
||||
|
||||
|
||||
// This is a simplified calculation for weeksSpan
|
||||
const weeksSpan = 4
|
||||
const weeksSpan = 4
|
||||
|
||||
return {
|
||||
name: getLocalizedMonthName(month),
|
||||
name: getLocalizedMonthName(month),
|
||||
year: String(year).slice(-2),
|
||||
weeksSpan
|
||||
weeksSpan,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user