- {#if datePickerTab === 'relative'}
-
+
+ {#if datePickerTab === TAB_RELATIVE}
+
+
{#each presetTimeRangeOptions as option}
{/each}
- {:else if datePickerTab === 'custom'}
+ {:else if datePickerTab === TAB_RECENT}
+ {#if recentTimeRanges.length === 0}
+
+
+
{'No recent time ranges'}
+
+ {:else}
+ {#each recentTimeRanges as range, index}
+
+
+
{
+ handleRecentOptionClick(range);
+ }}
+ >
+
+ {range.label}
+
+
+
+ {/each}
+ {/if}
+ {:else if datePickerTab === TAB_CUSTOM}
{/if}
-
+
{/if}
@@ -331,4 +500,35 @@
:global(.flatpickr-input) {
display: none !important;
}
+
+ .clear-btn {
+ background-color: transparent;
+ border: none;
+ padding: 0.5rem 0.75rem;
+ transition: background-color 0.15s ease-in-out;
+ }
+
+ .clear-btn:hover {
+ background-color: aliceblue;
+ }
+
+ /* Hover and active styles for relative dropdown items */
+ .relative-option {
+ background-color: transparent;
+ border: none;
+ transition: background-color 0.15s ease-in-out;
+ }
+
+ .relative-option:hover {
+ background-color: aliceblue;
+ }
+
+ .relative-option.active {
+ background-color: transparent;
+ color: inherit;
+ }
+
+ .relative-option.active:hover {
+ background-color: aliceblue;
+ }
diff --git a/src/lib/scss/custom/components/_time-range-picker.scss b/src/lib/scss/custom/components/_time-range-picker.scss
new file mode 100644
index 00000000..70cc9973
--- /dev/null
+++ b/src/lib/scss/custom/components/_time-range-picker.scss
@@ -0,0 +1,27 @@
+.multiselect-container {
+ .nav-tabs {
+ position: sticky;
+ top: 0;
+ z-index: 10;
+ background-color: white;
+ border-bottom: 1px solid var(--bs-border-color-translucent);
+ margin-bottom: 0;
+
+ .nav-item {
+ .nav-link {
+ border: none;
+ background: transparent;
+ cursor: pointer;
+ transition: all 0.2s ease-in-out;
+
+ &:hover {
+ background-color: transparent;
+ }
+
+ &.active {
+ background-color: transparent;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
From 0b1fc4ff9e2de0bfaa81425fe74a82f1eafea7df Mon Sep 17 00:00:00 2001
From: Jhih-Lin Jhou <103354@smsassist.com>
Date: Thu, 5 Feb 2026 10:14:59 -0600
Subject: [PATCH 2/5] fix type
---
src/lib/helpers/types/conversationTypes.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/lib/helpers/types/conversationTypes.js b/src/lib/helpers/types/conversationTypes.js
index 54879042..6dd900f1 100644
--- a/src/lib/helpers/types/conversationTypes.js
+++ b/src/lib/helpers/types/conversationTypes.js
@@ -323,7 +323,7 @@ IRichContent.prototype.language;
* @property {string?} [status]
* @property {UserStateDetailModel[]} states
* @property {string[]} tags
- * @property {string?} [timeRange]
+ * @property {string} [timeRange]
* @property {string} [startDate] - When timeRange is "Custom date", start date in YYYY-MM-DD format (e.g. 2026-01-25)
* @property {string} [endDate] - When timeRange is "Custom date", end date in YYYY-MM-DD format (e.g. 2026-01-30). Defaults to startDate if not provided
*/
From ad02f16a3a9d1b4326773baf3adab3cbcf367a57 Mon Sep 17 00:00:00 2001
From: Jhih-Lin Jhou <103354@smsassist.com>
Date: Thu, 5 Feb 2026 13:57:36 -0600
Subject: [PATCH 3/5] refine relative and recent tab
---
src/lib/common/shared/TimeRangePicker.svelte | 263 +++++++++---------
.../custom/components/_time-range-picker.scss | 27 --
2 files changed, 139 insertions(+), 151 deletions(-)
delete mode 100644 src/lib/scss/custom/components/_time-range-picker.scss
diff --git a/src/lib/common/shared/TimeRangePicker.svelte b/src/lib/common/shared/TimeRangePicker.svelte
index 3205c2d6..baa480c3 100644
--- a/src/lib/common/shared/TimeRangePicker.svelte
+++ b/src/lib/common/shared/TimeRangePicker.svelte
@@ -37,7 +37,7 @@
// Temporary dates for custom selection (before confirming)
/** @type {string} */
let tempStartDate = '';
-
+
/** @type {string} */
let tempEndDate = '';
@@ -65,7 +65,11 @@
dateFormat: 'Y-m-d',
inline: true,
allowInput: false,
- onChange: (/** @type {Date[]} */ selectedDates, /** @type {string} */ dateStr, /** @type {any} */ instance) => {
+ onChange: (
+ /** @type {Date[]} */ selectedDates,
+ /** @type {string} */ dateStr,
+ /** @type {any} */ instance
+ ) => {
if (selectedDates.length === 1) {
// Only start date selected
tempStartDate = formatDateForFlatpickr(selectedDates[0]);
@@ -130,26 +134,38 @@
}
// Preset time range options
- const presetTimeRangeOptions = TIME_RANGE_OPTIONS.map(x => ({
+ const presetTimeRangeOptions = TIME_RANGE_OPTIONS.map((x) => ({
label: x.label,
value: x.value
}));
onMount(() => {
loadRecentTimeRanges();
- });;
+ });
// Get today's date in YYYY-MM-DD format
const getTodayStr = () => {
const d = new Date();
- return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
+ return (
+ d.getFullYear() +
+ '-' +
+ String(d.getMonth() + 1).padStart(2, '0') +
+ '-' +
+ String(d.getDate()).padStart(2, '0')
+ );
};
// Get yesterday's date in YYYY-MM-DD format
const getYesterdayStr = () => {
const d = new Date();
d.setDate(d.getDate() - 1);
- return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
+ return (
+ d.getFullYear() +
+ '-' +
+ String(d.getMonth() + 1).padStart(2, '0') +
+ '-' +
+ String(d.getDate()).padStart(2, '0')
+ );
};
// Format date for display (YYYY-MM-DD -> MM/DD/YYYY)
@@ -172,12 +188,12 @@
} else if (timeRange === CUSTOM_DATE_RANGE) {
timeRangeDisplayText = 'Custom';
} else {
- const selected = presetTimeRangeOptions.find(x => x.value === timeRange);
+ const selected = presetTimeRangeOptions.find((x) => x.value === timeRange);
timeRangeDisplayText = selected ? selected.label : '';
}
}
- const dispatch = createEventDispatcher()
+ const dispatch = createEventDispatcher();
function loadRecentTimeRanges() {
try {
@@ -222,11 +238,10 @@
// Remove duplicate if exists (check by timeRange if it's a relative range, otherwise by dates)
if (range.timeRange) {
- recentTimeRanges = recentTimeRanges.filter(r => r.timeRange !== range.timeRange);
+ recentTimeRanges = recentTimeRanges.filter((r) => r.timeRange !== range.timeRange);
} else {
- recentTimeRanges = recentTimeRanges.filter(r =>
- r.startDate !== range.startDate ||
- r.endDate !== range.endDate
+ recentTimeRanges = recentTimeRanges.filter(
+ (r) => r.startDate !== range.startDate || r.endDate !== range.endDate
);
}
@@ -234,8 +249,7 @@
recentTimeRanges = [newRange, ...recentTimeRanges].slice(0, MAX_RECENT_ITEMS);
localStorage.setItem(RECENT_TIME_RANGES_KEY, JSON.stringify(recentTimeRanges));
- } catch (e) {
- }
+ } catch (e) {}
}
/** @param {number} index */
@@ -243,8 +257,7 @@
recentTimeRanges = recentTimeRanges.filter((_, idx) => idx !== index);
try {
localStorage.setItem(RECENT_TIME_RANGES_KEY, JSON.stringify(recentTimeRanges));
- } catch (e) {
- }
+ } catch (e) {}
}
/** @param {string} optionValue */
@@ -255,7 +268,7 @@
} else {
timeRange = optionValue;
- const option = TIME_RANGE_OPTIONS.find(x => x.value === optionValue);
+ const option = TIME_RANGE_OPTIONS.find((x) => x.value === optionValue);
if (option) {
saveRecentTimeRange({
@@ -282,10 +295,10 @@
timeRange = CUSTOM_DATE_RANGE;
saveRecentTimeRange({ startDate, endDate });
// Dispatch change event with updated values
- dispatch('change', {
- timeRange: CUSTOM_DATE_RANGE,
- startDate: tempStartDate,
- endDate: finalEndDate
+ dispatch('change', {
+ timeRange: CUSTOM_DATE_RANGE,
+ startDate: tempStartDate,
+ endDate: finalEndDate
});
}
showDatePicker = false;
@@ -296,16 +309,18 @@
}
-
{
- if (e.detail && e.detail.targetNode && datePickerRef) {
- if (!datePickerRef.contains(e.detail.targetNode)) {
- showDatePicker = false;
- }
- }
- }}>
+
{
+ if (e.detail && e.detail.targetNode && datePickerRef) {
+ if (!datePickerRef.contains(e.detail.targetNode)) {
+ showDatePicker = false;
+ }
+ }
+ }}
+>
{#if showDatePicker}
-
+
-
-
-
-
-
- {#if datePickerTab === TAB_RELATIVE}
-
-
- {#each presetTimeRangeOptions as option}
+
+ {#if datePickerTab === TAB_RELATIVE}
+
- {:else if datePickerTab === TAB_RECENT}
+
+
+ {:else if datePickerTab === TAB_RECENT}
+
{#if recentTimeRanges.length === 0}
{'No recent time ranges'}
{:else}
- {#each recentTimeRanges as range, index}
-
-
-
{
- handleRecentOptionClick(range);
- }}
- >
-
- {range.label}
-
-
-
- {/each}
+
{/if}
- {:else if datePickerTab === TAB_CUSTOM}
+
+ {:else if datePickerTab === TAB_CUSTOM}
+
+
+ {/if}
{/if}
@@ -504,31 +540,10 @@
.clear-btn {
background-color: transparent;
border: none;
- padding: 0.5rem 0.75rem;
transition: background-color 0.15s ease-in-out;
}
.clear-btn:hover {
background-color: aliceblue;
}
-
- /* Hover and active styles for relative dropdown items */
- .relative-option {
- background-color: transparent;
- border: none;
- transition: background-color 0.15s ease-in-out;
- }
-
- .relative-option:hover {
- background-color: aliceblue;
- }
-
- .relative-option.active {
- background-color: transparent;
- color: inherit;
- }
-
- .relative-option.active:hover {
- background-color: aliceblue;
- }
diff --git a/src/lib/scss/custom/components/_time-range-picker.scss b/src/lib/scss/custom/components/_time-range-picker.scss
deleted file mode 100644
index 70cc9973..00000000
--- a/src/lib/scss/custom/components/_time-range-picker.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-.multiselect-container {
- .nav-tabs {
- position: sticky;
- top: 0;
- z-index: 10;
- background-color: white;
- border-bottom: 1px solid var(--bs-border-color-translucent);
- margin-bottom: 0;
-
- .nav-item {
- .nav-link {
- border: none;
- background: transparent;
- cursor: pointer;
- transition: all 0.2s ease-in-out;
-
- &:hover {
- background-color: transparent;
- }
-
- &.active {
- background-color: transparent;
- }
- }
- }
- }
-}
\ No newline at end of file
From e2fb205b84ded70201d9d47c3b3ec6cb378ce83a Mon Sep 17 00:00:00 2001
From: Jhih-Lin Jhou <103354@smsassist.com>
Date: Mon, 9 Feb 2026 16:10:21 -0600
Subject: [PATCH 4/5] separage storage key for conversion and instruction
---
src/lib/common/shared/TimeRangePicker.svelte | 10 ++++++----
src/routes/page/conversation/+page.svelte | 1 +
src/routes/page/instruction/log/+page.svelte | 1 +
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/lib/common/shared/TimeRangePicker.svelte b/src/lib/common/shared/TimeRangePicker.svelte
index baa480c3..23c05f5b 100644
--- a/src/lib/common/shared/TimeRangePicker.svelte
+++ b/src/lib/common/shared/TimeRangePicker.svelte
@@ -7,7 +7,6 @@
import { clickoutsideDirective } from '$lib/helpers/directives';
// Constants
- const RECENT_TIME_RANGES_KEY = 'botsharp_recent_time_ranges';
const MAX_RECENT_ITEMS = 10;
const TAB_RELATIVE = 'relative';
const TAB_RECENT = 'recent';
@@ -48,6 +47,9 @@
/** @type {Array<{ startDate: string, endDate: string, label: string, timeRange?: string }>} */
let recentTimeRanges = [];
+ /** @type {string} */
+ export let storageKey = 'botsharp_recent_time_ranges';
+
// Format date for flatpickr (Date object to YYYY-MM-DD string)
/** @param {Date} date */
function formatDateForFlatpickr(/** @type {Date} */ date) {
@@ -197,7 +199,7 @@
function loadRecentTimeRanges() {
try {
- const stored = localStorage.getItem(RECENT_TIME_RANGES_KEY);
+ const stored = localStorage.getItem(storageKey);
if (stored) {
recentTimeRanges = JSON.parse(stored);
}
@@ -248,7 +250,7 @@
// Add to beginning and limit to MAX_RECENT_ITEMS
recentTimeRanges = [newRange, ...recentTimeRanges].slice(0, MAX_RECENT_ITEMS);
- localStorage.setItem(RECENT_TIME_RANGES_KEY, JSON.stringify(recentTimeRanges));
+ localStorage.setItem(storageKey, JSON.stringify(recentTimeRanges));
} catch (e) {}
}
@@ -256,7 +258,7 @@
function removeRecentTimeRange(index) {
recentTimeRanges = recentTimeRanges.filter((_, idx) => idx !== index);
try {
- localStorage.setItem(RECENT_TIME_RANGES_KEY, JSON.stringify(recentTimeRanges));
+ localStorage.setItem(storageKey, JSON.stringify(recentTimeRanges));
} catch (e) {}
}
diff --git a/src/routes/page/conversation/+page.svelte b/src/routes/page/conversation/+page.svelte
index ad7013a9..80f08d0d 100644
--- a/src/routes/page/conversation/+page.svelte
+++ b/src/routes/page/conversation/+page.svelte
@@ -505,6 +505,7 @@
Date: Tue, 10 Feb 2026 17:39:00 -0600
Subject: [PATCH 5/5] adding catch log
---
src/lib/common/shared/TimeRangePicker.svelte | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/lib/common/shared/TimeRangePicker.svelte b/src/lib/common/shared/TimeRangePicker.svelte
index 23c05f5b..2e5b0bed 100644
--- a/src/lib/common/shared/TimeRangePicker.svelte
+++ b/src/lib/common/shared/TimeRangePicker.svelte
@@ -204,6 +204,7 @@
recentTimeRanges = JSON.parse(stored);
}
} catch (e) {
+ console.warn(`[TimeRangePicker] Failed to load recent time ranges from localStorage (key: ${storageKey}):`, e);
recentTimeRanges = [];
}
}
@@ -251,7 +252,9 @@
recentTimeRanges = [newRange, ...recentTimeRanges].slice(0, MAX_RECENT_ITEMS);
localStorage.setItem(storageKey, JSON.stringify(recentTimeRanges));
- } catch (e) {}
+ } catch (e) {
+ console.warn(`[TimeRangePicker] Failed to save recent time range to localStorage (key: ${storageKey}):`, e);
+ }
}
/** @param {number} index */
@@ -259,7 +262,9 @@
recentTimeRanges = recentTimeRanges.filter((_, idx) => idx !== index);
try {
localStorage.setItem(storageKey, JSON.stringify(recentTimeRanges));
- } catch (e) {}
+ } catch (e) {
+ console.warn(`[TimeRangePicker] Failed to remove recent time range from localStorage (key: ${storageKey}):`, e);
+ }
}
/** @param {string} optionValue */