diff --git a/src/app/WardrobePage/ItemsPanel.js b/src/app/WardrobePage/ItemsPanel.js
index 430d587..d2ce512 100644
--- a/src/app/WardrobePage/ItemsPanel.js
+++ b/src/app/WardrobePage/ItemsPanel.js
@@ -17,8 +17,19 @@ import {
Portal,
Button,
useToast,
+ Popover,
+ PopoverTrigger,
+ PopoverContent,
+ PopoverArrow,
+ PopoverBody,
} from "@chakra-ui/react";
-import { EditIcon, QuestionIcon } from "@chakra-ui/icons";
+import {
+ CheckIcon,
+ EditIcon,
+ ExternalLinkIcon,
+ QuestionIcon,
+ WarningIcon,
+} from "@chakra-ui/icons";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import { useHistory } from "react-router-dom";
@@ -30,6 +41,7 @@ import { MdMoreVert } from "react-icons/md";
import useCurrentUser from "../components/useCurrentUser";
import gql from "graphql-tag";
import { useMutation } from "@apollo/client";
+import { outfitStatesAreEqual } from "./useOutfitState";
/**
* ItemsPanel shows the items in the current outfit, and lets the user toggle
@@ -255,16 +267,19 @@ function useOutfitSaving(outfitState) {
const history = useHistory();
const toast = useToast();
- // Whether this outfit has *ever* been saved, vs a brand-new local outfit.
- const hasBeenSaved = Boolean(outfitState.id);
+ // Whether this outfit is new, i.e. local-only, i.e. has _never_ been saved
+ // to the server.
+ const isNewOutfit = outfitState.id == null;
+
+ // Whether this outfit's latest local changes have been saved to the server.
+ const latestVersionIsSaved =
+ outfitState.savedOutfitState &&
+ outfitStatesAreEqual(outfitState, outfitState.savedOutfitState);
// Only logged-in users can save outfits - and they can only save new outfits,
// or outfits they created.
const canSaveOutfit =
- isLoggedIn &&
- (!hasBeenSaved || outfitState.creator?.id === currentUserId) &&
- // TODO: Add support for updating outfits
- !hasBeenSaved;
+ isLoggedIn && (isNewOutfit || outfitState.creator?.id === currentUserId);
const [sendSaveOutfitMutation, { loading: isSaving }] = useMutation(
gql`
@@ -365,18 +380,104 @@ function useOutfitSaving(outfitState) {
return {
canSaveOutfit,
+ isNewOutfit,
isSaving,
+ latestVersionIsSaved,
saveOutfit,
};
}
+/**
+ * OutfitSavingIndicator shows a Save button, or the "Saved" or "Saving" state,
+ * if the user can save this outfit. If not, this is empty!
+ */
+function OutfitSavingIndicator({ outfitState }) {
+ const {
+ canSaveOutfit,
+ isNewOutfit,
+ isSaving,
+ latestVersionIsSaved,
+ saveOutfit,
+ } = useOutfitSaving(outfitState);
+
+ if (!canSaveOutfit) {
+ return null;
+ }
+
+ if (isNewOutfit) {
+ return (
+
+ );
+ }
+
+ if (latestVersionIsSaved) {
+ return (
+