Date formatting cleanup, added utility functions to avoid repetition.
This commit is contained in:
		| @@ -13,7 +13,7 @@ import { | |||||||
|   daysInclusive, |   daysInclusive, | ||||||
|   addDaysStr, |   addDaysStr, | ||||||
|   formatDateRange, |   formatDateRange, | ||||||
|   getMondayOfISOWeek, |   formatTodayString, | ||||||
|   getOccurrenceIndex, |   getOccurrenceIndex, | ||||||
|   getVirtualOccurrenceEndDate, |   getVirtualOccurrenceEndDate, | ||||||
|   getISOWeek, |   getISOWeek, | ||||||
| @@ -83,10 +83,7 @@ const selectedDateRange = computed(() => { | |||||||
|  |  | ||||||
| const todayString = computed(() => { | const todayString = computed(() => { | ||||||
|   const d = new Date(calendarStore.now) |   const d = new Date(calendarStore.now) | ||||||
|   const t = d |   return formatTodayString(d) | ||||||
|     .toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric' }) |  | ||||||
|     .replace(/,? /, '\n') |  | ||||||
|   return t.charAt(0).toUpperCase() + t.slice(1) |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| const visibleWeeks = computed(() => { | const visibleWeeks = computed(() => { | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import { ref, computed, watch, onUnmounted, nextTick } from 'vue' | |||||||
| import BaseDialog from './BaseDialog.vue' | import BaseDialog from './BaseDialog.vue' | ||||||
| import WeekdaySelector from './WeekdaySelector.vue' | import WeekdaySelector from './WeekdaySelector.vue' | ||||||
| import Numeric from './Numeric.vue' | import Numeric from './Numeric.vue' | ||||||
| import { addDaysStr, getMondayOfISOWeek, fromLocalString, DEFAULT_TZ } from '@/utils/date' | import { addDaysStr, getMondayOfISOWeek, fromLocalString, formatDateShort, formatDateLong, DEFAULT_TZ } from '@/utils/date' | ||||||
| import { addDays, addMonths } from 'date-fns' | import { addDays, addMonths } from 'date-fns' | ||||||
|  |  | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
| @@ -440,24 +440,12 @@ const isLastOccurrence = computed(() => { | |||||||
| }) | }) | ||||||
| const formattedOccurrenceShort = computed(() => { | const formattedOccurrenceShort = computed(() => { | ||||||
|   if (occurrenceContext.value?.occurrenceDate) { |   if (occurrenceContext.value?.occurrenceDate) { | ||||||
|     try { |     return formatDateShort(occurrenceContext.value.occurrenceDate) | ||||||
|       return occurrenceContext.value.occurrenceDate |  | ||||||
|         .toLocaleDateString(undefined, { month: 'short', day: 'numeric' }) |  | ||||||
|         .replace(/, /, ' ') |  | ||||||
|     } catch { |  | ||||||
|       /* noop */ |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|   if (isRepeatingBaseEdit.value && editingEventId.value) { |   if (isRepeatingBaseEdit.value && editingEventId.value) { | ||||||
|     const ev = calendarStore.getEventById(editingEventId.value) |     const ev = calendarStore.getEventById(editingEventId.value) | ||||||
|     if (ev?.startDate) { |     if (ev?.startDate) { | ||||||
|       try { |       return formatDateShort(fromLocalString(ev.startDate, DEFAULT_TZ)) | ||||||
|         return fromLocalString(ev.startDate, DEFAULT_TZ) |  | ||||||
|           .toLocaleDateString(undefined, { month: 'short', day: 'numeric' }) |  | ||||||
|           .replace(/, /, ' ') |  | ||||||
|       } catch { |  | ||||||
|         /* noop */ |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   return '' |   return '' | ||||||
| @@ -465,24 +453,12 @@ const formattedOccurrenceShort = computed(() => { | |||||||
|  |  | ||||||
| const headerDateShort = computed(() => { | const headerDateShort = computed(() => { | ||||||
|   if (occurrenceContext.value?.occurrenceDate) { |   if (occurrenceContext.value?.occurrenceDate) { | ||||||
|     try { |     return formatDateShort(occurrenceContext.value.occurrenceDate) | ||||||
|       return occurrenceContext.value.occurrenceDate |  | ||||||
|         .toLocaleDateString(undefined, { month: 'short', day: 'numeric' }) |  | ||||||
|         .replace(/, /, ' ') |  | ||||||
|     } catch { |  | ||||||
|       return '' |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
|   if (editingEventId.value) { |   if (editingEventId.value) { | ||||||
|     const ev = calendarStore.getEventById(editingEventId.value) |     const ev = calendarStore.getEventById(editingEventId.value) | ||||||
|     if (ev?.startDate) { |     if (ev?.startDate) { | ||||||
|       try { |       return formatDateShort(fromLocalString(ev.startDate, DEFAULT_TZ)) | ||||||
|         return fromLocalString(ev.startDate, DEFAULT_TZ) |  | ||||||
|           .toLocaleDateString(undefined, { month: 'short', day: 'numeric' }) |  | ||||||
|           .replace(/, /, ' ') |  | ||||||
|       } catch { |  | ||||||
|         return '' |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   return '' |   return '' | ||||||
| @@ -533,17 +509,7 @@ const formattedFinalOccurrence = computed(() => { | |||||||
|   const includeYear = |   const includeYear = | ||||||
|     d.getFullYear() !== now.getFullYear() || |     d.getFullYear() !== now.getFullYear() || | ||||||
|     d.getTime() - now.getTime() >= 1000 * 60 * 60 * 24 * 365 |     d.getTime() - now.getTime() >= 1000 * 60 * 60 * 24 * 365 | ||||||
|   const opts = { |   return formatDateLong(d, includeYear) | ||||||
|     weekday: 'short', |  | ||||||
|     month: 'short', |  | ||||||
|     day: 'numeric', |  | ||||||
|     ...(includeYear ? { year: 'numeric' } : {}), |  | ||||||
|   } |  | ||||||
|   try { |  | ||||||
|     return d.toLocaleDateString(undefined, opts) |  | ||||||
|   } catch { |  | ||||||
|     return d.toDateString() |  | ||||||
|   } |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| const recurrenceSummary = computed(() => { | const recurrenceSummary = computed(() => { | ||||||
|   | |||||||
| @@ -287,6 +287,37 @@ function lunarPhaseSymbol(date) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // Exports ----------------------------------------------------------------- | // Exports ----------------------------------------------------------------- | ||||||
|  | /** | ||||||
|  |  * Format date as short localized string (e.g., "Jan 15") | ||||||
|  |  */ | ||||||
|  | function formatDateShort(date) { | ||||||
|  |   return date.toLocaleDateString(undefined, { month: 'short', day: 'numeric' }) | ||||||
|  |     .replace(/, /, ' ') | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Format date as long localized string with optional year (e.g., "Mon Jan 15" or "Mon Jan 15, 2025") | ||||||
|  |  */ | ||||||
|  | function formatDateLong(date, includeYear = false) { | ||||||
|  |   const opts = { | ||||||
|  |     weekday: 'short', | ||||||
|  |     month: 'short', | ||||||
|  |     day: 'numeric', | ||||||
|  |     ...(includeYear ? { year: 'numeric' } : {}), | ||||||
|  |   } | ||||||
|  |   return date.toLocaleDateString(undefined, opts) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Format date as today string (e.g., "Monday\nJanuary 15") | ||||||
|  |  */ | ||||||
|  | function formatTodayString(date) { | ||||||
|  |   const formatted = date | ||||||
|  |     .toLocaleDateString(undefined, { weekday: 'long', month: 'long', day: 'numeric' }) | ||||||
|  |     .replace(/,? /, '\n') | ||||||
|  |   return formatted.charAt(0).toUpperCase() + formatted.slice(1) | ||||||
|  | } | ||||||
|  |  | ||||||
| export { | export { | ||||||
|   // constants |   // constants | ||||||
|   monthAbbr, |   monthAbbr, | ||||||
| @@ -311,6 +342,9 @@ export { | |||||||
|   reorderByFirstDay, |   reorderByFirstDay, | ||||||
|   getLocalizedMonthName, |   getLocalizedMonthName, | ||||||
|   formatDateRange, |   formatDateRange, | ||||||
|  |   formatDateShort, | ||||||
|  |   formatDateLong, | ||||||
|  |   formatTodayString, | ||||||
|   lunarPhaseSymbol, |   lunarPhaseSymbol, | ||||||
|   // iso helpers re-export |   // iso helpers re-export | ||||||
|   getISOWeek, |   getISOWeek, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Leo Vasanko
					Leo Vasanko