|
|
@@ -0,0 +1,91 @@
|
|
|
+// noinspection JSIgnoredPromiseFromCall
|
|
|
+
|
|
|
+export const useCreateCharacter = defineMutation(() => {
|
|
|
+ const queryCache = useQueryCache()
|
|
|
+
|
|
|
+ const { mutate, ...mutation } = useMutation({
|
|
|
+ onMutate(character) {
|
|
|
+ // save the current character list and options
|
|
|
+ const oldCharacterList = queryCache.getQueryData(characterListQuery.key)
|
|
|
+ const oldOptions = queryCache.getQueryData(characterOptionsQuery.key)
|
|
|
+
|
|
|
+ // create the new character
|
|
|
+ const newCharacter = {
|
|
|
+ ...character,
|
|
|
+ id: Number.MAX_SAFE_INTEGER
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log("[useCreateCharacter] [onMutate]", newCharacter)
|
|
|
+
|
|
|
+ // create a copy of the current character list with the new character
|
|
|
+ const newCharacterList = [...oldCharacterList || [], newCharacter]
|
|
|
+
|
|
|
+ // calculate new character options
|
|
|
+ const newOptions = getCharacterOptions(newCharacterList)
|
|
|
+
|
|
|
+ // update the caches with the new character list, options, and character
|
|
|
+ queryCache.setQueryData(characterListQuery.key, newCharacterList)
|
|
|
+ queryCache.setQueryData(characterOptionsQuery.key, newOptions)
|
|
|
+
|
|
|
+ // cancel (without refreshing) queries depending on the character list
|
|
|
+ queryCache.cancelQueries({ key: characterListQuery.key })
|
|
|
+
|
|
|
+ // pass the old and new character list, options, and the new character to the other hooks
|
|
|
+ return { oldCharacterList, newCharacterList, oldOptions, newCharacter }
|
|
|
+ },
|
|
|
+
|
|
|
+ mutation: (character) => {
|
|
|
+ console.log("[useCreateCharacter] [mutation]", character)
|
|
|
+
|
|
|
+ return useEmit("character:create", character)
|
|
|
+ },
|
|
|
+
|
|
|
+ // on both error and success
|
|
|
+ onSettled(_data, _errors, _vars, { newCharacter }) {
|
|
|
+ console.log("[useCreateCharacter] [onSettled]")
|
|
|
+
|
|
|
+ // invalidate queries to refetch the new data
|
|
|
+ queryCache.invalidateQueries({ key: characterListQuery.key })
|
|
|
+
|
|
|
+ // newCharacter can be undefined if the onMutate hook fails
|
|
|
+ if (newCharacter) {
|
|
|
+ queryCache.cancelQueries({ key: characterByIdQuery(newCharacter.id).key })
|
|
|
+ queryCache.remove({ key: characterByIdQuery(newCharacter.id).key })
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ onError(error, _vars, { oldCharacterList, newCharacterList, oldOptions }) {
|
|
|
+ // before applying the rollback, check if the value in the cache is the same
|
|
|
+ // in case the cache was updated by another mutation or query
|
|
|
+ if (newCharacterList === queryCache.getQueryData(characterListQuery.key)) {
|
|
|
+ console.log("[useCreateCharacter] [onError] [rollback]")
|
|
|
+
|
|
|
+ queryCache.setQueryData(characterListQuery.key, oldCharacterList)
|
|
|
+ queryCache.setQueryData(characterOptionsQuery.key, oldOptions)
|
|
|
+ }
|
|
|
+
|
|
|
+ // handle the error
|
|
|
+ console.error("[useCreateCharacter] [onError]", error)
|
|
|
+ },
|
|
|
+
|
|
|
+ onSuccess(character, _vars, { newCharacter }) {
|
|
|
+ console.log("[useCreateCharacter] [onSuccess]", character)
|
|
|
+
|
|
|
+ // update character list with the newly created character returned by the api
|
|
|
+ const characterList = queryCache.getQueryData(characterListQuery.key) || []
|
|
|
+
|
|
|
+ // replace the character created in onMutate() with the one from the server
|
|
|
+ const characterIndex = _findIndex(characterList, { id: newCharacter.id })
|
|
|
+
|
|
|
+ if (characterIndex >= 0) {
|
|
|
+ const characterListCopy = characterList.toSpliced(characterIndex, 1, character)
|
|
|
+ queryCache.setQueryData(characterListQuery.key, characterListCopy)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...mutation,
|
|
|
+ createCharacter: (character) => mutate(character)
|
|
|
+ }
|
|
|
+})
|