Refactor chore management to use React Query hooks for timer and chore actions

- Replaced direct API calls with React Query hooks in ChoreView, ChoreCard, CompactChoreCard, and TimerDetails components for better state management and error handling.
- Updated ArchivedTasks to utilize useUnArchiveChore hook for restoring archived chores.
- Enhanced NotificationSetting to include device registration logic and improved user feedback for push notifications.
- Refactored TimerEditModal and TimerDetails to streamline timer session updates and deletions using hooks.
- Improved ChoreActionMenu to handle archiving and unarchiving chores with hooks.
- Adjusted various components to use getSafeBottomStyles for consistent bottom padding.
- Cleaned up unused imports and optimized loading states across components.
This commit is contained in:
Mo Tarbin
2025-09-21 12:46:03 -04:00
parent 79dfb11fa4
commit f27bbd318f
26 changed files with 877 additions and 447 deletions

View File

@@ -3,12 +3,21 @@ import { useState } from 'react'
import { networkManager } from '../hooks/NetworkManager'
import { FEATURES, isFeatureEnabled } from '../utils/FeatureToggle'
import {
ApproveChore,
ArchiveChore,
CreateChore,
DeleteChoreHistory,
GetChoreByID,
GetChoreDetailById,
GetChoreHistory,
GetChoresHistory,
GetChoresNew,
MarkChoreComplete,
RejectChore,
SaveChore,
SkipChore,
UnArchiveChore,
UpdateChoreHistory,
} from '../utils/Fetcher'
import { localStore } from '../utils/LocalStore'
@@ -154,6 +163,8 @@ export const useUpdateChore = () => {
onSuccess: (data, variables) => {
// Invalidate the chores query to refresh the data
queryClient.invalidateQueries(['chores'])
// Invalidate history for the specific chore
queryClient.invalidateQueries(['choreHistory', variables.id])
},
onMutate: async updatedChore => {
if (!networkManager.isOnline && isFeatureEnabled(FEATURES.OFFLINE_MODE)) {
@@ -255,3 +266,123 @@ export const useChore = choreId => {
},
})
}
export const useArchiveChore = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: ArchiveChore,
onSuccess: () => {
queryClient.invalidateQueries(['chores'])
},
})
}
export const useUnArchiveChore = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: UnArchiveChore,
onSuccess: () => {
queryClient.invalidateQueries(['chores'])
},
})
}
export const useChoreHistory = choreId => {
return useQuery({
queryKey: ['choreHistory', choreId],
queryFn: async () => {
if (!choreId) {
throw new Error('Chore ID is required to fetch history')
}
const response = await GetChoreHistory(choreId)
if (response && response.ok) {
return await response.json()
}
throw new Error('Failed to fetch chore history')
},
enabled: !!choreId,
staleTime: 0, // Always consider data stale
cacheTime: 0, // Don't cache the data
refetchOnMount: true, // Always refetch when component mounts
refetchOnWindowFocus: true, // Refetch when window gains focus
})
}
export const useUpdateChoreHistory = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: ({ choreId, historyId, historyData }) =>
UpdateChoreHistory(choreId, historyId, historyData),
onSuccess: (data, { choreId }) => {
queryClient.invalidateQueries(['choreHistory', choreId])
},
})
}
export const useDeleteChoreHistory = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: ({ choreId, historyId }) =>
DeleteChoreHistory(choreId, historyId),
onSuccess: (data, { choreId }) => {
queryClient.invalidateQueries(['choreHistory', choreId])
},
})
}
export const useMarkChoreComplete = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: ({ choreId, body, completedDate, performer }) =>
MarkChoreComplete(choreId, body, completedDate, performer),
onSuccess: (data, { choreId }) => {
queryClient.invalidateQueries(['chores'])
queryClient.invalidateQueries(['choreHistory', choreId])
queryClient.invalidateQueries(['choreDetails', choreId])
},
})
}
export const useSkipChore = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: SkipChore,
onSuccess: (data, choreId) => {
queryClient.invalidateQueries(['chores'])
queryClient.invalidateQueries(['choreHistory', choreId])
queryClient.invalidateQueries(['choreDetails', choreId])
},
})
}
export const useApproveChore = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: ApproveChore,
onSuccess: (data, choreId) => {
queryClient.invalidateQueries(['chores'])
queryClient.invalidateQueries(['choreHistory', choreId])
queryClient.invalidateQueries(['choreDetails', choreId])
},
})
}
export const useRejectChore = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: RejectChore,
onSuccess: (data, choreId) => {
queryClient.invalidateQueries(['chores'])
queryClient.invalidateQueries(['choreHistory', choreId])
queryClient.invalidateQueries(['choreDetails', choreId])
},
})
}

