From f99eeecd20d64a6ace6ce2c53f7691d03a6117f9 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Thu, 3 Sep 2026 21:18:26 +0200 Subject: [PATCH 1/2] fix(calendar): restore selected date --- src/__tests__/date-validation.test.ts | 29 +++++++++++++++++++++++++++ src/lib/components/app/input.svelte | 11 +++++++++- src/lib/helper/date.helper.ts | 18 ++++++++++++++++- src/lib/helper/format.helper.ts | 3 +++ 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/__tests__/date-validation.test.ts b/src/__tests__/date-validation.test.ts index a247b028..7b4b7574 100644 --- a/src/__tests__/date-validation.test.ts +++ b/src/__tests__/date-validation.test.ts @@ -2,8 +2,37 @@ import { describe, expect, it } from 'vitest'; import { apiDateString, dateStringForFormat } from '$lib/domain/shared'; import { maintenanceFormSchema } from '$lib/domain/maintenance'; import { complianceFormSchema } from '$lib/domain/compliance'; +import { parseDateForCalendar, type FormatConfig } from '$lib/helper/date.helper'; + +const formatConfig: FormatConfig = { + dateFormat: 'dd/MM/yyyy', + timezone: 'America/Los_Angeles', + locale: 'en', + currency: 'USD', + unitOfVolume: 'liters', + unitOfLpg: 'liters', + unitOfCng: 'kg', + unitOfDistance: 'km', + mileageUnitFormat: 'km/L' +}; describe('localized date validation', () => { + it('restores calendar dates using the configured display format', () => { + const dayFirst = parseDateForCalendar('13/08/2026', formatConfig); + const monthFirst = parseDateForCalendar('08/13/2026', { + ...formatConfig, + dateFormat: 'MM/dd/yyyy' + }); + + expect(dayFirst?.toString()).toBe('2026-08-13'); + expect(monthFirst?.toString()).toBe('2026-08-13'); + }); + + it('does not restore invalid calendar input values', () => { + expect(parseDateForCalendar('31/02/2026', formatConfig)).toBeUndefined(); + expect(parseDateForCalendar(undefined, formatConfig)).toBeUndefined(); + }); + it('accepts days greater than 12 in day-first formats', () => { expect(dateStringForFormat('dd/MM/yyyy').safeParse('13/08/2026').success).toBe(true); expect(dateStringForFormat('dd/MM/yyyy').safeParse('31/12/2026').success).toBe(true); diff --git a/src/lib/components/app/input.svelte b/src/lib/components/app/input.svelte index aac8f3bc..e9b68d87 100644 --- a/src/lib/components/app/input.svelte +++ b/src/lib/components/app/input.svelte @@ -4,8 +4,9 @@ import type { Component } from 'svelte'; import * as Popover from '$ui/popover'; import { Calendar } from '$lib/components/ui/calendar/index.js'; - import { formatDateForCalendar } from '$lib/helper/format.helper'; + import { formatDateForCalendar, parseDateForCalendar } from '$lib/helper/format.helper'; import * as m from '$lib/paraglide/messages'; + import type { DateValue } from '@internationalized/date'; type InputType = Exclude | 'calendar'; @@ -27,6 +28,13 @@ }: Props = $props(); let open = $state(false); + let calendarValue = $state(); + + $effect(() => { + if (open) { + calendarValue = typeof value === 'string' ? parseDateForCalendar(value) : undefined; + } + });
@@ -75,6 +83,7 @@ id="date-calendar" type="single" captionLayout="dropdown" + bind:value={calendarValue} onValueChange={(v) => { if (v) { value = formatDateForCalendar(v); diff --git a/src/lib/helper/date.helper.ts b/src/lib/helper/date.helper.ts index 2e40a465..29a793c4 100644 --- a/src/lib/helper/date.helper.ts +++ b/src/lib/helper/date.helper.ts @@ -1,4 +1,4 @@ -import type { DateValue } from '@internationalized/date'; +import { CalendarDate, type DateValue } from '@internationalized/date'; import { format, parse } from 'date-fns'; import { formatInTimeZone, fromZonedTime } from 'date-fns-tz'; import { es, fr, de, hi } from 'date-fns/locale'; @@ -49,6 +49,22 @@ export const formatDateForCalendar = (date: DateValue, config: FormatConfig): st return format(dateObj, config.dateFormat, { locale: getDateFnsLocale(config.locale) }); }; +export const parseDateForCalendar = ( + date: string | undefined, + config: FormatConfig +): CalendarDate | undefined => { + if (!date) return undefined; + + const parsedDate = parse(date, config.dateFormat, new Date()); + if (Number.isNaN(parsedDate.getTime())) return undefined; + + return new CalendarDate( + parsedDate.getFullYear(), + parsedDate.getMonth() + 1, + parsedDate.getDate() + ); +}; + export const parseDate = (date: string, config: FormatConfig) => { const parsedDate = parse(date, config.dateFormat, new Date()); return fromZonedTime(parsedDate, config.timezone); diff --git a/src/lib/helper/format.helper.ts b/src/lib/helper/format.helper.ts index 2b7d653e..97c704c8 100644 --- a/src/lib/helper/format.helper.ts +++ b/src/lib/helper/format.helper.ts @@ -3,6 +3,7 @@ import type { FormatConfig } from './date.helper'; import { formatDate as formatDatePure, formatDateForCalendar as formatDateForCalendarPure, + parseDateForCalendar as parseDateForCalendarPure, parseDate as parseDatePure } from './date.helper'; export type { FormatConfig }; @@ -22,6 +23,8 @@ import { export const formatDate = (date: Date | string) => formatDatePure(date, configs); export const formatDateForCalendar = (date: import('@internationalized/date').DateValue) => formatDateForCalendarPure(date, configs); +export const parseDateForCalendar = (date: string | undefined) => + parseDateForCalendarPure(date, configs); export const parseDate = (date: string) => parseDatePure(date, configs); export const getCurrencySymbol = (currency?: string) => getCurrencySymbolPure(currency || configs.currency); From 57285d81bc092fb0a5d8eb1bb79254c6b3c05607 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Thu, 3 Sep 2026 21:18:32 +0200 Subject: [PATCH 2/2] fix(calendar): theme native select options --- src/lib/components/ui/calendar/calendar-month-select.svelte | 1 + src/lib/components/ui/calendar/calendar-year-select.svelte | 1 + 2 files changed, 2 insertions(+) diff --git a/src/lib/components/ui/calendar/calendar-month-select.svelte b/src/lib/components/ui/calendar/calendar-month-select.svelte index a95f8483..c47a1fca 100644 --- a/src/lib/components/ui/calendar/calendar-month-select.svelte +++ b/src/lib/components/ui/calendar/calendar-month-select.svelte @@ -23,6 +23,7 @@