use real query for item support pet compatibility rule

mutation isn't hooked up yet though! it exists but the sever doesn't recognize it
This commit is contained in:
Emi Matchu 2020-08-14 21:38:45 -07:00
parent 02c959a837
commit a2f5dcd498

View file

@ -76,9 +76,8 @@ function ItemSupportDrawer({ item, isOpen, onClose }) {
<DrawerBody> <DrawerBody>
<Box paddingBottom="5"> <Box paddingBottom="5">
<Stack spacing="8"> <Stack spacing="8">
<ItemSupportSpecialColorFields item={item} /> <ItemSupportFields item={item} />
<ItemSupportPetCompatibilityRuleFields item={item} /> <ItemSupportAppearanceLayers item={item} />
<ItemSupportAppearanceFields item={item} />
</Stack> </Stack>
</Box> </Box>
</DrawerBody> </DrawerBody>
@ -88,17 +87,16 @@ function ItemSupportDrawer({ item, isOpen, onClose }) {
); );
} }
function ItemSupportSpecialColorFields({ item }) { function ItemSupportFields({ item }) {
const supportSecret = useSupportSecret(); const { loading, error, data } = useQuery(
const { loading: itemLoading, error: itemError, data: itemData } = useQuery(
gql` gql`
query ItemSupportDrawerManualSpecialColor($itemId: ID!) { query ItemSupportFields($itemId: ID!) {
item(id: $itemId) { item(id: $itemId) {
id id
manualSpecialColor { manualSpecialColor {
id id
} }
explicitlyBodySpecific
} }
} }
`, `,
@ -112,10 +110,39 @@ function ItemSupportSpecialColorFields({ item }) {
// This cheap trick of changing the display name every re-render // This cheap trick of changing the display name every re-render
// persuades Apollo that this is a different query, so it re-checks // persuades Apollo that this is a different query, so it re-checks
// its cache and finds the empty `manualSpecialColor`. Weird! // its cache and finds the empty `manualSpecialColor`. Weird!
displayName: `ItemSupportDrawerManualSpecialColor-${new Date()}`, displayName: `ItemSupportFields-${new Date()}`,
} }
); );
const errorColor = useColorModeValue("red.500", "red.300");
return (
<>
{error && <Box color={errorColor}>{error.message}</Box>}
<ItemSupportSpecialColorFields
loading={loading}
error={error}
item={item}
manualSpecialColor={data?.item?.manualSpecialColor?.id}
/>
<ItemSupportPetCompatibilityRuleFields
loading={loading}
error={error}
item={item}
explicitlyBodySpecific={data?.item?.explicitlyBodySpecific}
/>
</>
);
}
function ItemSupportSpecialColorFields({
loading,
error,
item,
manualSpecialColor,
}) {
const supportSecret = useSupportSecret();
const { const {
loading: colorsLoading, loading: colorsLoading,
error: colorsError, error: colorsError,
@ -154,33 +181,8 @@ function ItemSupportSpecialColorFields({ item }) {
} }
`); `);
const nonStandardColors = const onChange = React.useCallback(
colorsData?.allColors?.filter((c) => !c.isStandard) || []; (e) => {
nonStandardColors.sort((a, b) => a.name.localeCompare(b.name));
const linkColor = useColorModeValue("green.500", "green.300");
return (
<FormControl
isInvalid={colorsError || itemError || mutationError ? true : false}
>
<FormLabel>Special color</FormLabel>
<Select
placeholder={
colorsLoading || itemLoading
? "Loading…"
: "Default: Auto-detect from item description"
}
value={itemData?.item?.manualSpecialColor?.id}
isDisabled={mutationLoading}
icon={
colorsLoading || itemLoading || mutationLoading ? (
<Spinner />
) : mutationData ? (
<CheckCircleIcon />
) : undefined
}
onChange={(e) => {
const colorId = e.target.value || null; const colorId = e.target.value || null;
const color = const color =
colorId != null ? { __typename: "Color", id: colorId } : null; colorId != null ? { __typename: "Color", id: colorId } : null;
@ -198,8 +200,38 @@ function ItemSupportSpecialColorFields({ item }) {
manualSpecialColor: color, manualSpecialColor: color,
}, },
}, },
}).catch((e) => {
// Ignore errors from the promise, because we'll handle them on render!
}); });
}} },
[item.id, mutate, supportSecret]
);
const nonStandardColors =
colorsData?.allColors?.filter((c) => !c.isStandard) || [];
nonStandardColors.sort((a, b) => a.name.localeCompare(b.name));
const linkColor = useColorModeValue("green.500", "green.300");
return (
<FormControl isInvalid={Boolean(error || colorsError || mutationError)}>
<FormLabel>Special color</FormLabel>
<Select
placeholder={
loading || colorsLoading
? "Loading…"
: "Default: Auto-detect from item description"
}
value={manualSpecialColor?.id}
isDisabled={mutationLoading}
icon={
loading || colorsLoading || mutationLoading ? (
<Spinner />
) : mutationData ? (
<CheckCircleIcon />
) : undefined
}
onChange={onChange}
> >
{nonStandardColors.map((color) => ( {nonStandardColors.map((color) => (
<option key={color.id} value={color.id}> <option key={color.id} value={color.id}>
@ -210,11 +242,10 @@ function ItemSupportSpecialColorFields({ item }) {
{colorsError && ( {colorsError && (
<FormErrorMessage>{colorsError.message}</FormErrorMessage> <FormErrorMessage>{colorsError.message}</FormErrorMessage>
)} )}
{itemError && <FormErrorMessage>{itemError.message}</FormErrorMessage>}
{mutationError && ( {mutationError && (
<FormErrorMessage>{mutationError.message}</FormErrorMessage> <FormErrorMessage>{mutationError.message}</FormErrorMessage>
)} )}
{!colorsError && !itemError && !mutationError && ( {!colorsError && !mutationError && (
<FormHelperText> <FormHelperText>
This controls which previews we show on the{" "} This controls which previews we show on the{" "}
<Link <Link
@ -233,18 +264,95 @@ function ItemSupportSpecialColorFields({ item }) {
); );
} }
function ItemSupportPetCompatibilityRuleFields({ item }) { function ItemSupportPetCompatibilityRuleFields({
loading,
error,
item,
explicitlyBodySpecific,
}) {
const supportSecret = useSupportSecret();
const [
mutate,
{ loading: mutationLoading, error: mutationError, data: mutationData },
] = useMutation(gql`
mutation ItemSupportDrawerSetItemExplicitlyBodySpecific(
$itemId: ID!
$explicitlyBodySpecific: Boolean!
$supportSecret: String!
) {
setItemExplicitlyBodySpecific(
itemId: $itemId
explicitlyBodySpecific: $explicitlyBodySpecific
supportSecret: $supportSecret
) {
id
explicitlyBodySpecific
}
}
`);
const onChange = React.useCallback(
(e) => {
const explicitlyBodySpecific = e.target.value === "true";
mutate({
variables: {
itemId: item.id,
explicitlyBodySpecific,
supportSecret,
},
optimisticResponse: {
__typename: "Mutation",
setItemExplicitlyBodySpecific: {
__typename: "Item",
id: item.id,
explicitlyBodySpecific,
},
},
}).catch((e) => {
// Ignore errors from the promise, because we'll handle them on render!
});
},
[item.id, mutate, supportSecret]
);
return ( return (
<FormControl> <FormControl isInvalid={Boolean(error || mutationError)}>
<FormLabel>Pet compatibility rule</FormLabel> <FormLabel>Pet compatibility rule</FormLabel>
<Select> <Select
<option>Default: Auto-detect whether this fits all pets</option> value={explicitlyBodySpecific ? "true" : "false"}
<option>Body specific: Always different for each pet body</option> isDisabled={mutationLoading}
icon={
loading || mutationLoading ? (
<Spinner />
) : mutationData ? (
<CheckCircleIcon />
) : undefined
}
onChange={onChange}
>
{loading ? (
<option>Loading</option>
) : (
<>
<option value="false">
Default: Auto-detect whether this fits all pets
</option>
<option value="true">
Body specific: Always different for each pet body
</option>
</>
)}
</Select> </Select>
{mutationError && (
<FormErrorMessage>{mutationError.message}</FormErrorMessage>
)}
{!mutationError && (
<FormHelperText> <FormHelperText>
By default, we assume Background-y zones fit all pets the same. When By default, we assume Background-y zones fit all pets the same. When
items don't follow that rule, we can override it. items don't follow that rule, we can override it.
</FormHelperText> </FormHelperText>
)}
</FormControl> </FormControl>
); );
} }
@ -256,7 +364,7 @@ function ItemSupportPetCompatibilityRuleFields({ item }) {
* sure the context isn't accessed when the drawer is closed. So we use * sure the context isn't accessed when the drawer is closed. So we use
* it here, only when the drawer is open! * it here, only when the drawer is open!
*/ */
function ItemSupportAppearanceFields({ item }) { function ItemSupportAppearanceLayers({ item }) {
const outfitState = React.useContext(OutfitStateContext); const outfitState = React.useContext(OutfitStateContext);
const { speciesId, colorId, pose } = outfitState; const { speciesId, colorId, pose } = outfitState;
const { error, visibleLayers } = useOutfitAppearance({ const { error, visibleLayers } = useOutfitAppearance({