Add SmartTaskInput with Custom Renderer.

Change to use `@tanstack/react-query`
Add Global ErrorProvider
Add limited Support for offline version
Fix issue with calendar display +1 day
This commit is contained in:
Mo Tarbin
2025-04-24 19:14:17 -04:00
38 changed files with 2109 additions and 996 deletions

View File

@@ -67,19 +67,22 @@ export const useCreateChore = () => {
{ ...newTask, id: tempId, tempId }, // Use the tempId for offline tracking
]
await localStore.saveToCache('offlineTasks', updateOfflineTasks) // Save to local storage
// force useChores to refetch:
queryClient.invalidateQueries(['chores'])
// Force the chores query to refetch
queryClient.refetchQueries(['chores'])
// Update the chores query cache immediately
queryClient.setQueryData(['chores'], oldData => {
console.log('ATTEMPT TO SAVE OFFLINE TASKS:', updateOfflineTasks)
// queryClient.setQueryData(['chores'], oldData => {
// console.log('ATTEMPT TO SAVE OFFLINE TASKS:', updateOfflineTasks)
if (!oldData)
return {
res: [{ ...newTask, id: tempId, tempId }],
} // If no data, return offline tasks
return {
res: [...oldData.res, { ...newTask, id: tempId, tempId }],
}
})
// if (!oldData)
// return {
// res: [{ ...newTask, id: tempId, tempId }],
// } // If no data, return offline tasks
// return {
// res: [...oldData.res, { ...newTask, id: tempId, tempId }],
// }
// })
return { tempId }
}
return { tempId: null }
@@ -135,11 +138,11 @@ export const useUpdateChore = () => {
throw new Error('Failed to save chore')
}
const updatedChoreRes = await resp.json()
if (!updatedChoreRes || !updatedChoreRes.res) {
if (!updatedChoreRes) {
throw new Error('Failed to get updated chore data')
}
// Successfully updated the chore on the server, return the updated chore
return updatedChoreRes.res
return updatedChoreRes?.res || updatedChoreRes
}
},
onSuccess: (data, variables) => {
@@ -158,9 +161,13 @@ export const useUpdateChore = () => {
export const useChoresHistory = (initialLimit, includeMembers) => {
const [limit, setLimit] = useState(initialLimit) // Initially, no limit is selected
const { data, error, isLoading } = useQuery(['choresHistory', limit], () =>
GetChoresHistory(limit, includeMembers),
)
const { data, error, isLoading } = useQuery({
queryKey: ['choresHistory', limit],
queryFn: async () => {
const resp = await GetChoresHistory(limit, includeMembers)
return resp?.res || []
},
})
const handleLimitChange = newLimit => {
setLimit(newLimit)

View File

@@ -4,8 +4,12 @@ import { GetResource } from '../utils/Fetcher'
export const useResource = () => {
const { data, isLoading, error } = useQuery({
queryKey: ['resource'],
queryFn: GetResource,
cacheTime: 1000 * 60 * 10, // 10 minutes
queryFn: async () => {
const response = await GetResource()
return response.json()
},
refetchOnWindowFocus: false,
refetchOnReconnect: false,
})
return { data, isLoading, error }
}

View File

@@ -0,0 +1,94 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { networkManager } from '../hooks/NetworkManager'
import { CompleteSubTask, SaveChore } from '../utils/Fetcher'
import { localStore } from '../utils/LocalStore'
export const useUpdate = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async updatedChore => {
if (!networkManager.isOnline) {
updatedChore['updatedAt'] = new Date().toISOString()
if (!updatedChore['nextDueDate']) {
updatedChore['nextDueDate'] = updatedChore['dueDate']
}
const offlineTasks =
(await localStore.getFromCache('offlineTasks')) || []
for (const task of offlineTasks) {
// Find the task with the same id or tempId and update it
if (task.id === updatedChore.id || task.tempId === updatedChore.id) {
// Update the task in local storage
const updatedTask = { ...task, ...updatedChore }
const updatedOfflineTasks = offlineTasks.map(t =>
t.id === task.id ? updatedTask : t,
)
await localStore.saveToCache('offlineTasks', updatedOfflineTasks)
return new Promise((resolve, reject) => {
resolve(updatedTask)
})
}
}
const newTaskId = crypto.randomUUID()
const updatedChoreWithNewId = {
...updatedChore,
tempId: newTaskId,
}
await localStore.saveToCache('offlineTasks', [
...offlineTasks,
updatedChoreWithNewId,
])
return new Promise((resolve, reject) => {
// Resolve with the updated task
resolve(updatedChoreWithNewId)
})
} else {
// Call the API to update the chore
const resp = await SaveChore(updatedChore)
if (!resp || !resp.ok) {
throw new Error('Failed to save chore')
}
const updatedChoreRes = await resp.json()
if (!updatedChoreRes) {
throw new Error('Failed to get updated chore data')
}
// Successfully updated the chore on the server, return the updated chore
return updatedChoreRes?.res || updatedChoreRes
}
},
onSuccess: (data, variables) => {
// Invalidate the chores query to refresh the data
queryClient.invalidateQueries(['chores'])
},
onMutate: async updatedChore => {
if (!networkManager.isOnline) {
// Handle offline case here if needed
return
}
},
})
}
export const useCompleteSubTask = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async (subTaskId, choreId, completedAt) => {
if (!networkManager.isOnline) {
throw new Error('Cannot complete subtask while offline')
}
const resp = await CompleteSubTask(subTaskId, choreId, completedAt)
if (!resp || !resp.ok) {
throw new Error('Failed to complete subtask')
}
const result = await resp.json()
if (!result || !result.res) {
throw new Error('Failed to get completed subtask data')
}
return result.res
},
onSuccess: (data, variables) => {},
})
}

View File

@@ -11,7 +11,7 @@ export const useAllUsers = () => {
export const useCircleMembers = () => {
const queryClient = useQueryClient()
const { data, error, isLoading, refetch } = useQuery({
const { data, error, isLoading } = useQuery({
queryKey: ['allCircleMembers'],
queryFn: GetAllCircleMembers,
})