favicon changing
BIN
frontend-react/public/favicon_blue.png
Normal file
|
After Width: | Height: | Size: 735 B |
BIN
frontend-react/public/favicon_cyan.png
Normal file
|
After Width: | Height: | Size: 693 B |
BIN
frontend-react/public/favicon_gray.png
Normal file
|
After Width: | Height: | Size: 744 B |
BIN
frontend-react/public/favicon_green.png
Normal file
|
After Width: | Height: | Size: 739 B |
BIN
frontend-react/public/favicon_orange.png
Normal file
|
After Width: | Height: | Size: 740 B |
BIN
frontend-react/public/favicon_pink.png
Normal file
|
After Width: | Height: | Size: 747 B |
BIN
frontend-react/public/favicon_purple.png
Normal file
|
After Width: | Height: | Size: 741 B |
BIN
frontend-react/public/favicon_red.png
Normal file
|
After Width: | Height: | Size: 731 B |
BIN
frontend-react/public/favicon_teal.png
Normal file
|
After Width: | Height: | Size: 740 B |
BIN
frontend-react/public/favicon_yellow.png
Normal file
|
After Width: | Height: | Size: 735 B |
@@ -4,7 +4,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="theme-color" content="#232946" />
|
||||
<meta name="description" content="Competitive Splatoon hub" />
|
||||
<link rel="apple-touch-icon" href="logo192.png" />
|
||||
<!--
|
||||
|
||||
95
frontend-react/src/components/builds/AbilitySelector.tsx
Normal file
@@ -0,0 +1,95 @@
|
||||
import React, { useState } from "react"
|
||||
import FieldsetWithLegend from "../common/FieldsetWithLegend"
|
||||
import { Flex, Box, Button } from "@chakra-ui/core"
|
||||
import { abilitiesGameOrder } from "../../utils/lists"
|
||||
import AbilityIcon from "./AbilityIcon"
|
||||
import { Ability } from "../../types"
|
||||
import { useContext } from "react"
|
||||
import MyThemeContext from "../../themeContext"
|
||||
|
||||
interface AbilitySelectorProps {
|
||||
abilities: Ability[]
|
||||
setAbilities: (abilities: Ability[]) => void
|
||||
}
|
||||
|
||||
const AbilitySelector: React.FC<AbilitySelectorProps> = ({
|
||||
abilities,
|
||||
setAbilities,
|
||||
}) => {
|
||||
const [show, setShow] = useState(false)
|
||||
const { themeColor } = useContext(MyThemeContext)
|
||||
return show ? (
|
||||
<>
|
||||
<Button
|
||||
variantColor={themeColor}
|
||||
onClick={() => {
|
||||
setShow(!show)
|
||||
setAbilities([])
|
||||
}}
|
||||
>
|
||||
Hide ability filter
|
||||
</Button>
|
||||
<FieldsetWithLegend
|
||||
title="Click an ability to filter by it"
|
||||
titleFontSize="md"
|
||||
centerTitle
|
||||
dividerMode
|
||||
mt="1em"
|
||||
>
|
||||
<Flex flexWrap="wrap" justifyContent="center">
|
||||
{abilitiesGameOrder.map(ability => (
|
||||
<Box
|
||||
key={ability}
|
||||
p="5px"
|
||||
cursor={abilities.indexOf(ability) === -1 ? "pointer" : undefined}
|
||||
onClick={() => {
|
||||
if (abilities.indexOf(ability) !== -1) return
|
||||
setAbilities(abilities.concat(ability))
|
||||
}}
|
||||
>
|
||||
<AbilityIcon
|
||||
ability={abilities.indexOf(ability) === -1 ? ability : "EMPTY"}
|
||||
size="SUB"
|
||||
/>{" "}
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
</FieldsetWithLegend>
|
||||
{abilities.length > 0 && (
|
||||
<Box textAlign="center" width="100%">
|
||||
<FieldsetWithLegend
|
||||
title="Only showing builds featuring the following abilities"
|
||||
titleFontSize="md"
|
||||
centerTitle
|
||||
fullWidth
|
||||
>
|
||||
<Flex flexWrap="wrap" justifyContent="center">
|
||||
{abilities.map(ability => (
|
||||
<Box
|
||||
key={ability}
|
||||
cursor="pointer"
|
||||
p="5px"
|
||||
onClick={() =>
|
||||
setAbilities(
|
||||
abilities.filter(
|
||||
abilityInArray => ability !== abilityInArray
|
||||
)
|
||||
)
|
||||
}
|
||||
>
|
||||
<AbilityIcon ability={ability} size="SUB" />{" "}
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
</FieldsetWithLegend>
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<Button variantColor={themeColor} onClick={() => setShow(!show)}>
|
||||
Filter by ability
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
export default AbilitySelector
|
||||
@@ -34,6 +34,7 @@ import BuildCard from "./BuildCard"
|
||||
import InfiniteScroll from "react-infinite-scroller"
|
||||
import FieldsetWithLegend from "../common/FieldsetWithLegend"
|
||||
import PageHeader from "../common/PageHeader"
|
||||
import AbilitySelector from "./AbilitySelector"
|
||||
|
||||
const BuildsPage: React.FC<RouteComponentProps> = () => {
|
||||
const { themeColor } = useContext(MyThemeContext)
|
||||
@@ -72,79 +73,22 @@ const BuildsPage: React.FC<RouteComponentProps> = () => {
|
||||
<title>{weapon ? `${weapon} ` : ""}Builds | sendou.ink</title>
|
||||
</Helmet>
|
||||
<PageHeader title="Builds" />
|
||||
<Box mb="1em">
|
||||
<FormLabel htmlFor="apview">Default to Ability Point view</FormLabel>
|
||||
<Switch
|
||||
id="apview"
|
||||
color={themeColor}
|
||||
isChecked={prefersAPView === null ? false : prefersAPView}
|
||||
onChange={() => setAPPreference(!prefersAPView)}
|
||||
<FormLabel htmlFor="apview">Default to Ability Point view</FormLabel>
|
||||
<Switch
|
||||
id="apview"
|
||||
color={themeColor}
|
||||
isChecked={prefersAPView === null ? false : prefersAPView}
|
||||
onChange={() => setAPPreference(!prefersAPView)}
|
||||
/>
|
||||
<Box mt="1em">
|
||||
<WeaponSelector
|
||||
weapon={weapon}
|
||||
setWeapon={(weapon: Weapon | null) => setWeapon(weapon)}
|
||||
dropdownMode={isSmall}
|
||||
/>
|
||||
</Box>
|
||||
<WeaponSelector
|
||||
weapon={weapon}
|
||||
setWeapon={(weapon: Weapon | null) => setWeapon(weapon)}
|
||||
dropdownMode={isSmall}
|
||||
/>
|
||||
{weapon && (
|
||||
<FieldsetWithLegend
|
||||
title="Click an ability to filter by it"
|
||||
titleFontSize="md"
|
||||
centerTitle
|
||||
dividerMode
|
||||
>
|
||||
<Flex flexWrap="wrap" justifyContent="center">
|
||||
{abilitiesGameOrder.map(ability => (
|
||||
<Box
|
||||
key={ability}
|
||||
p="5px"
|
||||
cursor={
|
||||
abilities.indexOf(ability) === -1 ? "pointer" : undefined
|
||||
}
|
||||
onClick={() => {
|
||||
if (abilities.indexOf(ability) !== -1) return
|
||||
setAbilities(abilities.concat(ability))
|
||||
}}
|
||||
>
|
||||
<AbilityIcon
|
||||
ability={
|
||||
abilities.indexOf(ability) === -1 ? ability : "EMPTY"
|
||||
}
|
||||
size="SUB"
|
||||
/>{" "}
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
</FieldsetWithLegend>
|
||||
)}
|
||||
{abilities.length > 0 && (
|
||||
<Box textAlign="center" width="100%">
|
||||
<FieldsetWithLegend
|
||||
title="Only showing builds featuring the following abilities"
|
||||
titleFontSize="md"
|
||||
centerTitle
|
||||
fullWidth
|
||||
>
|
||||
<Flex flexWrap="wrap" justifyContent="center">
|
||||
{abilities.map(ability => (
|
||||
<Box
|
||||
key={ability}
|
||||
cursor="pointer"
|
||||
p="5px"
|
||||
onClick={() =>
|
||||
setAbilities(
|
||||
abilities.filter(
|
||||
abilityInArray => ability !== abilityInArray
|
||||
)
|
||||
)
|
||||
}
|
||||
>
|
||||
<AbilityIcon ability={ability} size="SUB" />{" "}
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
</FieldsetWithLegend>
|
||||
</Box>
|
||||
<AbilitySelector abilities={abilities} setAbilities={setAbilities} />
|
||||
)}
|
||||
{loading && <Loading />}
|
||||
{buildsFilterByAbilities.length > 0 && data && (
|
||||
@@ -154,7 +98,7 @@ const BuildsPage: React.FC<RouteComponentProps> = () => {
|
||||
loadMore={page => setBuildsToShow(page * 4)}
|
||||
hasMore={buildsToShow < data.searchForBuilds.length}
|
||||
>
|
||||
<Flex flexWrap="wrap" pt="2em">
|
||||
<Flex flexWrap="wrap" pt="2em" justifyContent="center">
|
||||
{buildsFilterByAbilities
|
||||
.filter((build, index) => index < buildsToShow)
|
||||
.map(build => (
|
||||
@@ -184,7 +128,7 @@ const BuildsPage: React.FC<RouteComponentProps> = () => {
|
||||
</>
|
||||
)}
|
||||
{weapon && buildsFilterByAbilities.length === 0 && (
|
||||
<Alert status="info" borderRadius="5px" mt="1em">
|
||||
<Alert status="info" borderRadius="5px" mt="2em">
|
||||
<AlertIcon />
|
||||
No builds found with the current selection. Please adjust it above.
|
||||
</Alert>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react"
|
||||
import { Box } from "@chakra-ui/core"
|
||||
import { Box, BoxProps } from "@chakra-ui/core"
|
||||
import { useContext } from "react"
|
||||
import MyThemeContext from "../../themeContext"
|
||||
|
||||
@@ -12,13 +12,14 @@ interface FieldsetWithLegendProps {
|
||||
fullWidth?: boolean
|
||||
}
|
||||
|
||||
const FieldsetWithLegend: React.FC<FieldsetWithLegendProps> = ({
|
||||
const FieldsetWithLegend: React.FC<FieldsetWithLegendProps & BoxProps> = ({
|
||||
children,
|
||||
title,
|
||||
titleFontSize,
|
||||
dividerMode = false,
|
||||
centerTitle = false,
|
||||
fullWidth = false,
|
||||
...props
|
||||
}) => {
|
||||
const { borderStyle, textColor } = useContext(MyThemeContext)
|
||||
return (
|
||||
@@ -31,6 +32,7 @@ const FieldsetWithLegend: React.FC<FieldsetWithLegendProps> = ({
|
||||
display="inline-block"
|
||||
p="1em"
|
||||
w={fullWidth ? "100%" : undefined}
|
||||
{...props}
|
||||
>
|
||||
<Box
|
||||
as="legend"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react"
|
||||
import { Weapon } from "../../types"
|
||||
import { Input, Flex, PseudoBox, Select, Box } from "@chakra-ui/core"
|
||||
import { Input, Flex, PseudoBox, Select } from "@chakra-ui/core"
|
||||
import { useState } from "react"
|
||||
import { weapons } from "../../utils/lists"
|
||||
import WeaponImage from "./WeaponImage"
|
||||
@@ -51,29 +51,28 @@ const WeaponSelector: React.FC<WeaponSelectorProps> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box pb="1em">
|
||||
<Input
|
||||
placeholder="Filter weapons"
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
w="50%"
|
||||
ml="auto"
|
||||
mr="auto"
|
||||
onKeyDown={(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (event.key !== "Enter") return
|
||||
const oneWeaponArray = weapons.filter(filterWeaponArray)
|
||||
if (oneWeaponArray.length !== 1) return
|
||||
setWeapon(oneWeaponArray[0])
|
||||
}}
|
||||
autoFocus
|
||||
/>
|
||||
</Box>
|
||||
<Input
|
||||
placeholder="Filter weapons"
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
w="50%"
|
||||
ml="auto"
|
||||
mr="auto"
|
||||
onKeyDown={(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (event.key !== "Enter") return
|
||||
const oneWeaponArray = weapons.filter(filterWeaponArray)
|
||||
if (oneWeaponArray.length !== 1) return
|
||||
setWeapon(oneWeaponArray[0])
|
||||
}}
|
||||
autoFocus
|
||||
/>
|
||||
<FieldsetWithLegend
|
||||
title="Click a weapon to select it"
|
||||
titleFontSize="md"
|
||||
dividerMode
|
||||
centerTitle
|
||||
fullWidth
|
||||
mt="1em"
|
||||
>
|
||||
<Flex flexWrap="wrap" justifyContent="center">
|
||||
{weapons.filter(filterWeaponArray).map(weapon => (
|
||||
|
||||
@@ -8,6 +8,7 @@ import useLocalStorage from "@rehooks/local-storage"
|
||||
import { ThemeColor } from "../../types"
|
||||
import { MyThemeProvider } from "../../themeContext"
|
||||
import { Theme } from "../../types"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
|
||||
const App: React.FC = () => {
|
||||
const chakraTheme = useChakraTheme()
|
||||
@@ -47,6 +48,9 @@ const App: React.FC = () => {
|
||||
|
||||
return (
|
||||
<MyThemeProvider value={theme[colorMode]}>
|
||||
<Helmet>
|
||||
<link rel="icon" type="image/png" href={`/favicon_${themeColor}.png`} />
|
||||
</Helmet>
|
||||
<Box
|
||||
marginLeft={[null, null, "250px"]}
|
||||
mt={["4em", null, "0"]}
|
||||
|
||||