New filters for builds page (#523)

* new filter for modes

* new filter for abilities

* prettifier

* fix imports

* fix margin + some things from pull request

* better fix for select

* MySelect default style + styles for selects on builds page.

* Remove duplicates, import default style from file
This commit is contained in:
Igor 2021-05-28 17:10:50 +03:00 committed by GitHub
parent e5b9a6ccb3
commit 668b2d73e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 220 additions and 126 deletions

View File

@ -9,7 +9,6 @@ import {
NumberInputField,
NumberInputStepper,
Radio,
Select,
} from "@chakra-ui/react";
import { t, Trans } from "@lingui/macro";
import { Ability, Mode } from "@prisma/client";
@ -22,15 +21,135 @@ import { useMyTheme } from "hooks/common";
import { Fragment, useState } from "react";
import { FiTrash } from "react-icons/fi";
import { abilities, isMainAbility } from "utils/lists/abilities";
import { components } from "react-select";
import ModeImage from "components/common/ModeImage";
import MySelect from "components/common/MySelect";
import defaultStyles from "utils/selectStyles";
interface Props {
filters: UseBuildsByWeaponState["filters"];
dispatch: UseBuildsByWeaponDispatch;
}
const modeOptions = [
{
label: "All modes",
value: "ALL",
},
{
label: "Splat Zones",
value: "SZ",
},
{
label: "Tower Control",
value: "TC",
},
{
label: "Rainmaker",
value: "RM",
},
{
label: "Clam Blitz",
value: "CB",
},
{
label: "Turf War",
value: "TW",
},
] as const;
const abilitiesOptions = abilities.map((item) => {
return { label: item.name, value: item.code };
});
const ModeOption = (props: any) => {
return (
<components.Option {...props}>
<Flex alignItems="center">
<Box mr="0.5em">
{props.value !== "ALL" ? (
<ModeImage size={20} mode={props.value} />
) : (
<></>
)}
</Box>
{props.label}
</Flex>
</components.Option>
);
};
const AbilityOption = (props: any) => {
return (
<components.Option {...props}>
<Flex alignItems="center">
<Box mr="0.5em">
<AbilityIcon ability={props.value} size="SUBTINY" />
</Box>
{props.label}
</Flex>
</components.Option>
);
};
const ModeSingleValue = (props: any) => {
return (
<components.SingleValue {...props}>
{props.data.value !== "ALL" ? (
<Box mr="0.5em">
<ModeImage size={20} mode={props.data.value} />
</Box>
) : (
<></>
)}
{props.data.label}
</components.SingleValue>
);
};
const BuildFilters: React.FC<Props> = ({ filters, dispatch }) => {
const [modeValueChanged, setModeValueChanged] = useState(false);
const { gray } = useMyTheme();
const [mode, setMode] = useState<{ label: string; value: string }>(
modeOptions[0]
);
const {
borderColor,
themeColorOpaque,
textColor,
gray
} = useMyTheme();
const selectDefaultStyles = defaultStyles();
const selectStyles = {
...selectDefaultStyles,
singleValue: (base: any) => ({
...base,
padding: 0,
borderRadius: 5,
color: textColor,
fontSize: '0.875rem',
display: "flex",
}),
option: (styles: any, {isFocused}: any) => {
return {
...styles,
backgroundColor: isFocused ? themeColorOpaque : undefined,
fontSize: '0.875rem',
color: textColor,
};
},
control: (base: any) => ({
...base,
borderColor,
minHeight: 32,
height: 32,
background: "hsla(0, 0%, 0%, 0)",
}),
dropdownIndicator: (base: any) => ({
...base,
padding: 4
}),
};
return (
<>
@ -171,58 +290,49 @@ const BuildFilters: React.FC<Props> = ({ filters, dispatch }) => {
align="center"
flexDir={["column", "row"]}
>
<Select
onChange={(e) =>
dispatch({
type: "ADD_FILTER",
ability: e.target.value as Ability,
})
}
size="sm"
width={48}
m={2}
>
<option hidden value="NO_VALUE">
{t`Filter by ability`}
</option>
{abilities
.filter(
(ability) =>
!filters.some((filter) => ability.code === filter.ability)
)
.map((ability) => (
<option key={ability.code} value={ability.code}>
{ability.name}
</option>
))}
</Select>
<Select
onChange={(e) => {
setModeValueChanged(true);
dispatch({
type: "SET_MODE_FILTER",
modeFilter:
e.target.value === "ALL" ? undefined : (e.target.value as Mode),
});
}}
size="sm"
width={48}
m={2}
>
<option hidden value="NO_VALUE">
{t`Filter by mode`}
</option>
{[t`All modes`, "TW", "SZ", "TC", "RM", "CB"]
// let's filter out all modes initially
// to avoid confusion as it does nothing different from
// having nothing selected at all
.filter((_, i) => modeValueChanged || i !== 0)
.map((mode, i) => (
<option key={mode} value={i === 0 ? "ALL" : mode}>
{mode}
</option>
))}
</Select>
<Box minW={200} m="2">
<MySelect
name="filter by ability"
isMulti={false}
value={{ label: "Filter by ability", value: "DEFAULT" }}
options={abilitiesOptions.filter((option) => {
return !filters.find(
(filterElement) => filterElement.ability === option.value
);
})}
setValue={(value) => {
dispatch({
type: "ADD_FILTER",
ability: value as Ability,
});
}}
components={{
Option: AbilityOption,
}}
styles={selectStyles}
/>
</Box>
<Box minW={200} m="2">
<MySelect
name="filter by mode"
isMulti={false}
value={mode}
options={modeOptions}
setValue={(value) => {
const mode = modeOptions.find((option) => option.value === value);
if (mode) setMode(mode);
dispatch({
type: "SET_MODE_FILTER",
modeFilter: value === "ALL" ? undefined : (value as Mode),
});
}}
components={{
Option: ModeOption,
SingleValue: ModeSingleValue,
}}
styles={selectStyles}
/>
</Box>
</Flex>
</>
);

View File

@ -3,7 +3,7 @@ import { CSSProperties } from "react";
interface ModeImageProps {
mode: "TW" | "SZ" | "TC" | "RM" | "CB";
size?: 24 | 32 | 64 | 128;
size?: 20 | 24 | 32 | 64 | 128;
onClick?: () => void;
style?: CSSProperties;
}

View File

@ -11,6 +11,7 @@ import ReactSelect, {
import { SelectComponents } from "react-select/src/components";
import { Box, Flex } from "@chakra-ui/react";
import ModeImage from "./ModeImage";
import defaultStyles from "utils/selectStyles";
interface SelectProps {
options?:
@ -70,14 +71,12 @@ const MultipleModeSelector: React.FC<SelectProps> = ({
defaultValue,
}) => {
const {
borderColor,
themeColorHex,
bgColor,
themeColorOpaque,
textColor,
} = useMyTheme();
const [inputValue, setInputValue] = useState("");
const [selectedModes, setSelectedModes] = useState(defaultValue);
const selectDefaultStyles = defaultStyles();
const handleChange = (selectedOption: any) => {
if (!selectedOption) {
@ -144,38 +143,7 @@ const MultipleModeSelector: React.FC<SelectProps> = ({
neutral5: bgColor,
},
})}
styles={{
singleValue: (base) => ({
...base,
padding: 5,
borderRadius: 5,
color: textColor,
display: "flex",
}),
input: (base) => ({
...base,
color: textColor,
}),
multiValue: (base) => ({
...base,
background: themeColorHex,
color: "black",
}),
option: (styles, { isFocused }) => {
return {
...styles,
backgroundColor: isFocused ? themeColorOpaque : undefined,
color: textColor,
};
},
menu: (styles) => ({ ...styles, zIndex: 999 }),
control: (base) => ({
...base,
borderColor,
minHeight: "2.5rem",
background: "hsla(0, 0%, 0%, 0)",
}),
}}
styles={selectDefaultStyles}
/>
);
};

View File

@ -9,6 +9,7 @@ import ReactSelect, {
ValueType,
} from "react-select";
import { SelectComponents } from "react-select/src/components";
import defaultStyles from "utils/selectStyles";
interface SelectProps {
options?:
@ -36,6 +37,7 @@ interface SelectProps {
menuIsOpen?: boolean;
hideMenuBeforeTyping?: boolean;
customFilterOption?: (option: any, rawInput: string) => boolean;
styles?: any;
}
const DropdownIndicator = (props: any) => {
@ -62,15 +64,14 @@ const MySelect: React.FC<SelectProps> = ({
menuIsOpen = false,
hideMenuBeforeTyping,
customFilterOption,
styles
}) => {
const {
borderColor,
themeColorHex,
bgColor,
themeColorOpaque,
textColor,
} = useMyTheme();
const [inputValue, setInputValue] = useState("");
const selectDefaultStyles = defaultStyles();
const handleChange = (selectedOption: any) => {
if (!selectedOption) {
@ -136,38 +137,7 @@ const MySelect: React.FC<SelectProps> = ({
},
})}
autoFocus={autoFocus}
styles={{
singleValue: (base) => ({
...base,
padding: 5,
borderRadius: 5,
color: textColor,
display: "flex",
}),
input: (base) => ({
...base,
color: textColor,
}),
multiValue: (base) => ({
...base,
background: themeColorHex,
color: "black",
}),
option: (styles, { isFocused }) => {
return {
...styles,
backgroundColor: isFocused ? themeColorOpaque : undefined,
color: textColor,
};
},
menu: (styles) => ({ ...styles, zIndex: 999 }),
control: (base) => ({
...base,
borderColor,
minHeight: "2.5rem",
background: "hsla(0, 0%, 0%, 0)",
}),
}}
styles={ styles ? styles : selectDefaultStyles}
/>
);
};

46
utils/selectStyles.ts Normal file
View File

@ -0,0 +1,46 @@
import { useMyTheme } from "../hooks/common";
const defaultStyles = () => {
const {
borderColor,
themeColorHex,
themeColorOpaque,
textColor,
} = useMyTheme();
return {
singleValue: (base: any) => ({
...base,
padding: 5,
borderRadius: 5,
color: textColor,
display: "flex",
}),
input: (base: any) => ({
...base,
color: textColor,
}),
multiValue: (base: any) => ({
...base,
background: themeColorHex,
color: "black",
}),
option: (styles: any, {isFocused}: any) => {
return {
...styles,
backgroundColor: isFocused ? themeColorOpaque : undefined,
color: textColor,
};
},
menu: (styles: any) => ({...styles, zIndex: 999}),
control: (base: any) => ({
...base,
borderColor,
minHeight: "2.5rem",
background: "hsla(0, 0%, 0%, 0)",
}),
};
};
export default defaultStyles;