gear selector

This commit is contained in:
Kalle (Sendou)
2020-12-17 15:00:31 +02:00
parent ca93b0de7b
commit 07197e662e
4 changed files with 103 additions and 49 deletions

View File

@@ -0,0 +1,30 @@
import { Select } from "@chakra-ui/react";
interface Props {
value: string;
setValue: (value?: string) => void;
placeholder?: string;
name?: string;
children: React.ReactNode;
}
const ChakraSelect: React.FC<Props> = ({
value,
setValue,
placeholder,
children,
name,
}) => (
<Select
value={value ?? ""}
onChange={(e) =>
setValue(e.target.value === "" ? undefined : e.target.value)
}
name={name}
>
{placeholder && <option value="">{placeholder}</option>}
{children}
</Select>
);
export default ChakraSelect;

View File

@@ -0,0 +1,52 @@
import { Box, Flex } from "@chakra-ui/react";
import { useLingui } from "@lingui/react";
import { gear } from "lib/lists/gear";
import { components } from "react-select";
import GearImage from "./GearImage";
import MySelect from "./MySelect";
interface WeaponSelectorProps {
value?: string;
setValue: (value: string) => void;
slot: "head" | "clothing" | "shoes";
}
const GearSelector: React.FC<WeaponSelectorProps> = ({
value,
setValue,
slot,
}) => {
const { i18n } = useLingui();
const singleOption = (props: any) => (
<components.Option {...props}>
<Flex alignItems="center" color={props.isFocused ? "black" : undefined}>
<Box mr="0.5em">
<GearImage mini englishName={props.value} />
</Box>
{props.label}
</Flex>
</components.Option>
);
return (
<MySelect
options={gear.map((category) => ({
label: i18n._(category.brand),
options: category[slot].map((gear) => ({
value: gear,
label: i18n._(gear),
})),
}))}
value={value ? { value, label: i18n._(value) } : undefined}
setValue={setValue}
isClearable
isSearchable
components={{
IndicatorSeparator: () => null,
Option: singleOption,
}}
/>
);
};
export default GearSelector;

View File

@@ -15,7 +15,6 @@ import {
ModalFooter,
ModalHeader,
ModalOverlay,
Select,
Stack,
Textarea,
useToast,
@@ -24,9 +23,9 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { t, Trans } from "@lingui/macro";
import { Ability } from "@prisma/client";
import ViewSlots from "components/builds/ViewSlots";
import GearSelector from "components/common/GearSelector";
import WeaponSelector from "components/common/WeaponSelector";
import { getToastOptions } from "lib/getToastOptions";
import { gear } from "lib/lists/gear";
import { sendData } from "lib/postData";
import { Unpacked } from "lib/types";
import useUser from "lib/useUser";
@@ -36,7 +35,7 @@ import {
TITLE_CHARACTER_LIMIT,
} from "lib/validators/build";
import { GetBuildsByUserData } from "prisma/queries/getBuildsByUser";
import { Fragment, useState } from "react";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { FiTrash } from "react-icons/fi";
import { mutate } from "swr";
@@ -297,18 +296,7 @@ const BuildModal: React.FC<Props> = ({ onClose, build }) => {
control={control}
defaultValue=""
render={({ onChange, value, name }) => (
<Select name={name} value={value} setValue={onChange}>
{gear.map(({ brand, head }) => (
<Fragment key={brand}>
<optgroup>{brand}</optgroup>
{head.map((item) => (
<option key={item} value={item}>
{item}
</option>
))}
</Fragment>
))}
</Select>
<GearSelector slot="head" value={value} setValue={onChange} />
)}
/>
@@ -319,19 +307,12 @@ const BuildModal: React.FC<Props> = ({ onClose, build }) => {
name="clothingGear"
control={control}
defaultValue=""
render={({ onChange, value, name }) => (
<Select name={name} value={value} setValue={onChange}>
{gear.map(({ brand, clothing }) => (
<Fragment key={brand}>
<optgroup>{brand}</optgroup>
{clothing.map((item) => (
<option key={item} value={item}>
{item}
</option>
))}
</Fragment>
))}
</Select>
render={({ onChange, value }) => (
<GearSelector
slot="clothing"
value={value}
setValue={onChange}
/>
)}
/>
@@ -343,20 +324,11 @@ const BuildModal: React.FC<Props> = ({ onClose, build }) => {
control={control}
defaultValue=""
render={({ onChange, value, name }) => (
<Select name={name} value={value} setValue={onChange}>
{gear
.filter((brand) => brand.shoes.length > 0)
.map(({ brand, shoes }) => (
<Fragment key={brand}>
<optgroup>{brand}</optgroup>
{shoes.map((item) => (
<option key={item} value={item}>
{item}
</option>
))}
</Fragment>
))}
</Select>
<GearSelector
slot="shoes"
value={value}
setValue={onChange}
/>
)}
/>

View File

@@ -19,9 +19,9 @@ import {
import { zodResolver } from "@hookform/resolvers/zod";
import { t, Trans } from "@lingui/macro";
import { useLingui } from "@lingui/react";
import ChakraSelect from "components/common/ChakraSelect";
import MarkdownTextarea from "components/common/MarkdownTextarea";
import WeaponSelector from "components/common/MultiWeaponSelector";
import MySelect from "components/common/MySelect";
import { countries } from "countries-list";
import { getToastOptions } from "lib/getToastOptions";
import { sendData } from "lib/postData";
@@ -230,7 +230,7 @@ const ProfileModal: React.FC<Props> = ({ onClose, user }) => {
control={control}
defaultValue={""}
render={({ onChange, value }) => (
<MySelect
<ChakraSelect
value={value}
setValue={onChange}
placeholder={t`Select country`}
@@ -242,7 +242,7 @@ const ProfileModal: React.FC<Props> = ({ onClose, user }) => {
{countries[countryCode].name}
</option>
))}
</MySelect>
</ChakraSelect>
)}
/>
@@ -270,7 +270,7 @@ const ProfileModal: React.FC<Props> = ({ onClose, user }) => {
name="sensStick"
control={control}
render={({ onChange, value, name }) => (
<MySelect
<ChakraSelect
placeholder={t`Select stick sensitivity`}
name={name}
value={value}
@@ -281,7 +281,7 @@ const ProfileModal: React.FC<Props> = ({ onClose, user }) => {
{sens}
</option>
))}
</MySelect>
</ChakraSelect>
)}
/>
@@ -293,7 +293,7 @@ const ProfileModal: React.FC<Props> = ({ onClose, user }) => {
name="sensMotion"
control={control}
render={({ onChange, value, name }) => (
<MySelect
<ChakraSelect
placeholder={t`Select motion sensitivity`}
name={name}
value={value}
@@ -304,7 +304,7 @@ const ProfileModal: React.FC<Props> = ({ onClose, user }) => {
{sens}
</option>
))}
</MySelect>
</ChakraSelect>
)}
/>