mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 20:12:39 +08:00
fix(date-picker): refresh relative dates after midnight
This commit is contained in:
@@ -43,7 +43,7 @@
|
||||
<input
|
||||
type="date"
|
||||
v-model="localStartDate"
|
||||
:max="localEndDate || tomorrow"
|
||||
:max="localEndDate || tomorrow()"
|
||||
class="date-picker-input"
|
||||
@change="onDateChange"
|
||||
/>
|
||||
@@ -57,7 +57,7 @@
|
||||
type="date"
|
||||
v-model="localEndDate"
|
||||
:min="localStartDate"
|
||||
:max="tomorrow"
|
||||
:max="tomorrow()"
|
||||
class="date-picker-input"
|
||||
@change="onDateChange"
|
||||
/>
|
||||
@@ -108,22 +108,15 @@ const localStartDate = ref(props.startDate)
|
||||
const localEndDate = ref(props.endDate)
|
||||
const activePreset = ref<string | null>('last24Hours')
|
||||
|
||||
const today = computed(() => {
|
||||
// Use local timezone to avoid UTC timezone issues
|
||||
const now = new Date()
|
||||
const year = now.getFullYear()
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(now.getDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
})
|
||||
const today = () => formatDateToString(new Date())
|
||||
|
||||
// Tomorrow's date - used for max date to handle timezone differences
|
||||
// When user is in a timezone behind the server, "today" on server might be "tomorrow" locally
|
||||
const tomorrow = computed(() => {
|
||||
const tomorrow = () => {
|
||||
const d = new Date()
|
||||
d.setDate(d.getDate() + 1)
|
||||
return formatDateToString(d)
|
||||
})
|
||||
}
|
||||
|
||||
// Helper function to format date to YYYY-MM-DD using local timezone
|
||||
const formatDateToString = (date: Date): string => {
|
||||
@@ -138,7 +131,7 @@ const presets: DatePreset[] = [
|
||||
labelKey: 'dates.today',
|
||||
value: 'today',
|
||||
getRange: () => {
|
||||
const t = today.value
|
||||
const t = today()
|
||||
return { start: t, end: t }
|
||||
}
|
||||
},
|
||||
@@ -168,7 +161,7 @@ const presets: DatePreset[] = [
|
||||
labelKey: 'dates.last7Days',
|
||||
value: '7days',
|
||||
getRange: () => {
|
||||
const end = today.value
|
||||
const end = today()
|
||||
const d = new Date()
|
||||
d.setDate(d.getDate() - 6)
|
||||
const start = formatDateToString(d)
|
||||
@@ -179,7 +172,7 @@ const presets: DatePreset[] = [
|
||||
labelKey: 'dates.last14Days',
|
||||
value: '14days',
|
||||
getRange: () => {
|
||||
const end = today.value
|
||||
const end = today()
|
||||
const d = new Date()
|
||||
d.setDate(d.getDate() - 13)
|
||||
const start = formatDateToString(d)
|
||||
@@ -190,7 +183,7 @@ const presets: DatePreset[] = [
|
||||
labelKey: 'dates.last30Days',
|
||||
value: '30days',
|
||||
getRange: () => {
|
||||
const end = today.value
|
||||
const end = today()
|
||||
const d = new Date()
|
||||
d.setDate(d.getDate() - 29)
|
||||
const start = formatDateToString(d)
|
||||
@@ -203,7 +196,7 @@ const presets: DatePreset[] = [
|
||||
getRange: () => {
|
||||
const now = new Date()
|
||||
const start = formatDateToString(new Date(now.getFullYear(), now.getMonth(), 1))
|
||||
return { start, end: today.value }
|
||||
return { start, end: today() }
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { enableAutoUnmount, mount } from '@vue/test-utils'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { ref } from 'vue'
|
||||
import DateRangePicker from '../DateRangePicker.vue'
|
||||
vi.mock('vue-i18n', () => ({ useI18n: () => ({ t: (key: string) => key, locale: ref('en') }) }))
|
||||
enableAutoUnmount(afterEach)
|
||||
beforeEach(() => { vi.useFakeTimers(); vi.setSystemTime(new Date(2026, 8, 30, 23, 59)) })
|
||||
afterEach(() => vi.useRealTimers())
|
||||
async function reopenNextDay() {
|
||||
const w = mount(DateRangePicker, { props: { startDate: '2026-09-30', endDate: '2026-09-30' }, global: { stubs: { Icon: true } } })
|
||||
await w.get('.date-picker-trigger').trigger('click')
|
||||
expect(w.findAll('input[type="date"]')[1].attributes('max')).toBe('2026-10-01')
|
||||
await w.get('.date-picker-trigger').trigger('click')
|
||||
vi.setSystemTime(new Date(2026, 9, 1, 0, 1))
|
||||
await w.get('.date-picker-trigger').trigger('click')
|
||||
return w
|
||||
}
|
||||
describe('date presets after midnight', () => {
|
||||
it.each([
|
||||
['dates.today', '2026-10-01'],
|
||||
['dates.last7Days', '2026-09-25'],
|
||||
['dates.thisMonth', '2026-10-01'],
|
||||
])('refreshes %s when the page stays mounted overnight', async (label, startDate) => {
|
||||
const w = await reopenNextDay()
|
||||
await w.findAll('.date-picker-preset').find(b => b.text() === label)!.trigger('click')
|
||||
await w.get('.date-picker-apply').trigger('click')
|
||||
expect(w.emitted('change')?.[0]?.[0]).toMatchObject({ startDate, endDate: '2026-10-01' })
|
||||
})
|
||||
it('updates the maximum selectable date when reopened', async () => {
|
||||
const w = await reopenNextDay()
|
||||
expect(w.findAll('input[type="date"]')[1].attributes('max')).toBe('2026-10-02')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user