import * as React from "react";
import gql from "graphql-tag";
import { useMutation } from "@apollo/client";
import {
Button,
Box,
FormControl,
FormErrorMessage,
FormHelperText,
FormLabel,
HStack,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Radio,
RadioGroup,
Spinner,
useToast,
} from "@chakra-ui/core";
import { ChevronRightIcon, ExternalLinkIcon } from "@chakra-ui/icons";
import ItemLayerSupportUploadModal from "./ItemLayerSupportUploadModal";
import Metadata, { MetadataLabel, MetadataValue } from "./Metadata";
import { OutfitLayers } from "../../components/OutfitPreview";
import SpeciesColorPicker from "../../components/SpeciesColorPicker";
import useOutfitAppearance, {
itemAppearanceFragment,
} from "../../components/useOutfitAppearance";
import useSupportSecret from "./useSupportSecret";
/**
* ItemLayerSupportModal offers Support info and tools for a specific item
* appearance layer. Open it by clicking a layer from ItemSupportDrawer.
*/
function ItemLayerSupportModal({
item,
itemLayer,
outfitState,
isOpen,
onClose,
}) {
const [selectedBodyId, setSelectedBodyId] = React.useState(itemLayer.bodyId);
const [previewBiology, setPreviewBiology] = React.useState({
speciesId: outfitState.speciesId,
colorId: outfitState.colorId,
pose: outfitState.pose,
isValid: true,
});
const [uploadModalIsOpen, setUploadModalIsOpen] = React.useState(false);
const supportSecret = useSupportSecret();
const toast = useToast();
const [
mutate,
{ loading: mutationLoading, error: mutationError },
] = useMutation(
gql`
mutation ItemSupportSetLayerBodyId(
$layerId: ID!
$bodyId: ID!
$supportSecret: String!
$outfitSpeciesId: ID!
$outfitColorId: ID!
$formPreviewSpeciesId: ID!
$formPreviewColorId: ID!
) {
setLayerBodyId(
layerId: $layerId
bodyId: $bodyId
supportSecret: $supportSecret
) {
# This mutation returns the affected AppearanceLayer. Fetch the
# updated fields, including the appearance on the outfit pet and the
# form preview pet, to automatically update our cached appearance in
# the rest of the app. That means you should be able to see your
# changes immediately!
id
bodyId
item {
id
appearanceOnOutfit: appearanceOn(
speciesId: $outfitSpeciesId
colorId: $outfitColorId
) {
...ItemAppearanceForOutfitPreview
}
appearanceOnFormPreviewPet: appearanceOn(
speciesId: $formPreviewSpeciesId
colorId: $formPreviewColorId
) {
...ItemAppearanceForOutfitPreview
}
}
}
}
${itemAppearanceFragment}
`,
{
variables: {
layerId: itemLayer.id,
bodyId: selectedBodyId,
supportSecret,
outfitSpeciesId: outfitState.speciesId,
outfitColorId: outfitState.colorId,
formPreviewSpeciesId: previewBiology.speciesId,
formPreviewColorId: previewBiology.colorId,
},
onCompleted: () => {
onClose();
toast({
status: "success",
title: `Saved layer ${itemLayer.id}: ${item.name}`,
});
},
}
);
return (
Layer {itemLayer.id}: {item.name}
Item ID:
{itemLayer.id}
Neopets ID:
{itemLayer.remoteId}
Zone:
{itemLayer.zone.label} ({itemLayer.zone.id})
Assets:
{itemLayer.svgUrl ? (
) : (
)}
{itemLayer.imageUrl ? (
) : (
)}
setUploadModalIsOpen(false)}
/>
{mutationError && (
{mutationError.message}
)}
);
}
function ItemLayerSupportPetCompatibilityFields({
item,
itemLayer,
outfitState,
selectedBodyId,
previewBiology,
onChangeBodyId,
onChangePreviewBiology,
}) {
const [selectedBiology, setSelectedBiology] = React.useState(previewBiology);
const {
loading,
error,
visibleLayers,
bodyId: appearanceBodyId,
} = useOutfitAppearance({
speciesId: previewBiology.speciesId,
colorId: previewBiology.colorId,
pose: previewBiology.pose,
wornItemIds: [item.id],
});
const biologyLayers = visibleLayers.filter((l) => l.source === "pet");
// After we touch a species/color selector and null out `bodyId`, when the
// appearance body ID loads in, select it as the new body ID.
//
// This might move the radio button away from "all pets", but I think that's
// a _less_ surprising experience: if you're touching the pickers, then
// that's probably where you head is.
React.useEffect(() => {
if (selectedBodyId == null && appearanceBodyId != null) {
onChangeBodyId(appearanceBodyId);
}
}, [selectedBodyId, appearanceBodyId, onChangeBodyId]);
return (
Pet compatibility
onChangeBodyId(newBodyId)}
marginBottom="4"
>
Fits all pets{" "}
(Body ID: 0)
Fits all pets with the same body as:{" "}
(Body ID:{" "}
{appearanceBodyId == null ? (
) : (
appearanceBodyId
)}
)
{
const speciesId = species.id;
const colorId = color.id;
setSelectedBiology({ speciesId, colorId, isValid, pose });
if (isValid) {
onChangePreviewBiology({ speciesId, colorId, isValid, pose });
// Also temporarily null out the body ID. We'll switch to the new
// body ID once it's loaded.
onChangeBodyId(null);
}
}}
/>
{!error && (
If it doesn't look right, try some other options until it does!
)}
{error && {error.message}}
);
}
export default ItemLayerSupportModal;