diff --git a/app/javascript/wardrobe-2020/WardrobePage/ItemsPanel.js b/app/javascript/wardrobe-2020/WardrobePage/ItemsPanel.js
index e2b3c385..6da13cf3 100644
--- a/app/javascript/wardrobe-2020/WardrobePage/ItemsPanel.js
+++ b/app/javascript/wardrobe-2020/WardrobePage/ItemsPanel.js
@@ -36,19 +36,13 @@ import {
} from "@chakra-ui/icons";
import { CSSTransition, TransitionGroup } from "react-transition-group";
-import {
- Delay,
- ErrorMessage,
- getGraphQLErrorMessage,
- Heading1,
- Heading2,
-} from "../util";
+import { Delay, ErrorMessage, Heading1, Heading2 } from "../util";
import Item, { ItemListContainer, ItemListSkeleton } from "./Item";
import { BiRename } from "react-icons/bi";
import { IoCloudUploadOutline } from "react-icons/io5";
import { MdMoreVert } from "react-icons/md";
import { buildOutfitUrl } from "./useOutfitState";
-import { gql, useMutation } from "@apollo/client";
+import { useDeleteOutfitMutation } from "../loaders/outfits";
/**
* ItemsPanel shows the items in the current outfit, and lets the user toggle
@@ -455,25 +449,7 @@ function DeleteOutfitMenuItem({ outfitState }) {
const { id, name } = outfitState;
const { isOpen, onOpen, onClose } = useDisclosure();
- const [sendDeleteOutfitMutation, { loading, error }] = useMutation(
- gql`
- mutation DeleteOutfitMenuItem($id: ID!) {
- deleteOutfit(id: $id)
- }
- `,
- {
- context: { sendAuth: true },
- update(cache) {
- // Once this is deleted, evict it from the local cache, and "garbage
- // collect" to force all queries referencing this outfit to reload the
- // next time we see them. (This is especially important since we're
- // about to redirect to the user outfits page, which shouldn't show
- // the outfit anymore!)
- cache.evict(`Outfit:${id}`);
- cache.gc();
- },
- },
- );
+ const { status, error, mutateAsync } = useDeleteOutfitMutation();
return (
<>
@@ -489,10 +465,9 @@ function DeleteOutfitMenuItem({ outfitState }) {
We'll delete this data and remove it from your list of outfits.
Links and image embeds pointing to this outfit will break. Is that
okay?
- {error && (
+ {status === "error" && (
- Error deleting outfit: "{getGraphQLErrorMessage(error)}". Try
- again?
+ Error deleting outfit: "{error.message}". Try again?
)}
@@ -502,7 +477,7 @@ function DeleteOutfitMenuItem({ outfitState }) {
diff --git a/app/javascript/wardrobe-2020/WardrobePage/useOutfitSaving.js b/app/javascript/wardrobe-2020/WardrobePage/useOutfitSaving.js
index 9ceb5551..f0ae2c71 100644
--- a/app/javascript/wardrobe-2020/WardrobePage/useOutfitSaving.js
+++ b/app/javascript/wardrobe-2020/WardrobePage/useOutfitSaving.js
@@ -3,8 +3,6 @@ import { useToast } from "@chakra-ui/react";
import { useLocation, useNavigate } from "react-router-dom";
import { useDebounce } from "../util";
import useCurrentUser from "../components/useCurrentUser";
-import gql from "graphql-tag";
-import { useMutation } from "@apollo/client";
import { outfitStatesAreEqual } from "./useOutfitState";
import { useSaveOutfitMutation } from "../loaders/outfits";
diff --git a/app/javascript/wardrobe-2020/loaders/outfits.js b/app/javascript/wardrobe-2020/loaders/outfits.js
index 09a111c9..ac73ab6c 100644
--- a/app/javascript/wardrobe-2020/loaders/outfits.js
+++ b/app/javascript/wardrobe-2020/loaders/outfits.js
@@ -8,7 +8,7 @@ export function useSavedOutfit(id, options) {
});
}
-export function useSaveOutfitMutation(options) {
+export function useSaveOutfitMutation(options = {}) {
const queryClient = useQueryClient();
return useMutation({
@@ -16,7 +16,24 @@ export function useSaveOutfitMutation(options) {
mutationFn: saveOutfit,
onSuccess: (outfit) => {
queryClient.setQueryData(["outfits", outfit.id], outfit);
- options.onSuccess(outfit);
+ if (options.onSuccess) {
+ options.onSuccess(outfit);
+ }
+ },
+ });
+}
+
+export function useDeleteOutfitMutation(options = {}) {
+ const queryClient = useQueryClient();
+
+ return useMutation({
+ ...options,
+ mutationFn: deleteOutfit,
+ onSuccess: (emptyData, id, context) => {
+ queryClient.invalidateQueries({ queryKey: ["outfits", String(id)] });
+ if (options.onSuccess) {
+ options.onSuccess(emptyData, id, context);
+ }
},
});
}
@@ -80,6 +97,19 @@ async function saveOutfit({
return res.json().then(normalizeOutfit);
}
+async function deleteOutfit(id) {
+ const res = await fetch(`/outfits/${encodeURIComponent(id)}.json`, {
+ method: "DELETE",
+ headers: {
+ "X-CSRF-Token": getCSRFToken(),
+ },
+ });
+
+ if (!res.ok) {
+ throw new Error(`deleting outfit failed: ${res.status} ${res.statusText}`);
+ }
+}
+
function normalizeOutfit(outfit) {
return {
id: String(outfit.id),