mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-28 22:31:22 -05:00
gear selector
This commit is contained in:
30
components/common/ChakraSelect.tsx
Normal file
30
components/common/ChakraSelect.tsx
Normal 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;
|
||||
52
components/common/GearSelector.tsx
Normal file
52
components/common/GearSelector.tsx
Normal 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;
|
||||
@@ -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}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user