mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-04-24 06:58:10 -05:00
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:
parent
e5b9a6ccb3
commit
668b2d73e7
|
|
@ -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>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
46
utils/selectStyles.ts
Normal 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;
|
||||
Loading…
Reference in New Issue
Block a user