feat(players): add optimistic update for listWithSkillData

When creating a new player, optimistically update both the player list
and the listWithSkillData query (used by /practice page). This makes
new players appear immediately without requiring a page reload.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock 2026-01-14 17:35:22 -06:00
parent 71e9345d2a
commit 72c4825333
1 changed files with 42 additions and 16 deletions

View File

@ -141,38 +141,64 @@ export function useCreatePlayer() {
return useMutation({
mutationFn: createPlayer,
onMutate: async (newPlayer) => {
// Cancel outgoing refetches
await queryClient.cancelQueries({ queryKey: playerKeys.lists() })
// Cancel outgoing refetches for all player queries
await queryClient.cancelQueries({ queryKey: playerKeys.all })
// Snapshot previous value
// Snapshot previous values
const previousPlayers = queryClient.getQueryData<Player[]>(playerKeys.list())
const previousPlayersWithSkillData = queryClient.getQueryData<StudentWithSkillData[]>(
playerKeys.listWithSkillData()
)
// Optimistically update to new value
// Create optimistic player
const optimisticPlayer: Player = {
id: `temp-${Date.now()}`, // Temporary ID
...newPlayer,
createdAt: new Date(),
isActive: newPlayer.isActive ?? false,
isArchived: false,
userId: 'temp-user', // Temporary userId, will be replaced by server response
helpSettings: null, // Will be set by server with default values
notes: null,
familyCode: null, // Will be generated by server
}
// Optimistically update player list
if (previousPlayers) {
const optimisticPlayer: Player = {
id: `temp-${Date.now()}`, // Temporary ID
...newPlayer,
createdAt: new Date(),
isActive: newPlayer.isActive ?? false,
isArchived: false,
userId: 'temp-user', // Temporary userId, will be replaced by server response
helpSettings: null, // Will be set by server with default values
notes: null,
familyCode: null, // Will be generated by server
}
queryClient.setQueryData<Player[]>(playerKeys.list(), [
...previousPlayers,
optimisticPlayer,
])
}
return { previousPlayers }
// Optimistically update players with skill data (used by practice page)
if (previousPlayersWithSkillData) {
const optimisticPlayerWithSkillData: StudentWithSkillData = {
...optimisticPlayer,
practicingSkills: [],
lastPracticedAt: null,
skillCategory: null,
intervention: null,
}
queryClient.setQueryData<StudentWithSkillData[]>(playerKeys.listWithSkillData(), [
...previousPlayersWithSkillData,
optimisticPlayerWithSkillData,
])
}
return { previousPlayers, previousPlayersWithSkillData }
},
onError: (_err, _newPlayer, context) => {
// Rollback on error
if (context?.previousPlayers) {
queryClient.setQueryData(playerKeys.list(), context.previousPlayers)
}
if (context?.previousPlayersWithSkillData) {
queryClient.setQueryData(
playerKeys.listWithSkillData(),
context.previousPlayersWithSkillData
)
}
},
onSettled: () => {
// Always refetch after error or success