From 676e7fd97d2b07cf545538f39810d36afffaa733 Mon Sep 17 00:00:00 2001 From: Jhih-Lin Jhou <103354@smsassist.com> Date: Wed, 4 Feb 2026 16:28:36 -0600 Subject: [PATCH 1/5] refine time range filter --- src/lib/common/shared/TimeRangePicker.svelte | 272 +++++++++++++++--- .../custom/components/_time-range-picker.scss | 27 ++ 2 files changed, 263 insertions(+), 36 deletions(-) create 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 e05d8b89..3205c2d6 100644 --- a/src/lib/common/shared/TimeRangePicker.svelte +++ b/src/lib/common/shared/TimeRangePicker.svelte @@ -1,11 +1,18 @@ -
+
{ + if (e.detail && e.detail.targetNode && datePickerRef) { + if (!datePickerRef.contains(e.detail.targetNode)) { + showDatePicker = false; + } + } + }}> {#if showDatePicker} -
{ - if (e.detail && e.detail.targetNode && datePickerRef) { - if (!datePickerRef.contains(e.detail.targetNode)) { - showDatePicker = false; - } - } - }} - class="position-absolute top-100 start-0 mt-1 bg-white border rounded shadow-lg" - style="z-index: 1050; min-width: 320px; max-width: 350px;" - > +
    -
    - {#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} +
      +
        +
      • +
      • + {#each presetTimeRangeOptions as option} +
      • +
        + +
        +
        + +
        +
      • {/each} -
      - {: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} +
    + {#each recentTimeRanges as range, index} +
  • +
    + +
    +
    + +
    +
  • + {/each} +
{/if} - {:else if datePickerTab === TAB_CUSTOM} +
+ {:else if datePickerTab === TAB_CUSTOM} +
- +
- +
- +
- {/if} -
+
+ {/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 */