diff --git a/app/(app)/tasks/[id].tsx b/app/(app)/tasks/[id].tsx index f828a37..f3174e7 100644 --- a/app/(app)/tasks/[id].tsx +++ b/app/(app)/tasks/[id].tsx @@ -85,8 +85,11 @@ export default function TicketDetailScreen() { const updateStatus = useMutation({ mutationFn: async ({ status, activationTicket, subId }: { status: string; activationTicket: boolean; subId?: string }) => { - await api.patch(`/api/v1/tickets/${id}`, { status }); - // If this is an activation ticket being RESOLVED → activate subscription + // Return the patched ticket so onSuccess can set cache directly + const res = await api.patch(`/api/v1/tickets/${id}`, { status }); + const updatedTicket = res.data; + + // Activate subscription when resolving an activation ticket if ((status === 'RESOLVED' || status === 'CLOSED') && activationTicket && subId) { await api.patch(`/api/v1/subscriptions/${subId}`, { status: 'ACTIVE' }).catch(() => {}); } @@ -94,15 +97,19 @@ export default function TicketDetailScreen() { await api.post(`/api/v1/tickets/${id}/messages`, { body: `Status changed to ${status.replace('_', ' ')} by ${who}`, }).catch(() => {}); + + return updatedTicket; }, - onSuccess: async () => { + onSuccess: (updatedTicket) => { + // Directly inject fresh data into cache — avoids race condition with refetch + if (updatedTicket) { + qc.setQueryData(['task', id], (old: any) => ({ ...(old ?? {}), ...updatedTicket })); + } setShowStatusPicker(false); - await qc.invalidateQueries({ queryKey: ['task', id] }); - await qc.invalidateQueries({ queryKey: ['tasks'] }); - await qc.invalidateQueries({ queryKey: ['clients'] }); - await refetch(); - await refetchClient().catch(() => {}); - await refetchInvoices().catch(() => {}); + // Invalidate list queries in background (non-blocking) + qc.invalidateQueries({ queryKey: ['tasks'] }); + qc.invalidateQueries({ queryKey: ['clients'] }); + qc.invalidateQueries({ queryKey: ['task-client', updatedTicket?.clientId] }); }, onError: (e: any) => { const msg = e?.response?.data?.message ?? 'Could not update status.'; @@ -130,8 +137,11 @@ export default function TicketDetailScreen() { const confirmInstallation = async () => { setInstConfirming(true); try { - // 1. Resolve the ticket - await api.patch(`/api/v1/tickets/${id}`, { status: 'RESOLVED' }); + // 1. Resolve the ticket — use response to directly update cache + const patchRes = await api.patch(`/api/v1/tickets/${id}`, { status: 'RESOLVED' }); + if (patchRes.data) { + qc.setQueryData(['task', id], (old: any) => ({ ...(old ?? {}), ...patchRes.data })); + } // 2. Update client location with recorded coordinates (skip if GPS unavailable) if (ticket?.clientId && coords) { @@ -163,12 +173,9 @@ export default function TicketDetailScreen() { setInstNotes(''); setCoords(null); - // Invalidate + force refetch so the status shows RESOLVED immediately - await qc.invalidateQueries({ queryKey: ['tasks'] }); - await qc.invalidateQueries({ queryKey: ['task', id] }); - await refetch(); - await qc.invalidateQueries({ queryKey: ['client', ticket?.clientId] }); - await qc.invalidateQueries({ queryKey: ['client-tickets', ticket?.clientId] }); + // Invalidate list queries in background (cache already updated above) + qc.invalidateQueries({ queryKey: ['tasks'] }); + qc.invalidateQueries({ queryKey: ['clients'] }); Alert.alert( 'Installation Complete! ✓', 'Ticket resolved, location recorded, and activation ticket created.',