Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/funny-planes-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@evidence-dev/core-components': major
---

- Timezone Fixes
- Changed the default value to today
- Year select only shows the first and last date in the data
- Disabled dates that are before or after the first and last date
- Added Today and Yesterday range presets
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
/** @type {boolean| string} */
export let range = false;
$: range = toBoolean(range);
/** @type {boolean | string} */
export let defaultToToday = false;

let query;
let errors = [];
Expand Down Expand Up @@ -78,11 +80,9 @@
$: startString = formatDateString(start || $query?.[0].start || new Date(0));
$: endString = formatDateString(end || $query?.[0].end || new Date());

let currentDate = dateToYYYYMMDD(new Date());

let extraDayEndString;

$: if (endString && range) {
$: if (endString) {
extraDayEndString = new Date(endString);
extraDayEndString.setDate(extraDayEndString.getDate() + 1);
extraDayEndString = formatDateString(extraDayEndString);
Expand Down Expand Up @@ -151,10 +151,12 @@
loaded={loaded?.ready ?? true}
{presetRanges}
{defaultValue}
{defaultToToday}
{range}
{currentDate}
{title}
{description}
{data}
{dates}
/>
</QueryLoad>
{/if}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
startOfMonth,
endOfMonth,
startOfYear,
endOfYear
endOfYear,
today
} from '@internationalized/date';
import { cn } from '$lib/utils.js';
import { Button } from '$lib/atoms/shadcn/button/index.js';
Expand All @@ -33,133 +34,197 @@
dateStyle: 'short'
});

const todayDate = today(getLocalTimeZone());

/** @type {import('bits-ui').DateRange | undefined} */
let selectedDateInput = undefined;

$: referenceDate = (() => {
if (selectedDateInput && !range) {
return selectedDateInput;
}
if (selectedDateInput && selectedDateInput.end) {
return selectedDateInput.end;
}
// If today is outside the data range, use calendarEnd as reference for presets
if (calendarEnd && todayDate.compare(calendarEnd) > 0) {
return calendarEnd;
}
if (calendarStart && todayDate.compare(calendarStart) < 0) {
return calendarStart;
}
return todayDate;
})();

/** @type {(selectedDateInput: import('bits-ui').DateRange | undefined) => void} */
export let onSelectedDateInputChange;
/** @type {string} */
export let start;
export let start = undefined;
/** @type {string} */
export let end;
export let end = undefined;
export let loaded = true;
/** @type {[]string] | undefined} */
export let presetRanges;
export let presetRanges = undefined;
/** @type {string] | undefined} */
export let defaultValue;
export let defaultValue = undefined;
/** @type {boolean} */
export let range = false;
$: range = toBoolean(range);
/** @type {boolean} */
export let defaultToToday = false;
$: defaultToToday = toBoolean(defaultToToday);
/** @type {string} */
export let title;
export let title = undefined;
export let extraDayEndString = undefined;
/** @type {string | undefined} */
export let description = undefined;
/** @type {any} */
export let data = undefined;
/** @type {string | undefined} */
export let dates = undefined;

// Extract available years from data if provided
$: extractedYears = (() => {
if (!data || !dates || !data.rows) {
return undefined;
}

const years = new Set();
data.rows.forEach((row) => {
if (row[dates]) {
const year = new Date(row[dates]).getFullYear();
years.add(year);
}
});

return Array.from(years).sort((a, b) => b - a);
})();

$: calendarStart = start ? YYYYMMDDToCalendar(start) : todayDate.subtract({ years: 10 });
// Use extraDayEndString for safety measures if available, otherwise use regular end
$: calendarEnd =
extraDayEndString || end ? YYYYMMDDToCalendar(extraDayEndString || end) : todayDate;

