species/color picker!
This commit is contained in:
parent
d13420256c
commit
564cdef0ce
8 changed files with 388 additions and 207 deletions
|
@ -15,6 +15,7 @@ import {
|
|||
} from "@chakra-ui/core";
|
||||
|
||||
import { Delay } from "./util";
|
||||
import SpeciesColorPicker from "./SpeciesColorPicker";
|
||||
|
||||
import "./OutfitPreview.css";
|
||||
|
||||
|
@ -35,8 +36,9 @@ export const itemAppearanceFragment = gql`
|
|||
}
|
||||
`;
|
||||
|
||||
function OutfitPreview({ outfitState }) {
|
||||
function OutfitPreview({ outfitState, dispatchToOutfit }) {
|
||||
const { wornItemIds, speciesId, colorId } = outfitState;
|
||||
const [hasFocus, setHasFocus] = React.useState(false);
|
||||
|
||||
const { loading, error, data } = useQuery(
|
||||
gql`
|
||||
|
@ -122,45 +124,72 @@ function OutfitPreview({ outfitState }) {
|
|||
</Delay>
|
||||
)}
|
||||
<Box
|
||||
// Bottom-right in small screens, top-right on large screens
|
||||
// Bottom toolbar on small screens, top on large screens
|
||||
pos="absolute"
|
||||
right="2"
|
||||
left="0"
|
||||
right="0"
|
||||
bottom={{ base: "2", lg: "auto" }}
|
||||
top={{ base: "auto", lg: "2" }}
|
||||
// Grid layout for the content!
|
||||
display="grid"
|
||||
gridTemplateAreas={`"space picker download"`}
|
||||
gridTemplateColumns="minmax(0, 1fr) auto 1fr"
|
||||
alignItems="center"
|
||||
>
|
||||
<Tooltip label="Download" placement="left">
|
||||
<IconButton
|
||||
icon="download"
|
||||
aria-label="Download"
|
||||
isRound
|
||||
as="a"
|
||||
// eslint-disable-next-line no-script-url
|
||||
href={downloadImageUrl || "javascript:void 0"}
|
||||
download={(outfitState.name || "Outfit") + ".png"}
|
||||
onMouseEnter={prepareDownload}
|
||||
onFocus={prepareDownload}
|
||||
cursor={!downloadImageUrl && "wait"}
|
||||
variant="unstyled"
|
||||
backgroundColor="gray.600"
|
||||
color="gray.50"
|
||||
d="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
opacity="0"
|
||||
transition="all 0.2s"
|
||||
_groupHover={{
|
||||
opacity: 1,
|
||||
}}
|
||||
_focus={{
|
||||
opacity: 1,
|
||||
backgroundColor: "gray.500",
|
||||
}}
|
||||
_hover={{
|
||||
backgroundColor: "gray.500",
|
||||
}}
|
||||
outline="initial"
|
||||
<Box gridArea="space"></Box>
|
||||
<PseudoBox
|
||||
gridArea="picker"
|
||||
opacity={hasFocus ? 1 : 0}
|
||||
_groupHover={{ opacity: 1 }}
|
||||
transition="opacity 0.2s"
|
||||
>
|
||||
<SpeciesColorPicker
|
||||
outfitState={outfitState}
|
||||
dispatchToOutfit={dispatchToOutfit}
|
||||
onFocus={() => setHasFocus(true)}
|
||||
onBlur={() => setHasFocus(false)}
|
||||
/>
|
||||
</Tooltip>
|
||||
</PseudoBox>
|
||||
<Flex gridArea="download" justify="flex-end">
|
||||
<Tooltip label="Download" placement="left">
|
||||
<IconButton
|
||||
icon="download"
|
||||
aria-label="Download"
|
||||
isRound
|
||||
as="a"
|
||||
// eslint-disable-next-line no-script-url
|
||||
href={downloadImageUrl || "javascript:void 0"}
|
||||
download={(outfitState.name || "Outfit") + ".png"}
|
||||
onMouseEnter={prepareDownload}
|
||||
onFocus={() => {
|
||||
prepareDownload();
|
||||
setHasFocus(true);
|
||||
}}
|
||||
onBlur={() => setHasFocus(false)}
|
||||
cursor={!downloadImageUrl && "wait"}
|
||||
variant="unstyled"
|
||||
backgroundColor="gray.600"
|
||||
color="gray.50"
|
||||
boxShadow="md"
|
||||
d="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
opacity={hasFocus ? 1 : 0}
|
||||
transition="all 0.2s"
|
||||
_groupHover={{
|
||||
opacity: 1,
|
||||
}}
|
||||
_focus={{
|
||||
opacity: 1,
|
||||
backgroundColor: "gray.500",
|
||||
}}
|
||||
_hover={{
|
||||
backgroundColor: "gray.500",
|
||||
}}
|
||||
outline="initial"
|
||||
/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
</Box>
|
||||
</PseudoBox>
|
||||
);
|
||||
|
@ -218,14 +247,14 @@ function useDownloadableImage(visibleLayers) {
|
|||
const [preparedForLayerIds, setPreparedForLayerIds] = React.useState([]);
|
||||
|
||||
const prepareDownload = React.useCallback(async () => {
|
||||
setDownloadImageUrl(null);
|
||||
|
||||
// Skip if the current image URL is already correct for these layers.
|
||||
const layerIds = visibleLayers.map((l) => l.id);
|
||||
if (layerIds.join(",") === preparedForLayerIds.join(",")) {
|
||||
return;
|
||||
}
|
||||
|
||||
setDownloadImageUrl(null);
|
||||
|
||||
const imagePromises = visibleLayers.map(
|
||||
(layer) =>
|
||||
new Promise((resolve, reject) => {
|
||||
|
|
144
src/SpeciesColorPicker.js
Normal file
144
src/SpeciesColorPicker.js
Normal file
|
@ -0,0 +1,144 @@
|
|||
import React from "react";
|
||||
import gql from "graphql-tag";
|
||||
import { useQuery } from "@apollo/react-hooks";
|
||||
import { Box, Flex, Select, Text, useToast } from "@chakra-ui/core";
|
||||
|
||||
import { Delay } from "./util";
|
||||
|
||||
function SpeciesColorPicker({
|
||||
outfitState,
|
||||
dispatchToOutfit,
|
||||
onFocus,
|
||||
onBlur,
|
||||
}) {
|
||||
const toast = useToast();
|
||||
const { loading, error, data } = useQuery(gql`
|
||||
query {
|
||||
allSpecies {
|
||||
id
|
||||
name
|
||||
}
|
||||
|
||||
allColors {
|
||||
id
|
||||
name
|
||||
}
|
||||
|
||||
allValidSpeciesColorPairs {
|
||||
species {
|
||||
id
|
||||
}
|
||||
color {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const allColors = (data && [...data.allColors]) || [];
|
||||
allColors.sort((a, b) => a.name.localeCompare(b.name));
|
||||
const allSpecies = (data && [...data.allSpecies]) || [];
|
||||
allSpecies.sort((a, b) => a.name.localeCompare(b.name));
|
||||
const allValidSpeciesColorPairs = React.useMemo(
|
||||
() =>
|
||||
new Set(
|
||||
((data && data.allValidSpeciesColorPairs) || []).map(
|
||||
(p) => `${p.species.id},${p.color.id}`
|
||||
)
|
||||
),
|
||||
[data]
|
||||
);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<Delay ms={5000}>
|
||||
<Text color="gray.50" textShadow="md">
|
||||
Loading species/color data…
|
||||
</Text>
|
||||
</Delay>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Text color="gray.50" textShadow="md">
|
||||
Error loading species/color data.
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
const onChangeColor = (e) => {
|
||||
const speciesId = outfitState.speciesId;
|
||||
const colorId = e.target.value;
|
||||
const pair = `${speciesId},${colorId}`;
|
||||
if (allValidSpeciesColorPairs.has(pair)) {
|
||||
dispatchToOutfit({ type: "changeColor", colorId: e.target.value });
|
||||
} else {
|
||||
console.log(pair, Array.from(allValidSpeciesColorPairs));
|
||||
const species = allSpecies.find((s) => s.id === speciesId);
|
||||
const color = allColors.find((c) => c.id === colorId);
|
||||
toast({
|
||||
title: `We haven't seen a ${color.name} ${species.name} before! 😓`,
|
||||
status: "warning",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onChangeSpecies = (e) => {
|
||||
const colorId = outfitState.colorId;
|
||||
const speciesId = e.target.value;
|
||||
const pair = `${speciesId},${colorId}`;
|
||||
if (allValidSpeciesColorPairs.has(pair)) {
|
||||
dispatchToOutfit({ type: "changeSpecies", speciesId: e.target.value });
|
||||
} else {
|
||||
console.log(pair, Array.from(allValidSpeciesColorPairs));
|
||||
const species = allSpecies.find((s) => s.id === speciesId);
|
||||
const color = allColors.find((c) => c.id === colorId);
|
||||
toast({
|
||||
title: `We haven't seen a ${color.name} ${species.name} before! 😓`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex direction="row">
|
||||
<Select
|
||||
aria-label="Pet color"
|
||||
value={outfitState.colorId}
|
||||
onChange={onChangeColor}
|
||||
backgroundColor="gray.600"
|
||||
color="gray.50"
|
||||
border="none"
|
||||
boxShadow="md"
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
>
|
||||
{allColors.map((color) => (
|
||||
<option key={color.id} value={color.id}>
|
||||
{color.name}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
<Box width="8" />
|
||||
<Select
|
||||
aria-label="Pet species"
|
||||
value={outfitState.speciesId}
|
||||
onChange={onChangeSpecies}
|
||||
backgroundColor="gray.600"
|
||||
color="gray.50"
|
||||
border="none"
|
||||
boxShadow="md"
|
||||
onFocus={onFocus}
|
||||
onBlur={onBlur}
|
||||
>
|
||||
{allSpecies.map((species) => (
|
||||
<option key={species.id} value={species.id}>
|
||||
{species.name}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
export default SpeciesColorPicker;
|
|
@ -65,7 +65,10 @@ function WardrobePage() {
|
|||
width="100%"
|
||||
>
|
||||
<Box gridArea="outfit" backgroundColor="gray.900">
|
||||
<OutfitPreview outfitState={outfitState} />
|
||||
<OutfitPreview
|
||||
outfitState={outfitState}
|
||||
dispatchToOutfit={dispatchToOutfit}
|
||||
/>
|
||||
</Box>
|
||||
<Box gridArea="search" boxShadow="sm">
|
||||
<Box px="5" py="3">
|
||||
|
|
|
@ -2,6 +2,7 @@ const { gql } = require("apollo-server");
|
|||
|
||||
const connectToDb = require("./db");
|
||||
const buildLoaders = require("./loaders");
|
||||
const { capitalize } = require("./util");
|
||||
|
||||
const typeDefs = gql`
|
||||
enum LayerImageSize {
|
||||
|
@ -140,7 +141,7 @@ const resolvers = {
|
|||
Color: {
|
||||
name: async (color, _, { colorTranslationLoader }) => {
|
||||
const colorTranslation = await colorTranslationLoader.load(color.id);
|
||||
return colorTranslation.name;
|
||||
return capitalize(colorTranslation.name);
|
||||
},
|
||||
},
|
||||
Species: {
|
||||
|
@ -148,7 +149,7 @@ const resolvers = {
|
|||
const speciesTranslation = await speciesTranslationLoader.load(
|
||||
species.id
|
||||
);
|
||||
return speciesTranslation.name;
|
||||
return capitalize(speciesTranslation.name);
|
||||
},
|
||||
},
|
||||
Query: {
|
||||
|
|
|
@ -769,223 +769,223 @@ describe("Species", () => {
|
|||
"allSpecies": Array [
|
||||
Object {
|
||||
"id": "1",
|
||||
"name": "acara",
|
||||
"name": "Acara",
|
||||
},
|
||||
Object {
|
||||
"id": "2",
|
||||
"name": "aisha",
|
||||
"name": "Aisha",
|
||||
},
|
||||
Object {
|
||||
"id": "3",
|
||||
"name": "blumaroo",
|
||||
"name": "Blumaroo",
|
||||
},
|
||||
Object {
|
||||
"id": "4",
|
||||
"name": "bori",
|
||||
"name": "Bori",
|
||||
},
|
||||
Object {
|
||||
"id": "5",
|
||||
"name": "bruce",
|
||||
"name": "Bruce",
|
||||
},
|
||||
Object {
|
||||
"id": "6",
|
||||
"name": "buzz",
|
||||
"name": "Buzz",
|
||||
},
|
||||
Object {
|
||||
"id": "7",
|
||||
"name": "chia",
|
||||
"name": "Chia",
|
||||
},
|
||||
Object {
|
||||
"id": "8",
|
||||
"name": "chomby",
|
||||
"name": "Chomby",
|
||||
},
|
||||
Object {
|
||||
"id": "9",
|
||||
"name": "cybunny",
|
||||
"name": "Cybunny",
|
||||
},
|
||||
Object {
|
||||
"id": "10",
|
||||
"name": "draik",
|
||||
"name": "Draik",
|
||||
},
|
||||
Object {
|
||||
"id": "11",
|
||||
"name": "elephante",
|
||||
"name": "Elephante",
|
||||
},
|
||||
Object {
|
||||
"id": "12",
|
||||
"name": "eyrie",
|
||||
"name": "Eyrie",
|
||||
},
|
||||
Object {
|
||||
"id": "13",
|
||||
"name": "flotsam",
|
||||
"name": "Flotsam",
|
||||
},
|
||||
Object {
|
||||
"id": "14",
|
||||
"name": "gelert",
|
||||
"name": "Gelert",
|
||||
},
|
||||
Object {
|
||||
"id": "15",
|
||||
"name": "gnorbu",
|
||||
"name": "Gnorbu",
|
||||
},
|
||||
Object {
|
||||
"id": "16",
|
||||
"name": "grarrl",
|
||||
"name": "Grarrl",
|
||||
},
|
||||
Object {
|
||||
"id": "17",
|
||||
"name": "grundo",
|
||||
"name": "Grundo",
|
||||
},
|
||||
Object {
|
||||
"id": "18",
|
||||
"name": "hissi",
|
||||
"name": "Hissi",
|
||||
},
|
||||
Object {
|
||||
"id": "19",
|
||||
"name": "ixi",
|
||||
"name": "Ixi",
|
||||
},
|
||||
Object {
|
||||
"id": "20",
|
||||
"name": "jetsam",
|
||||
"name": "Jetsam",
|
||||
},
|
||||
Object {
|
||||
"id": "21",
|
||||
"name": "jubjub",
|
||||
"name": "Jubjub",
|
||||
},
|
||||
Object {
|
||||
"id": "22",
|
||||
"name": "kacheek",
|
||||
"name": "Kacheek",
|
||||
},
|
||||
Object {
|
||||
"id": "23",
|
||||
"name": "kau",
|
||||
"name": "Kau",
|
||||
},
|
||||
Object {
|
||||
"id": "24",
|
||||
"name": "kiko",
|
||||
"name": "Kiko",
|
||||
},
|
||||
Object {
|
||||
"id": "25",
|
||||
"name": "koi",
|
||||
"name": "Koi",
|
||||
},
|
||||
Object {
|
||||
"id": "26",
|
||||
"name": "korbat",
|
||||
"name": "Korbat",
|
||||
},
|
||||
Object {
|
||||
"id": "27",
|
||||
"name": "kougra",
|
||||
"name": "Kougra",
|
||||
},
|
||||
Object {
|
||||
"id": "28",
|
||||
"name": "krawk",
|
||||
"name": "Krawk",
|
||||
},
|
||||
Object {
|
||||
"id": "29",
|
||||
"name": "kyrii",
|
||||
"name": "Kyrii",
|
||||
},
|
||||
Object {
|
||||
"id": "30",
|
||||
"name": "lenny",
|
||||
"name": "Lenny",
|
||||
},
|
||||
Object {
|
||||
"id": "31",
|
||||
"name": "lupe",
|
||||
"name": "Lupe",
|
||||
},
|
||||
Object {
|
||||
"id": "32",
|
||||
"name": "lutari",
|
||||
"name": "Lutari",
|
||||
},
|
||||
Object {
|
||||
"id": "33",
|
||||
"name": "meerca",
|
||||
"name": "Meerca",
|
||||
},
|
||||
Object {
|
||||
"id": "34",
|
||||
"name": "moehog",
|
||||
"name": "Moehog",
|
||||
},
|
||||
Object {
|
||||
"id": "35",
|
||||
"name": "mynci",
|
||||
"name": "Mynci",
|
||||
},
|
||||
Object {
|
||||
"id": "36",
|
||||
"name": "nimmo",
|
||||
"name": "Nimmo",
|
||||
},
|
||||
Object {
|
||||
"id": "37",
|
||||
"name": "ogrin",
|
||||
"name": "Ogrin",
|
||||
},
|
||||
Object {
|
||||
"id": "38",
|
||||
"name": "peophin",
|
||||
"name": "Peophin",
|
||||
},
|
||||
Object {
|
||||
"id": "39",
|
||||
"name": "poogle",
|
||||
"name": "Poogle",
|
||||
},
|
||||
Object {
|
||||
"id": "40",
|
||||
"name": "pteri",
|
||||
"name": "Pteri",
|
||||
},
|
||||
Object {
|
||||
"id": "41",
|
||||
"name": "quiggle",
|
||||
"name": "Quiggle",
|
||||
},
|
||||
Object {
|
||||
"id": "42",
|
||||
"name": "ruki",
|
||||
"name": "Ruki",
|
||||
},
|
||||
Object {
|
||||
"id": "43",
|
||||
"name": "scorchio",
|
||||
"name": "Scorchio",
|
||||
},
|
||||
Object {
|
||||
"id": "44",
|
||||
"name": "shoyru",
|
||||
"name": "Shoyru",
|
||||
},
|
||||
Object {
|
||||
"id": "45",
|
||||
"name": "skeith",
|
||||
"name": "Skeith",
|
||||
},
|
||||
Object {
|
||||
"id": "46",
|
||||
"name": "techo",
|
||||
"name": "Techo",
|
||||
},
|
||||
Object {
|
||||
"id": "47",
|
||||
"name": "tonu",
|
||||
"name": "Tonu",
|
||||
},
|
||||
Object {
|
||||
"id": "48",
|
||||
"name": "tuskaninny",
|
||||
"name": "Tuskaninny",
|
||||
},
|
||||
Object {
|
||||
"id": "49",
|
||||
"name": "uni",
|
||||
"name": "Uni",
|
||||
},
|
||||
Object {
|
||||
"id": "50",
|
||||
"name": "usul",
|
||||
"name": "Usul",
|
||||
},
|
||||
Object {
|
||||
"id": "51",
|
||||
"name": "wocky",
|
||||
"name": "Wocky",
|
||||
},
|
||||
Object {
|
||||
"id": "52",
|
||||
"name": "xweetok",
|
||||
"name": "Xweetok",
|
||||
},
|
||||
Object {
|
||||
"id": "53",
|
||||
"name": "yurble",
|
||||
"name": "Yurble",
|
||||
},
|
||||
Object {
|
||||
"id": "54",
|
||||
"name": "zafara",
|
||||
"name": "Zafara",
|
||||
},
|
||||
Object {
|
||||
"id": "55",
|
||||
"name": "vandagyre",
|
||||
"name": "Vandagyre",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
@ -1078,373 +1078,369 @@ describe("Color", () => {
|
|||
expect(res.data).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"allColors": Array [
|
||||
Object {
|
||||
"id": "-1",
|
||||
"name": "nebula",
|
||||
},
|
||||
Object {
|
||||
"id": "1",
|
||||
"name": "alien",
|
||||
"name": "Alien",
|
||||
},
|
||||
Object {
|
||||
"id": "2",
|
||||
"name": "apple",
|
||||
"name": "Apple",
|
||||
},
|
||||
Object {
|
||||
"id": "3",
|
||||
"name": "asparagus",
|
||||
"name": "Asparagus",
|
||||
},
|
||||
Object {
|
||||
"id": "4",
|
||||
"name": "aubergine",
|
||||
"name": "Aubergine",
|
||||
},
|
||||
Object {
|
||||
"id": "5",
|
||||
"name": "avocado",
|
||||
"name": "Avocado",
|
||||
},
|
||||
Object {
|
||||
"id": "6",
|
||||
"name": "baby",
|
||||
"name": "Baby",
|
||||
},
|
||||
Object {
|
||||
"id": "7",
|
||||
"name": "biscuit",
|
||||
"name": "Biscuit",
|
||||
},
|
||||
Object {
|
||||
"id": "8",
|
||||
"name": "blue",
|
||||
"name": "Blue",
|
||||
},
|
||||
Object {
|
||||
"id": "9",
|
||||
"name": "blueberry",
|
||||
"name": "Blueberry",
|
||||
},
|
||||
Object {
|
||||
"id": "10",
|
||||
"name": "brown",
|
||||
"name": "Brown",
|
||||
},
|
||||
Object {
|
||||
"id": "11",
|
||||
"name": "camouflage",
|
||||
"name": "Camouflage",
|
||||
},
|
||||
Object {
|
||||
"id": "12",
|
||||
"name": "carrot",
|
||||
"name": "Carrot",
|
||||
},
|
||||
Object {
|
||||
"id": "13",
|
||||
"name": "checkered",
|
||||
"name": "Checkered",
|
||||
},
|
||||
Object {
|
||||
"id": "14",
|
||||
"name": "chocolate",
|
||||
"name": "Chocolate",
|
||||
},
|
||||
Object {
|
||||
"id": "15",
|
||||
"name": "chokato",
|
||||
"name": "Chokato",
|
||||
},
|
||||
Object {
|
||||
"id": "16",
|
||||
"name": "christmas",
|
||||
"name": "Christmas",
|
||||
},
|
||||
Object {
|
||||
"id": "17",
|
||||
"name": "clay",
|
||||
"name": "Clay",
|
||||
},
|
||||
Object {
|
||||
"id": "18",
|
||||
"name": "cloud",
|
||||
"name": "Cloud",
|
||||
},
|
||||
Object {
|
||||
"id": "19",
|
||||
"name": "coconut",
|
||||
"name": "Coconut",
|
||||
},
|
||||
Object {
|
||||
"id": "20",
|
||||
"name": "custard",
|
||||
"name": "Custard",
|
||||
},
|
||||
Object {
|
||||
"id": "21",
|
||||
"name": "darigan",
|
||||
"name": "Darigan",
|
||||
},
|
||||
Object {
|
||||
"id": "22",
|
||||
"name": "desert",
|
||||
"name": "Desert",
|
||||
},
|
||||
Object {
|
||||
"id": "23",
|
||||
"name": "disco",
|
||||
"name": "Disco",
|
||||
},
|
||||
Object {
|
||||
"id": "24",
|
||||
"name": "durian",
|
||||
"name": "Durian",
|
||||
},
|
||||
Object {
|
||||
"id": "25",
|
||||
"name": "electric",
|
||||
"name": "Electric",
|
||||
},
|
||||
Object {
|
||||
"id": "26",
|
||||
"name": "faerie",
|
||||
"name": "Faerie",
|
||||
},
|
||||
Object {
|
||||
"id": "27",
|
||||
"name": "fire",
|
||||
"name": "Fire",
|
||||
},
|
||||
Object {
|
||||
"id": "28",
|
||||
"name": "garlic",
|
||||
"name": "Garlic",
|
||||
},
|
||||
Object {
|
||||
"id": "29",
|
||||
"name": "ghost",
|
||||
"name": "Ghost",
|
||||
},
|
||||
Object {
|
||||
"id": "30",
|
||||
"name": "glowing",
|
||||
"name": "Glowing",
|
||||
},
|
||||
Object {
|
||||
"id": "31",
|
||||
"name": "gold",
|
||||
"name": "Gold",
|
||||
},
|
||||
Object {
|
||||
"id": "32",
|
||||
"name": "gooseberry",
|
||||
"name": "Gooseberry",
|
||||
},
|
||||
Object {
|
||||
"id": "33",
|
||||
"name": "grape",
|
||||
"name": "Grape",
|
||||
},
|
||||
Object {
|
||||
"id": "34",
|
||||
"name": "green",
|
||||
"name": "Green",
|
||||
},
|
||||
Object {
|
||||
"id": "35",
|
||||
"name": "grey",
|
||||
"name": "Grey",
|
||||
},
|
||||
Object {
|
||||
"id": "36",
|
||||
"name": "halloween",
|
||||
"name": "Halloween",
|
||||
},
|
||||
Object {
|
||||
"id": "37",
|
||||
"name": "ice",
|
||||
"name": "Ice",
|
||||
},
|
||||
Object {
|
||||
"id": "38",
|
||||
"name": "invisible",
|
||||
"name": "Invisible",
|
||||
},
|
||||
Object {
|
||||
"id": "39",
|
||||
"name": "island",
|
||||
"name": "Island",
|
||||
},
|
||||
Object {
|
||||
"id": "40",
|
||||
"name": "jelly",
|
||||
"name": "Jelly",
|
||||
},
|
||||
Object {
|
||||
"id": "41",
|
||||
"name": "lemon",
|
||||
"name": "Lemon",
|
||||
},
|
||||
Object {
|
||||
"id": "42",
|
||||
"name": "lime",
|
||||
"name": "Lime",
|
||||
},
|
||||
Object {
|
||||
"id": "43",
|
||||
"name": "mallow",
|
||||
"name": "Mallow",
|
||||
},
|
||||
Object {
|
||||
"id": "44",
|
||||
"name": "maraquan",
|
||||
"name": "Maraquan",
|
||||
},
|
||||
Object {
|
||||
"id": "45",
|
||||
"name": "msp",
|
||||
"name": "Msp",
|
||||
},
|
||||
Object {
|
||||
"id": "46",
|
||||
"name": "mutant",
|
||||
"name": "Mutant",
|
||||
},
|
||||
Object {
|
||||
"id": "47",
|
||||
"name": "orange",
|
||||
"name": "Orange",
|
||||
},
|
||||
Object {
|
||||
"id": "48",
|
||||
"name": "pea",
|
||||
"name": "Pea",
|
||||
},
|
||||
Object {
|
||||
"id": "49",
|
||||
"name": "peach",
|
||||
"name": "Peach",
|
||||
},
|
||||
Object {
|
||||
"id": "50",
|
||||
"name": "pear",
|
||||
"name": "Pear",
|
||||
},
|
||||
Object {
|
||||
"id": "51",
|
||||
"name": "pepper",
|
||||
"name": "Pepper",
|
||||
},
|
||||
Object {
|
||||
"id": "52",
|
||||
"name": "pineapple",
|
||||
"name": "Pineapple",
|
||||
},
|
||||
Object {
|
||||
"id": "53",
|
||||
"name": "pink",
|
||||
"name": "Pink",
|
||||
},
|
||||
Object {
|
||||
"id": "54",
|
||||
"name": "pirate",
|
||||
"name": "Pirate",
|
||||
},
|
||||
Object {
|
||||
"id": "55",
|
||||
"name": "plum",
|
||||
"name": "Plum",
|
||||
},
|
||||
Object {
|
||||
"id": "56",
|
||||
"name": "plushie",
|
||||
"name": "Plushie",
|
||||
},
|
||||
Object {
|
||||
"id": "57",
|
||||
"name": "purple",
|
||||
"name": "Purple",
|
||||
},
|
||||
Object {
|
||||
"id": "58",
|
||||
"name": "quigukiboy",
|
||||
"name": "Quigukiboy",
|
||||
},
|
||||
Object {
|
||||
"id": "59",
|
||||
"name": "quigukigirl",
|
||||
"name": "Quigukigirl",
|
||||
},
|
||||
Object {
|
||||
"id": "60",
|
||||
"name": "rainbow",
|
||||
"name": "Rainbow",
|
||||
},
|
||||
Object {
|
||||
"id": "61",
|
||||
"name": "red",
|
||||
"name": "Red",
|
||||
},
|
||||
Object {
|
||||
"id": "62",
|
||||
"name": "robot",
|
||||
"name": "Robot",
|
||||
},
|
||||
Object {
|
||||
"id": "63",
|
||||
"name": "royalboy",
|
||||
"name": "Royalboy",
|
||||
},
|
||||
Object {
|
||||
"id": "64",
|
||||
"name": "royalgirl",
|
||||
"name": "Royalgirl",
|
||||
},
|
||||
Object {
|
||||
"id": "65",
|
||||
"name": "shadow",
|
||||
"name": "Shadow",
|
||||
},
|
||||
Object {
|
||||
"id": "66",
|
||||
"name": "silver",
|
||||
"name": "Silver",
|
||||
},
|
||||
Object {
|
||||
"id": "67",
|
||||
"name": "sketch",
|
||||
"name": "Sketch",
|
||||
},
|
||||
Object {
|
||||
"id": "68",
|
||||
"name": "skunk",
|
||||
"name": "Skunk",
|
||||
},
|
||||
Object {
|
||||
"id": "69",
|
||||
"name": "snot",
|
||||
"name": "Snot",
|
||||
},
|
||||
Object {
|
||||
"id": "70",
|
||||
"name": "snow",
|
||||
"name": "Snow",
|
||||
},
|
||||
Object {
|
||||
"id": "71",
|
||||
"name": "speckled",
|
||||
"name": "Speckled",
|
||||
},
|
||||
Object {
|
||||
"id": "72",
|
||||
"name": "split",
|
||||
"name": "Split",
|
||||
},
|
||||
Object {
|
||||
"id": "73",
|
||||
"name": "sponge",
|
||||
"name": "Sponge",
|
||||
},
|
||||
Object {
|
||||
"id": "74",
|
||||
"name": "spotted",
|
||||
"name": "Spotted",
|
||||
},
|
||||
Object {
|
||||
"id": "75",
|
||||
"name": "starry",
|
||||
"name": "Starry",
|
||||
},
|
||||
Object {
|
||||
"id": "76",
|
||||
"name": "strawberry",
|
||||
"name": "Strawberry",
|
||||
},
|
||||
Object {
|
||||
"id": "77",
|
||||
"name": "striped",
|
||||
"name": "Striped",
|
||||
},
|
||||
Object {
|
||||
"id": "78",
|
||||
"name": "thornberry",
|
||||
"name": "Thornberry",
|
||||
},
|
||||
Object {
|
||||
"id": "79",
|
||||
"name": "tomato",
|
||||
"name": "Tomato",
|
||||
},
|
||||
Object {
|
||||
"id": "80",
|
||||
"name": "tyrannian",
|
||||
"name": "Tyrannian",
|
||||
},
|
||||
Object {
|
||||
"id": "81",
|
||||
"name": "usuki boy",
|
||||
"name": "Usuki boy",
|
||||
},
|
||||
Object {
|
||||
"id": "82",
|
||||
"name": "usuki girl",
|
||||
"name": "Usuki girl",
|
||||
},
|
||||
Object {
|
||||
"id": "83",
|
||||
"name": "white",
|
||||
"name": "White",
|
||||
},
|
||||
Object {
|
||||
"id": "84",
|
||||
"name": "yellow",
|
||||
"name": "Yellow",
|
||||
},
|
||||
Object {
|
||||
"id": "85",
|
||||
"name": "zombie",
|
||||
"name": "Zombie",
|
||||
},
|
||||
Object {
|
||||
"id": "86",
|
||||
"name": "onion",
|
||||
"name": "Onion",
|
||||
},
|
||||
Object {
|
||||
"id": "87",
|
||||
"name": "magma",
|
||||
"name": "Magma",
|
||||
},
|
||||
Object {
|
||||
"id": "88",
|
||||
"name": "relic",
|
||||
"name": "Relic",
|
||||
},
|
||||
Object {
|
||||
"id": "89",
|
||||
"name": "woodland",
|
||||
"name": "Woodland",
|
||||
},
|
||||
Object {
|
||||
"id": "90",
|
||||
"name": "transparent",
|
||||
"name": "Transparent",
|
||||
},
|
||||
Object {
|
||||
"id": "91",
|
||||
"name": "maractite",
|
||||
"name": "Maractite",
|
||||
},
|
||||
Object {
|
||||
"id": "92",
|
||||
|
@ -1452,47 +1448,47 @@ describe("Color", () => {
|
|||
},
|
||||
Object {
|
||||
"id": "93",
|
||||
"name": "swamp gas",
|
||||
"name": "Swamp gas",
|
||||
},
|
||||
Object {
|
||||
"id": "94",
|
||||
"name": "water",
|
||||
"name": "Water",
|
||||
},
|
||||
Object {
|
||||
"id": "95",
|
||||
"name": "wraith",
|
||||
"name": "Wraith",
|
||||
},
|
||||
Object {
|
||||
"id": "96",
|
||||
"name": "eventide",
|
||||
"name": "Eventide",
|
||||
},
|
||||
Object {
|
||||
"id": "97",
|
||||
"name": "elderlyboy",
|
||||
"name": "Elderlyboy",
|
||||
},
|
||||
Object {
|
||||
"id": "98",
|
||||
"name": "elderlygirl",
|
||||
"name": "Elderlygirl",
|
||||
},
|
||||
Object {
|
||||
"id": "99",
|
||||
"name": "stealthy",
|
||||
"name": "Stealthy",
|
||||
},
|
||||
Object {
|
||||
"id": "100",
|
||||
"name": "dimensional",
|
||||
"name": "Dimensional",
|
||||
},
|
||||
Object {
|
||||
"id": "101",
|
||||
"name": "agueena",
|
||||
"name": "Agueena",
|
||||
},
|
||||
Object {
|
||||
"id": "102",
|
||||
"name": "pastel",
|
||||
"name": "Pastel",
|
||||
},
|
||||
Object {
|
||||
"id": "103",
|
||||
"name": "ummagine",
|
||||
"name": "Ummagine",
|
||||
},
|
||||
Object {
|
||||
"id": "104",
|
||||
|
@ -1504,7 +1500,7 @@ describe("Color", () => {
|
|||
},
|
||||
Object {
|
||||
"id": "106",
|
||||
"name": "marble",
|
||||
"name": "Marble",
|
||||
},
|
||||
Object {
|
||||
"id": "107",
|
||||
|
@ -1536,13 +1532,12 @@ describe("Color", () => {
|
|||
expect(queryFn.mock.calls).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Array [
|
||||
"SELECT * FROM colors",
|
||||
"SELECT * FROM colors WHERE prank = 0",
|
||||
],
|
||||
Array [
|
||||
"SELECT * FROM color_translations
|
||||
WHERE color_id IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) AND locale = \\"en\\"",
|
||||
WHERE color_id IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) AND locale = \\"en\\"",
|
||||
Array [
|
||||
"-1",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const DataLoader = require("dataloader");
|
||||
|
||||
const loadAllColors = (db) => async () => {
|
||||
const [rows, _] = await db.execute(`SELECT * FROM colors`);
|
||||
const [rows, _] = await db.execute(`SELECT * FROM colors WHERE prank = 0`);
|
||||
const entities = rows.map(normalizeRow);
|
||||
return entities;
|
||||
};
|
||||
|
|
5
src/server/util.js
Normal file
5
src/server/util.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
function capitalize(str) {
|
||||
return str[0].toUpperCase() + str.slice(1);
|
||||
}
|
||||
|
||||
module.exports = { capitalize };
|
|
@ -94,6 +94,10 @@ const outfitStateReducer = (apolloClient) => (baseState, action) => {
|
|||
switch (action.type) {
|
||||
case "rename":
|
||||
return { ...baseState, name: action.outfitName };
|
||||
case "changeColor":
|
||||
return { ...baseState, colorId: action.colorId };
|
||||
case "changeSpecies":
|
||||
return { ...baseState, speciesId: action.speciesId };
|
||||
case "wearItem":
|
||||
return produce(baseState, (state) => {
|
||||
// A hack to work around https://github.com/immerjs/immer/issues/586
|
||||
|
@ -143,7 +147,7 @@ const outfitStateReducer = (apolloClient) => (baseState, action) => {
|
|||
closetedItemIds.delete(itemId);
|
||||
});
|
||||
default:
|
||||
throw new Error(`unexpected action ${action}`);
|
||||
throw new Error(`unexpected action ${JSON.stringify(action)}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue