mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-31 04:12:13 +03:00
fix(ui): commit date-picker selections immediately instead of on confirm (#6122)
* fix(ui): commit date-picker selections immediately instead of on confirm With showTime, Ant Design's DatePicker stages a clicked date until the OK button confirms it. Closing the dropdown any other way - clicking elsewhere in the form or hitting Create/Save directly - discarded the staged date without a hint, so an inbound saved this way ended up with expiryTime=0 (never expires). The Now shortcut commits in one click, which made it look like only the current time could ever be set. Drop the confirm step (needConfirm=false) and propagate every calendar selection through onCalendarChange, so the picked date reaches the form state the moment it is clicked and can no longer be lost to a race with the submit button. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(ui): pin calendar clicks committing without a confirm press A clicked day cell must reach onChange with the exact selected timestamp while the dropdown is still open, and the footer must not render a confirm button. Pins the needConfirm-free behavior so a picker dependency bump cannot silently bring the staged-value discard back. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -121,7 +121,9 @@ export default function DateTimePicker({
|
||||
<DatePicker
|
||||
value={value}
|
||||
onChange={(next) => onChange(next || null)}
|
||||
onCalendarChange={(next) => onChange((Array.isArray(next) ? next[0] : next) || null)}
|
||||
showTime={showTime ? { format: 'HH:mm:ss' } : false}
|
||||
needConfirm={false}
|
||||
format={format}
|
||||
placeholder={placeholder}
|
||||
disabled={disabled}
|
||||
|
||||
43
frontend/src/test/date-time-picker.test.tsx
Normal file
43
frontend/src/test/date-time-picker.test.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import dayjs from 'dayjs';
|
||||
import type { Dayjs } from 'dayjs';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import DateTimePicker from '@/components/form/DateTimePicker';
|
||||
import { renderWithProviders } from './test-utils';
|
||||
|
||||
function openPicker(): void {
|
||||
const input = document.querySelector('.ant-picker input');
|
||||
if (!input) throw new Error('picker input not rendered');
|
||||
fireEvent.mouseDown(input);
|
||||
fireEvent.click(input);
|
||||
}
|
||||
|
||||
function clickDayCell(title: string): void {
|
||||
const cell = document.querySelector(`.ant-picker-cell[title="${title}"] .ant-picker-cell-inner`);
|
||||
if (!cell) throw new Error(`day cell ${title} not rendered`);
|
||||
fireEvent.click(cell);
|
||||
}
|
||||
|
||||
describe('DateTimePicker', () => {
|
||||
it('commits a clicked calendar date without an OK press', () => {
|
||||
const onChange = vi.fn<(next: Dayjs | null) => void>();
|
||||
renderWithProviders(<DateTimePicker value={null} onChange={onChange} />);
|
||||
|
||||
openPicker();
|
||||
const tomorrow = dayjs().add(1, 'day').format('YYYY-MM-DD');
|
||||
clickDayCell(tomorrow);
|
||||
|
||||
expect(onChange).toHaveBeenCalled();
|
||||
const committed = onChange.mock.calls.at(-1)?.[0];
|
||||
expect(committed?.format('YYYY-MM-DD HH:mm:ss')).toBe(`${tomorrow} 00:00:00`);
|
||||
});
|
||||
|
||||
it('renders no OK confirm button in the picker footer', () => {
|
||||
renderWithProviders(<DateTimePicker value={null} onChange={vi.fn()} />);
|
||||
|
||||
openPicker();
|
||||
|
||||
expect(document.querySelector('.ant-picker-ok')).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user