/** @type { { label: string, group: string, range: import('bits-ui').DateRange }[] } */
$: presets = [
{
label: 'Yesterday',
group: 'Days',
range: {
start: todayDate.subtract({ days: 1 }),
end: todayDate.subtract({ days: 1 })
}
},
{
label: 'Today',
group: 'Days',
range: {
start: todayDate,
end: todayDate
}
},
{
label: 'Last 7 Days',
group: 'Days',
range: {
start: calendarEnd.subtract({ days: 6 }),
end: calendarEnd
start: referenceDate.subtract({ days: 6 }),
end: referenceDate
}
},
{
label: 'Last 30 Days',
group: 'Days',
range: {
start: calendarEnd.subtract({ days: 29 }),
end: calendarEnd
start: referenceDate.subtract({ days: 29 }),
end: referenceDate
}
},
{
label: 'Last 90 Days',
group: 'Days',
range: {
start: calendarEnd.subtract({ days: 89 }),
end: calendarEnd
start: referenceDate.subtract({ days: 89 }),
end: referenceDate
}
},
{
label: 'Last 365 Days',
group: 'Days',
range: {
start: calendarEnd.subtract({ days: 364 }),
end: calendarEnd
start: referenceDate.subtract({ days: 364 }),
end: referenceDate
}
},
{
label: 'Last 3 Months',
group: 'Months',
range: {
start: startOfMonth(calendarEnd.subtract({ months: 3 })),
end: endOfMonth(calendarEnd.subtract({ months: 1 }))
start: startOfMonth(referenceDate.subtract({ months: 3 })),
end: endOfMonth(referenceDate.subtract({ months: 1 }))
}
},
{
label: 'Last 6 Months',
group: 'Months',
range: {
start: startOfMonth(calendarEnd.subtract({ months: 6 })),
end: endOfMonth(calendarEnd.subtract({ months: 1 }))
start: startOfMonth(referenceDate.subtract({ months: 6 })),
end: endOfMonth(referenceDate.subtract({ months: 1 }))
}
},
{
label: 'Last 12 Months',
group: 'Months',
range: {
start: startOfMonth(calendarEnd.subtract({ months: 12 })),
end: endOfMonth(calendarEnd.subtract({ months: 1 }))
start: startOfMonth(referenceDate.subtract({ months: 12 })),
end: endOfMonth(referenceDate.subtract({ months: 1 }))
}
},
{
label: 'Last Month',
group: 'Last',
range: {
start: startOfMonth(calendarEnd.subtract({ months: 1 })),
end: endOfMonth(calendarEnd.subtract({ months: 1 }))
start: startOfMonth(referenceDate.subtract({ months: 1 })),
end: endOfMonth(referenceDate.subtract({ months: 1 }))
}
},
{
label: 'Last Year',
group: 'Last',
range: {
start: startOfYear(calendarEnd.subtract({ years: 1 })),
end: endOfYear(calendarEnd.subtract({ years: 1 }))
start: startOfYear(referenceDate.subtract({ years: 1 })),
end: endOfYear(referenceDate.subtract({ years: 1 }))
}
},
{
label: 'Month to Date',
group: 'To Date',
range: {
start: startOfMonth(calendarEnd),
end: endOfMonth(calendarEnd)
start: startOfMonth(referenceDate),
end: endOfMonth(referenceDate)
}
},
{
label: 'Month to Today',
group: 'To Date',
range: {
start: startOfMonth(calendarEnd),
end: calendarEnd
start: startOfMonth(referenceDate),
end: todayDate
}
},
{
label: 'Year to Date',
group: 'To Date',
range: {
start: startOfYear(calendarEnd),
end: endOfYear(calendarEnd)
start: startOfYear(referenceDate),
end: endOfYear(referenceDate)
}
},
{
label: 'Year to Today',
group: 'To Date',
range: {
start: startOfYear(calendarEnd),
end: calendarEnd
start: startOfYear(referenceDate),
end: todayDate
}
},
{
Expand Down Expand Up @@ -198,7 +263,51 @@

let selectedPreset;
let placeholder;
$: setPlaceholderDefault(calendarEnd);
// Set default placeholder: use calendarEnd if today is beyond the data range, otherwise use today
$: {
if (calendarEnd && todayDate.compare(calendarEnd) > 0) {
// If today is after the end of the data range, open to the end date
setPlaceholderDefault(calendarEnd);
} else if (calendarStart && todayDate.compare(calendarStart) < 0) {
// If today is before the start of the data range, open to the start date
setPlaceholderDefault(calendarStart);
} else {
// Otherwise, open to today
setPlaceholderDefault(todayDate);
}
}

$: if (typeof defaultValue === 'string' && !selectedPreset && presets.length) {
applyPreset(defaultValue);
}

// Initialize with default value or today's date (if defaultToToday is enabled)
$: if (!selectedDateInput && !selectedPreset) {
if (defaultValue && typeof defaultValue === 'string') {
try {
const defaultDate = YYYYMMDDToCalendar(defaultValue);
selectedDateInput = defaultDate;
} catch (error) {
if (defaultToToday) {
if (calendarEnd && todayDate.compare(calendarEnd) > 0) {
selectedDateInput = calendarEnd;
} else if (calendarStart && todayDate.compare(calendarStart) < 0) {
selectedDateInput = calendarStart;
} else {
selectedDateInput = todayDate;
}
}
}
} else if (defaultToToday) {
if (calendarEnd && todayDate.compare(calendarEnd) > 0) {
selectedDateInput = calendarEnd;
} else if (calendarStart && todayDate.compare(calendarStart) < 0) {
selectedDateInput = calendarStart;
} else {
selectedDateInput = todayDate;
}
}
}

// group exists check for nicely rendering group border for dropdown
function groupExists(groupName) {
Expand All @@ -219,23 +328,10 @@
selectedPreset = targetPreset;
if (range) {
selectedDateInput = targetPreset.range;
} else {
selectedDateInput = targetPreset.range.end;
}
}

$: if (
typeof defaultValue === 'string' &&
!selectedDateInput &&
!selectedPreset &&
presets.length
)
applyPreset(defaultValue);

$: calendarStart = YYYYMMDDToCalendar(start);
$: calendarEnd = YYYYMMDDToCalendar(end);

let extraDayCalendarEnd = calendarEnd;
$: if (range) {
extraDayCalendarEnd = YYYYMMDDToCalendar(extraDayEndString);
onSelectedDateInputChange(selectedDateInput);
}

function updateDateRange(start, end) {
Expand All @@ -244,7 +340,7 @@
if (range) {
selectedDateInput = { start, end };
} else {
selectedDateInput = start;
selectedDateInput = selectedDateInput;
}
}
$: updateDateRange(calendarStart, calendarEnd);
Expand Down Expand Up @@ -326,7 +422,9 @@
selectedDateInput = value;
}}
minValue={calendarStart}
maxValue={extraDayCalendarEnd}
maxValue={calendarEnd}
defaultValue={todayDate}
availableYears={extractedYears}
/>
{:else}
<Calendar
Expand All @@ -340,6 +438,8 @@
}}
minValue={calendarStart}
maxValue={calendarEnd}
defaultValue={todayDate}
availableYears={extractedYears}
/>
{/if}
</Popover.Content>
Expand Down
Loading
Loading