View File

@@ -3,7 +3,7 @@ import { GetResource } from '../utils/Fetcher'
export const useResource = () => {
const { data, isLoading, error } = useQuery({
queryKey: [],
queryKey: ['resource'],
queryFn: async () => {
const response = await GetResource()
return response

107
src/queries/TimeQueries.jsx Normal file
View File

@@ -0,0 +1,107 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import {
ClearChoreTimer,
DeleteTimeSession,
GetChoreTimer,
PauseChore,
ResetChoreTimer,
StartChore,
UpdateTimeSession,
} from '../utils/Fetcher'
export const useChoreTimer = choreId => {
return useQuery({
queryKey: ['choreTimer', choreId],
queryFn: async () => {
if (!choreId) {
throw new Error('Chore ID is required to fetch timer')
}
const response = await GetChoreTimer(choreId)
if (response && response.ok) {
return await response.json()
}
throw new Error('Failed to fetch chore timer')
},
enabled: !!choreId,
})
}
export const useStartChore = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: StartChore,
onSuccess: (data, choreId) => {
queryClient.invalidateQueries(['choreTimer', choreId])
queryClient.invalidateQueries(['chores'])
queryClient.invalidateQueries(['choreHistory', choreId])
},
})
}
export const usePauseChore = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: PauseChore,
onSuccess: (data, choreId) => {
queryClient.invalidateQueries(['choreTimer', choreId])
queryClient.invalidateQueries(['chores'])
queryClient.invalidateQueries(['choreHistory', choreId])
},
})
}
export const useUpdateTimeSession = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: ({ choreId, sessionId, sessionData }) =>
UpdateTimeSession(choreId, sessionId, sessionData),
onSuccess: (data, { choreId }) => {
queryClient.invalidateQueries(['choreTimer', choreId])
queryClient.invalidateQueries(['chores'])
queryClient.invalidateQueries(['choreHistory', choreId])
},
})
}
export const useDeleteTimeSession = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: ({ choreId, sessionId }) =>
DeleteTimeSession(choreId, sessionId),
onSuccess: (data, { choreId }) => {
queryClient.invalidateQueries(['choreTimer', choreId])
queryClient.invalidateQueries(['chores'])
queryClient.invalidateQueries(['choreHistory', choreId])
},
})
}
export const useResetChoreTimer = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: ResetChoreTimer,
onSuccess: (data, choreId) => {
queryClient.invalidateQueries(['choreTimer', choreId])
queryClient.invalidateQueries(['chores'])
queryClient.invalidateQueries(['choreHistory', choreId])
},
})
}
export const useClearChoreTimer = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: ClearChoreTimer,
onSuccess: (data, choreId) => {
queryClient.invalidateQueries(['choreTimer', choreId])
queryClient.invalidateQueries(['chores'])
queryClient.invalidateQueries(['choreHistory', choreId])
},
})
}

View File

@@ -67,7 +67,7 @@ export const useDeviceTokens = () => {
const result = await resp.json()
return result.res || []
},
staleTime: 5 * 60 * 1000, // 5 minutes
staleTime: 0, // Always fetch fresh data
gcTime: 10 * 60 * 1000, // 10 minutes
})