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;