feat(03-06): implement SyncStateToast with polled sync-status feedback (D-05/D-06/D-08/D-09)
- SyncStateToast: pending/done/failed/dead states per UI-SPEC - refetchInterval 3000ms while pending; disabled on terminal status - done + conflict (412) invalidate ['events'] cache (D-06/D-08) - done auto-dismisses after 2s; failed/dead persist with dismiss button - role=status (pending/done) and role=alert (failed/dead) for a11y - Mounted in CalendarShell (both phone + tablet/desktop layouts) - EventForm.onSuccess: setLastSyncedUid(uid) instead of invalidateQueries
This commit is contained in:
@@ -28,11 +28,13 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
|
||||
const {
|
||||
mockSetEventForm,
|
||||
mockSetLastSyncedUid,
|
||||
mockCreateEvent,
|
||||
mockUpdateEvent,
|
||||
mockFetchWritableCalendars,
|
||||
} = vi.hoisted(() => ({
|
||||
mockSetEventForm: vi.fn(),
|
||||
mockSetLastSyncedUid: vi.fn(),
|
||||
mockCreateEvent: vi.fn().mockResolvedValue({ uid: 'new-uid-123' }),
|
||||
mockUpdateEvent: vi.fn().mockResolvedValue({ uid: 'edit-uid-456' }),
|
||||
mockFetchWritableCalendars: vi.fn(),
|
||||
@@ -43,12 +45,18 @@ let mockEventFormMode: 'create' | 'edit' = 'create'
|
||||
let mockEventFormUid: string | null = null
|
||||
|
||||
vi.mock('../store/calendarStore.js', () => ({
|
||||
useCalendarStore: vi.fn(() => ({
|
||||
eventFormOpen: mockEventFormOpen,
|
||||
eventFormMode: mockEventFormMode,
|
||||
eventFormUid: mockEventFormUid,
|
||||
setEventForm: mockSetEventForm,
|
||||
})),
|
||||
useCalendarStore: vi.fn((selector?: (s: Record<string, unknown>) => unknown) => {
|
||||
const state = {
|
||||
eventFormOpen: mockEventFormOpen,
|
||||
eventFormMode: mockEventFormMode,
|
||||
eventFormUid: mockEventFormUid,
|
||||
setEventForm: mockSetEventForm,
|
||||
setLastSyncedUid: mockSetLastSyncedUid,
|
||||
}
|
||||
// Support both selector form and plain call form
|
||||
if (typeof selector === 'function') return selector(state)
|
||||
return state
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('../api/client.js', () => ({
|
||||
@@ -106,12 +114,19 @@ function renderForm(options: {
|
||||
mockEventFormOpen = true
|
||||
mockEventFormMode = mode
|
||||
mockEventFormUid = uid
|
||||
;(useCalendarStore as unknown as ReturnType<typeof vi.fn>).mockImplementation(() => ({
|
||||
eventFormOpen: true,
|
||||
eventFormMode: mode,
|
||||
eventFormUid: uid,
|
||||
setEventForm: mockSetEventForm,
|
||||
}))
|
||||
;(useCalendarStore as unknown as ReturnType<typeof vi.fn>).mockImplementation(
|
||||
(selector?: (s: Record<string, unknown>) => unknown) => {
|
||||
const state = {
|
||||
eventFormOpen: true,
|
||||
eventFormMode: mode,
|
||||
eventFormUid: uid,
|
||||
setEventForm: mockSetEventForm,
|
||||
setLastSyncedUid: mockSetLastSyncedUid,
|
||||
}
|
||||
if (typeof selector === 'function') return selector(state)
|
||||
return state
|
||||
},
|
||||
)
|
||||
|
||||
mockFetchWritableCalendars.mockResolvedValue(calendars)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user