mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
public tag submit form
This commit is contained in:
@@ -3,12 +3,12 @@ import React from 'react';
|
||||
|
||||
import PageNextJs from 'nextjs/PageNextJs';
|
||||
|
||||
// import PublicTagsSubmit from 'ui/pages/PublicTagsSubmit';
|
||||
import PublicTagsSubmit from 'ui/pages/PublicTagsSubmit';
|
||||
|
||||
const Page: NextPage = () => {
|
||||
return (
|
||||
<PageNextJs pathname="/public-tags/submit">
|
||||
{ /* <PublicTagsSubmit/> */ }
|
||||
<PublicTagsSubmit/>
|
||||
</PageNextJs>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button, chakra, Grid, GridItem } from '@chakra-ui/react';
|
||||
import { chakra, Grid, GridItem } from '@chakra-ui/react';
|
||||
import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
import type { SubmitHandler } from 'react-hook-form';
|
||||
@@ -13,6 +13,7 @@ import useApiFetch from 'lib/api/useApiFetch';
|
||||
import getErrorObj from 'lib/errors/getErrorObj';
|
||||
import getErrorObjPayload from 'lib/errors/getErrorObjPayload';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import { Button } from 'toolkit/chakra/button';
|
||||
import FormFieldEmail from 'ui/shared/forms/fields/FormFieldEmail';
|
||||
import FormFieldText from 'ui/shared/forms/fields/FormFieldText';
|
||||
import FormFieldUrl from 'ui/shared/forms/fields/FormFieldUrl';
|
||||
@@ -84,10 +85,6 @@ const PublicTagsSubmitForm = ({ config, userInfo, onSubmitResult }: Props) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fieldProps = {
|
||||
size: { base: 'md', lg: 'lg' },
|
||||
};
|
||||
|
||||
return (
|
||||
<FormProvider { ...formApi }>
|
||||
<chakra.form
|
||||
@@ -102,12 +99,12 @@ const PublicTagsSubmitForm = ({ config, userInfo, onSubmitResult }: Props) => {
|
||||
<GridItem colSpan={{ base: 1, lg: 3 }} as="h2" textStyle="h4">
|
||||
Company info
|
||||
</GridItem>
|
||||
<FormFieldText<FormFields> name="requesterName" isRequired placeholder="Your name" { ...fieldProps }/>
|
||||
<FormFieldEmail<FormFields> name="requesterEmail" isRequired { ...fieldProps }/>
|
||||
<FormFieldText<FormFields> name="requesterName" required placeholder="Your name"/>
|
||||
<FormFieldEmail<FormFields> name="requesterEmail" required/>
|
||||
|
||||
{ !isMobile && <div/> }
|
||||
<FormFieldText<FormFields> name="companyName" placeholder="Company name" { ...fieldProps }/>
|
||||
<FormFieldUrl<FormFields> name="companyWebsite" placeholder="Company website" { ...fieldProps }/>
|
||||
<FormFieldText<FormFields> name="companyName" placeholder="Company name"/>
|
||||
<FormFieldUrl<FormFields> name="companyWebsite" placeholder="Company website"/>
|
||||
{ !isMobile && <div/> }
|
||||
|
||||
<GridItem colSpan={{ base: 1, lg: 3 }} as="h2" textStyle="h4" mt={{ base: 3, lg: 5 }}>
|
||||
@@ -119,7 +116,7 @@ const PublicTagsSubmitForm = ({ config, userInfo, onSubmitResult }: Props) => {
|
||||
<GridItem colSpan={{ base: 1, lg: 2 }}>
|
||||
<FormFieldText<FormFields>
|
||||
name="description"
|
||||
isRequired
|
||||
required
|
||||
placeholder={
|
||||
isMobile ?
|
||||
'Confirm the connection between addresses and tags.' :
|
||||
@@ -128,7 +125,7 @@ const PublicTagsSubmitForm = ({ config, userInfo, onSubmitResult }: Props) => {
|
||||
maxH="160px"
|
||||
rules={{ maxLength: 80 }}
|
||||
asComponent="Textarea"
|
||||
{ ...fieldProps }
|
||||
size="2xl"
|
||||
/>
|
||||
</GridItem>
|
||||
|
||||
@@ -141,7 +138,7 @@ const PublicTagsSubmitForm = ({ config, userInfo, onSubmitResult }: Props) => {
|
||||
size="lg"
|
||||
type="submit"
|
||||
mt={ 3 }
|
||||
isLoading={ formApi.formState.isSubmitting }
|
||||
loading={ formApi.formState.isSubmitting }
|
||||
loadingText="Send request"
|
||||
w="min-content"
|
||||
>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Alert, Box, Button, Flex, Grid, GridItem } from '@chakra-ui/react';
|
||||
import { Box, Flex, Grid, GridItem } from '@chakra-ui/react';
|
||||
import { pickBy } from 'es-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
@@ -7,7 +7,9 @@ import type { FormSubmitResult } from './types';
|
||||
import { route } from 'nextjs-routes';
|
||||
|
||||
import makePrettyLink from 'lib/makePrettyLink';
|
||||
import LinkExternal from 'ui/shared/links/LinkExternal';
|
||||
import { Alert } from 'toolkit/chakra/alert';
|
||||
import { Button } from 'toolkit/chakra/button';
|
||||
import { Link } from 'toolkit/chakra/link';
|
||||
|
||||
import PublicTagsSubmitResultSuccess from './result/PublicTagsSubmitResultSuccess';
|
||||
import PublicTagsSubmitResultWithErrors from './result/PublicTagsSubmitResultWithErrors';
|
||||
@@ -57,7 +59,7 @@ const PublicTagsSubmitResult = ({ data }: Props) => {
|
||||
<>
|
||||
<GridItem>Company website</GridItem>
|
||||
<GridItem>
|
||||
<LinkExternal href={ companyWebsite.url }>{ companyWebsite.domain }</LinkExternal>
|
||||
<Link external href={ companyWebsite.url }>{ companyWebsite.domain }</Link>
|
||||
</GridItem>
|
||||
</>
|
||||
) }
|
||||
@@ -68,11 +70,15 @@ const PublicTagsSubmitResult = ({ data }: Props) => {
|
||||
|
||||
<Flex flexDir={{ base: 'column', lg: 'row' }} columnGap={ 6 } mt={ 8 } rowGap={ 3 }>
|
||||
{ hasErrors && (
|
||||
<Button size="lg" variant="outline" as="a" href={ route({ pathname: '/public-tags/submit', query: startOverButtonQuery }) }>
|
||||
Start over
|
||||
</Button>
|
||||
<Link href={ route({ pathname: '/public-tags/submit', query: startOverButtonQuery }) } asChild>
|
||||
<Button size="lg" variant="outline">
|
||||
Start over
|
||||
</Button>
|
||||
</Link>
|
||||
) }
|
||||
<Button size="lg" as="a" href={ route({ pathname: '/public-tags/submit' }) }>Add new tag</Button>
|
||||
<Link href={ route({ pathname: '/public-tags/submit' }) } asChild>
|
||||
<Button size="lg">Add new tag</Button>
|
||||
</Link>
|
||||
</Flex>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { GridItem, IconButton } from '@chakra-ui/react';
|
||||
import { GridItem } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||
|
||||
import type { FormFields } from '../types';
|
||||
|
||||
import { IconButton } from 'toolkit/chakra/icon-button';
|
||||
import FormFieldAddress from 'ui/shared/forms/fields/FormFieldAddress';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
@@ -40,9 +41,8 @@ const PublicTagsSubmitFieldAddresses = () => {
|
||||
<GridItem colSpan={{ base: 1, lg: 2 }}>
|
||||
<FormFieldAddress<FormFields>
|
||||
name={ `addresses.${ index }.hash` }
|
||||
isRequired
|
||||
required
|
||||
placeholder="Smart contract / Address (0x...)"
|
||||
size={{ base: 'md', lg: 'lg' }}
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem display="flex" alignItems="center" columnGap={ 5 } justifyContent={{ base: 'flex-end', lg: 'flex-start' }}>
|
||||
@@ -53,9 +53,10 @@ const PublicTagsSubmitFieldAddresses = () => {
|
||||
variant="outline"
|
||||
boxSize="30px"
|
||||
onClick={ handleAddFieldClick }
|
||||
icon={ <IconSvg name="plus" boxSize={ 5 }/> }
|
||||
isDisabled={ isDisabled }
|
||||
/>
|
||||
disabled={ isDisabled }
|
||||
>
|
||||
<IconSvg name="plus" boxSize={ 5 }/>
|
||||
</IconButton>
|
||||
) }
|
||||
{ fields.length > 1 && (
|
||||
<IconButton
|
||||
@@ -64,9 +65,10 @@ const PublicTagsSubmitFieldAddresses = () => {
|
||||
variant="outline"
|
||||
boxSize="30px"
|
||||
onClick={ handleRemoveFieldClick }
|
||||
icon={ <IconSvg name="minus" boxSize={ 5 }/> }
|
||||
isDisabled={ isDisabled }
|
||||
/>
|
||||
disabled={ isDisabled }
|
||||
>
|
||||
<IconSvg name="minus" boxSize={ 5 }/>
|
||||
</IconButton>
|
||||
) }
|
||||
</GridItem>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { chakra, Flex, Grid, GridItem, IconButton, useColorModeValue } from '@chakra-ui/react';
|
||||
import { chakra, Flex, Grid, GridItem } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import { type FieldError, type FieldErrorsImpl, type Merge } from 'react-hook-form';
|
||||
|
||||
@@ -6,15 +6,21 @@ import type { FormFields, FormFieldTag } from '../types';
|
||||
import type { PublicTagType } from 'types/api/addressMetadata';
|
||||
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import { IconButton } from 'toolkit/chakra/icon-button';
|
||||
import EntityTag from 'ui/shared/EntityTags/EntityTag';
|
||||
import FormFieldColor from 'ui/shared/forms/fields/FormFieldColor';
|
||||
import FormFieldText from 'ui/shared/forms/fields/FormFieldText';
|
||||
import FormFieldUrl from 'ui/shared/forms/fields/FormFieldUrl';
|
||||
import { validator as colorValidator } from 'ui/shared/forms/validators/color';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
import PublicTagsSubmitFieldTagColor from './PublicTagsSubmitFieldTagColor';
|
||||
import PublicTagsSubmitFieldTagType from './PublicTagsSubmitFieldTagType';
|
||||
|
||||
const CIRCLE_BG_COLOR_DEFAULT = {
|
||||
bgColor: { _light: 'gray.100', _dark: 'gray.700' },
|
||||
textColor: { _light: 'blackAlpha.800', _dark: 'whiteAlpha.800' },
|
||||
};
|
||||
|
||||
interface Props {
|
||||
index: number;
|
||||
field: FormFieldTag;
|
||||
@@ -27,8 +33,8 @@ interface Props {
|
||||
|
||||
const PublicTagsSubmitFieldTag = ({ index, isDisabled, errors, onAddClick, onRemoveClick, tagTypes, field }: Props) => {
|
||||
const isMobile = useIsMobile();
|
||||
const bgColorDefault = useColorModeValue('blackAlpha.50', 'whiteAlpha.100');
|
||||
const bgColorError = useColorModeValue('red.50', 'red.900');
|
||||
const bgColorDefault = { _light: 'blackAlpha.50', _dark: 'whiteAlpha.100' };
|
||||
const bgColorError = { _light: 'red.50', _dark: 'red.900' };
|
||||
|
||||
const handleAddClick = React.useCallback(() => {
|
||||
onAddClick?.(index);
|
||||
@@ -38,10 +44,6 @@ const PublicTagsSubmitFieldTag = ({ index, isDisabled, errors, onAddClick, onRem
|
||||
onRemoveClick?.(index);
|
||||
}, [ index, onRemoveClick ]);
|
||||
|
||||
const fieldProps = {
|
||||
size: { base: 'md', lg: 'lg' },
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<GridItem colSpan={{ base: 1, lg: 2 }} p="10px" borderRadius="base" bgColor={ errors ? bgColorError : bgColorDefault }>
|
||||
@@ -54,9 +56,8 @@ const PublicTagsSubmitFieldTag = ({ index, isDisabled, errors, onAddClick, onRem
|
||||
<FormFieldText<FormFields>
|
||||
name={ `tags.${ index }.name` }
|
||||
placeholder="Tag (max 35 characters)"
|
||||
isRequired
|
||||
required
|
||||
rules={{ maxLength: 35 }}
|
||||
{ ...fieldProps }
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem colSpan={{ base: 1, lg: 2 }}>
|
||||
@@ -66,20 +67,17 @@ const PublicTagsSubmitFieldTag = ({ index, isDisabled, errors, onAddClick, onRem
|
||||
<FormFieldUrl<FormFields>
|
||||
name={ `tags.${ index }.url` }
|
||||
placeholder="Label URL"
|
||||
{ ...fieldProps }
|
||||
/>
|
||||
</GridItem>
|
||||
<PublicTagsSubmitFieldTagColor
|
||||
fieldType="bgColor"
|
||||
fieldName={ `tags.${ index }.bgColor` }
|
||||
<FormFieldColor<FormFields>
|
||||
name={ `tags.${ index }.bgColor` }
|
||||
placeholder="Background (Hex)"
|
||||
error={ errors?.bgColor }
|
||||
sampleDefaultBgColor={ CIRCLE_BG_COLOR_DEFAULT.bgColor }
|
||||
/>
|
||||
<PublicTagsSubmitFieldTagColor
|
||||
fieldType="textColor"
|
||||
fieldName={ `tags.${ index }.textColor` }
|
||||
<FormFieldColor<FormFields>
|
||||
name={ `tags.${ index }.textColor` }
|
||||
placeholder="Text (Hex)"
|
||||
error={ errors?.textColor }
|
||||
sampleDefaultBgColor={ CIRCLE_BG_COLOR_DEFAULT.textColor }
|
||||
/>
|
||||
<GridItem colSpan={{ base: 1, lg: 4 }}>
|
||||
<FormFieldText<FormFields>
|
||||
@@ -88,7 +86,6 @@ const PublicTagsSubmitFieldTag = ({ index, isDisabled, errors, onAddClick, onRem
|
||||
maxH="160px"
|
||||
rules={{ maxLength: 80 }}
|
||||
asComponent="Textarea"
|
||||
{ ...fieldProps }
|
||||
/>
|
||||
</GridItem>
|
||||
</Grid>
|
||||
@@ -107,9 +104,10 @@ const PublicTagsSubmitFieldTag = ({ index, isDisabled, errors, onAddClick, onRem
|
||||
variant="outline"
|
||||
boxSize="30px"
|
||||
onClick={ handleAddClick }
|
||||
icon={ <IconSvg name="plus" boxSize={ 5 }/> }
|
||||
isDisabled={ isDisabled }
|
||||
/>
|
||||
disabled={ isDisabled }
|
||||
>
|
||||
<IconSvg name="plus" boxSize={ 5 }/>
|
||||
</IconButton>
|
||||
) }
|
||||
{ onRemoveClick && (
|
||||
<IconButton
|
||||
@@ -118,16 +116,17 @@ const PublicTagsSubmitFieldTag = ({ index, isDisabled, errors, onAddClick, onRem
|
||||
variant="outline"
|
||||
boxSize="30px"
|
||||
onClick={ handleRemoveClick }
|
||||
icon={ <IconSvg name="minus" boxSize={ 5 }/> }
|
||||
isDisabled={ isDisabled }
|
||||
/>
|
||||
disabled={ isDisabled }
|
||||
>
|
||||
<IconSvg name="minus" boxSize={ 5 }/>
|
||||
</IconButton>
|
||||
) }
|
||||
</Flex>
|
||||
{ !isMobile && (
|
||||
<Flex flexDir="column" alignItems="flex-start" mt={ 10 } rowGap={ 2 }>
|
||||
<EntityTag data={{
|
||||
name: field.name || 'Tag name',
|
||||
tagType: field.type.value,
|
||||
tagType: field.type[0].value,
|
||||
meta: {
|
||||
tagUrl: field.url,
|
||||
bgColor: field.bgColor && colorValidator(field.bgColor) === true ? field.bgColor : undefined,
|
||||
@@ -138,7 +137,7 @@ const PublicTagsSubmitFieldTag = ({ index, isDisabled, errors, onAddClick, onRem
|
||||
ordinal: 0,
|
||||
}}/>
|
||||
<chakra.span color="text_secondary" fontSize="sm">
|
||||
{ tagTypes?.find(({ type }) => type === field.type.value)?.description }
|
||||
{ tagTypes?.find(({ type }) => type === field.type[0].value)?.description }
|
||||
</chakra.span>
|
||||
</Flex>
|
||||
) }
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
import { Circle, FormControl, Input, InputGroup, InputRightElement, useColorModeValue } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import { useFormContext, type FieldError } from 'react-hook-form';
|
||||
|
||||
import type { FormFields } from '../types';
|
||||
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import FormInputPlaceholder from 'ui/shared/forms/inputs/FormInputPlaceholder';
|
||||
import { validator as colorValidator } from 'ui/shared/forms/validators/color';
|
||||
|
||||
type ColorFieldTypes = 'bgColor' | 'textColor';
|
||||
|
||||
interface Props<Type extends ColorFieldTypes> {
|
||||
fieldType: Type;
|
||||
fieldName: `tags.${ number }.${ Type }`;
|
||||
error: FieldError | undefined;
|
||||
placeholder: string;
|
||||
}
|
||||
|
||||
const PublicTagsSubmitFieldTagColor = <Type extends ColorFieldTypes>({ error, fieldName, placeholder, fieldType }: Props<Type>) => {
|
||||
const { register, formState } = useFormContext<FormFields>();
|
||||
|
||||
const isDisabled = formState.isSubmitting;
|
||||
|
||||
const circleBgColorDefault = {
|
||||
bgColor: useColorModeValue('gray.100', 'gray.700'),
|
||||
textColor: useColorModeValue('blackAlpha.800', 'whiteAlpha.800'),
|
||||
};
|
||||
const isMobile = useIsMobile();
|
||||
const field = register(fieldName, { validate: colorValidator, maxLength: 7 });
|
||||
const [ value, setValue ] = React.useState('');
|
||||
|
||||
const handleChange = React.useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const nextValue = (() => {
|
||||
const value = event.target.value;
|
||||
if (value) {
|
||||
if (value.length === 1 && value[0] !== '#') {
|
||||
return `#${ value }`;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
})();
|
||||
setValue(nextValue);
|
||||
field.onChange(event);
|
||||
}, [ field ]);
|
||||
|
||||
return (
|
||||
<FormControl variant="floating" size={{ base: 'md', lg: 'lg' }}>
|
||||
<InputGroup size={ isMobile ? 'md' : 'lg' }>
|
||||
<Input
|
||||
{ ...field }
|
||||
onChange={ handleChange }
|
||||
value={ value }
|
||||
isInvalid={ Boolean(error) }
|
||||
isDisabled={ isDisabled }
|
||||
autoComplete="off"
|
||||
maxLength={ 7 }
|
||||
/>
|
||||
<FormInputPlaceholder text={ placeholder } error={ error }/>
|
||||
<InputRightElement w="30px" h="auto" right={ 4 } top="50%" transform="translateY(-50%)" zIndex={ 10 }>
|
||||
<Circle
|
||||
size="30px"
|
||||
bgColor={ value && colorValidator(value) === true ? value : circleBgColorDefault[fieldType] }
|
||||
borderColor="gray.300"
|
||||
borderWidth="1px"
|
||||
/>
|
||||
</InputRightElement>
|
||||
</InputGroup>
|
||||
</FormControl>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(PublicTagsSubmitFieldTagColor);
|
||||
@@ -1,16 +1,13 @@
|
||||
import { chakra, Flex } from '@chakra-ui/react';
|
||||
import { createListCollection } from '@chakra-ui/react';
|
||||
import { capitalize } from 'es-toolkit';
|
||||
import React from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
// import { useFormContext } from 'react-hook-form';
|
||||
|
||||
import type { FormFields } from '../types';
|
||||
import type { PublicTagType } from 'types/api/addressMetadata';
|
||||
import type { Option } from 'ui/shared/forms/inputs/select/types';
|
||||
|
||||
import { chakraComponents } from 'chakra-react-select';
|
||||
import type { GroupBase, SelectComponentsConfig, SingleValueProps } from 'chakra-react-select';
|
||||
import FormFieldFancySelect from 'ui/shared/forms/fields/FormFieldFancySelect';
|
||||
import IconSvg from 'ui/shared/IconSvg';
|
||||
import FormFieldSelect from 'ui/shared/forms/fields/FormFieldSelect';
|
||||
// import IconSvg from 'ui/shared/IconSvg';
|
||||
|
||||
interface Props {
|
||||
index: number;
|
||||
@@ -18,56 +15,58 @@ interface Props {
|
||||
}
|
||||
|
||||
const PublicTagsSubmitFieldTagType = ({ index, tagTypes }: Props) => {
|
||||
const { watch } = useFormContext<FormFields>();
|
||||
// const { watch } = useFormContext<FormFields>();
|
||||
|
||||
const typeOptions = React.useMemo(() => tagTypes?.map((type) => ({
|
||||
value: type.type,
|
||||
label: capitalize(type.type),
|
||||
})) ?? [], [ tagTypes ]);
|
||||
const collection = React.useMemo(() => {
|
||||
const items = tagTypes?.map((type) => ({
|
||||
value: type.type,
|
||||
label: capitalize(type.type),
|
||||
})) ?? [];
|
||||
|
||||
const fieldValue = watch(`tags.${ index }.type`).value;
|
||||
return createListCollection({ items });
|
||||
}, [ tagTypes ]);
|
||||
|
||||
const selectComponents: SelectComponentsConfig<Option, boolean, GroupBase<Option>> = React.useMemo(() => {
|
||||
type SingleValueComponentProps = SingleValueProps<Option, boolean, GroupBase<Option>> & { children: React.ReactNode };
|
||||
const SingleValue = ({ children, ...props }: SingleValueComponentProps) => {
|
||||
switch (fieldValue) {
|
||||
case 'name': {
|
||||
return (
|
||||
<chakraComponents.SingleValue { ...props }>
|
||||
<Flex alignItems="center" columnGap={ 1 }>
|
||||
<IconSvg name="publictags_slim" boxSize={ 4 } flexShrink={ 0 } color="gray.400"/>
|
||||
{ children }
|
||||
</Flex>
|
||||
</chakraComponents.SingleValue>
|
||||
);
|
||||
}
|
||||
case 'protocol':
|
||||
case 'generic': {
|
||||
return (
|
||||
<chakraComponents.SingleValue { ...props }>
|
||||
<chakra.span color="gray.400">#</chakra.span> { children }
|
||||
</chakraComponents.SingleValue>
|
||||
);
|
||||
}
|
||||
// const fieldValue = watch(`tags.${ index }.type`).value;
|
||||
|
||||
default: {
|
||||
return (<chakraComponents.SingleValue { ...props }>{ children }</chakraComponents.SingleValue>);
|
||||
}
|
||||
}
|
||||
};
|
||||
// TODO @tom2drum: add icon for selected value
|
||||
// const selectComponents: SelectComponentsConfig<Option, boolean, GroupBase<Option>> = React.useMemo(() => {
|
||||
// type SingleValueComponentProps = SingleValueProps<Option, boolean, GroupBase<Option>> & { children: React.ReactNode };
|
||||
// const SingleValue = ({ children, ...props }: SingleValueComponentProps) => {
|
||||
// switch (fieldValue) {
|
||||
// case 'name': {
|
||||
// return (
|
||||
// <chakraComponents.SingleValue { ...props }>
|
||||
// <Flex alignItems="center" columnGap={ 1 }>
|
||||
// <IconSvg name="publictags_slim" boxSize={ 4 } flexShrink={ 0 } color="gray.400"/>
|
||||
// { children }
|
||||
// </Flex>
|
||||
// </chakraComponents.SingleValue>
|
||||
// );
|
||||
// }
|
||||
// case 'protocol':
|
||||
// case 'generic': {
|
||||
// return (
|
||||
// <chakraComponents.SingleValue { ...props }>
|
||||
// <chakra.span color="gray.400">#</chakra.span> { children }
|
||||
// </chakraComponents.SingleValue>
|
||||
// );
|
||||
// }
|
||||
|
||||
return { SingleValue };
|
||||
}, [ fieldValue ]);
|
||||
// default: {
|
||||
// return (<chakraComponents.SingleValue { ...props }>{ children }</chakraComponents.SingleValue>);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// return { SingleValue };
|
||||
// }, [ fieldValue ]);
|
||||
|
||||
return (
|
||||
<FormFieldFancySelect<FormFields, `tags.${ number }.type`>
|
||||
<FormFieldSelect<FormFields, `tags.${ number }.type`>
|
||||
name={ `tags.${ index }.type` }
|
||||
placeholder="Tag type"
|
||||
options={ typeOptions }
|
||||
isRequired
|
||||
isAsync={ false }
|
||||
isSearchable={ false }
|
||||
components={ selectComponents }
|
||||
collection={ collection }
|
||||
required
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -24,7 +24,7 @@ const PublicTagsSubmitFieldTags = ({ tagTypes }: Props) => {
|
||||
const handleAddFieldClick = React.useCallback((index: number) => {
|
||||
insert(index + 1, {
|
||||
name: '',
|
||||
type: { label: 'Name', value: 'name' },
|
||||
type: [ { label: 'Name', value: 'name' } ],
|
||||
url: undefined,
|
||||
bgColor: undefined,
|
||||
textColor: undefined,
|
||||
|
||||
@@ -13,7 +13,7 @@ export interface FormFields {
|
||||
|
||||
export interface FormFieldTag {
|
||||
name: string;
|
||||
type: Option<AddressMetadataTagType>;
|
||||
type: Array<Option<AddressMetadataTagType>>;
|
||||
url: string | undefined;
|
||||
bgColor: string | undefined;
|
||||
textColor: string | undefined;
|
||||
|
||||
@@ -19,7 +19,7 @@ export function convertFormDataToRequestsBody(data: FormFields): Array<SubmitReq
|
||||
companyWebsite: data.companyWebsite,
|
||||
address: address.hash,
|
||||
name: tag.name,
|
||||
tagType: tag.type.value,
|
||||
tagType: tag.type[0].value,
|
||||
description: data.description,
|
||||
meta: pickBy({
|
||||
bgColor: tag.bgColor,
|
||||
@@ -37,7 +37,7 @@ export function convertFormDataToRequestsBody(data: FormFields): Array<SubmitReq
|
||||
export function convertTagApiFieldsToFormFields(tag: Pick<SubmitRequestBody, 'name' | 'tagType' | 'meta'>): FormFieldTag {
|
||||
return {
|
||||
name: tag.name,
|
||||
type: { label: tag.tagType, value: tag.tagType },
|
||||
type: [ { label: tag.tagType, value: tag.tagType } ],
|
||||
url: tag.meta.tagUrl,
|
||||
bgColor: tag.meta.bgColor,
|
||||
textColor: tag.meta.textColor,
|
||||
@@ -104,7 +104,7 @@ export function getFormDefaultValues(query: Route['query'], userInfo: UserInfo |
|
||||
requesterEmail: getQueryParamString(query?.requesterEmail) || userInfo?.email || undefined,
|
||||
companyName: getQueryParamString(query?.companyName),
|
||||
companyWebsite: getQueryParamString(query?.companyWebsite),
|
||||
tags: [ { name: '', type: { label: 'Name', value: 'name' as const } } ],
|
||||
tags: [ { name: '', type: [ { label: 'Name', value: 'name' as const } ] } ],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
import type { BoxProps } from '@chakra-ui/react';
|
||||
import { Circle } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import type { FieldValues, Path } from 'react-hook-form';
|
||||
import { useController, useFormContext } from 'react-hook-form';
|
||||
|
||||
import type { FormFieldPropsBase } from './types';
|
||||
|
||||
import { Field } from 'toolkit/chakra/field';
|
||||
import type { InputProps } from 'toolkit/chakra/input';
|
||||
import { Input } from 'toolkit/chakra/input';
|
||||
import { InputGroup } from 'toolkit/chakra/input-group';
|
||||
import { validator as colorValidator } from 'ui/shared/forms/validators/color';
|
||||
|
||||
import getFieldErrorText from '../utils/getFieldErrorText';
|
||||
|
||||
interface Props<
|
||||
FormFields extends FieldValues,
|
||||
Name extends Path<FormFields> = Path<FormFields>,
|
||||
> extends FormFieldPropsBase<FormFields, Name> {
|
||||
sampleDefaultBgColor?: BoxProps['bgColor'];
|
||||
}
|
||||
|
||||
const FormFieldColor = <
|
||||
FormFields extends FieldValues,
|
||||
Name extends Path<FormFields> = Path<FormFields>,
|
||||
>({
|
||||
name,
|
||||
placeholder,
|
||||
rules,
|
||||
onBlur,
|
||||
group,
|
||||
inputProps,
|
||||
size = 'xl',
|
||||
disabled,
|
||||
sampleDefaultBgColor,
|
||||
...restProps
|
||||
}: Props<FormFields, Name>) => {
|
||||
const { control } = useFormContext<FormFields>();
|
||||
const { field, fieldState, formState } = useController<FormFields, typeof name>({
|
||||
control,
|
||||
name,
|
||||
rules: {
|
||||
...rules,
|
||||
required: restProps.required,
|
||||
validate: colorValidator,
|
||||
maxLength: 7,
|
||||
},
|
||||
});
|
||||
|
||||
const [ value, setValue ] = React.useState('');
|
||||
|
||||
const handleChange = React.useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const nextValue = (() => {
|
||||
const value = event.target.value;
|
||||
if (value) {
|
||||
if (value.length === 1 && value[0] !== '#') {
|
||||
return `#${ value }`;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
})();
|
||||
setValue(nextValue);
|
||||
field.onChange(nextValue);
|
||||
}, [ field ]);
|
||||
|
||||
const handleBlur = React.useCallback(() => {
|
||||
field.onBlur();
|
||||
onBlur?.();
|
||||
}, [ field, onBlur ]);
|
||||
|
||||
const endElement = (
|
||||
<Circle
|
||||
size="30px"
|
||||
bgColor={ field.value && colorValidator(field.value) === true ? field.value : sampleDefaultBgColor }
|
||||
borderColor="gray.300"
|
||||
borderWidth="1px"
|
||||
mx="15px"
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<Field
|
||||
label={ placeholder }
|
||||
errorText={ getFieldErrorText(fieldState.error) }
|
||||
invalid={ Boolean(fieldState.error) }
|
||||
disabled={ formState.isSubmitting || disabled }
|
||||
size={ size }
|
||||
floating
|
||||
{ ...restProps }
|
||||
>
|
||||
<InputGroup
|
||||
{ ...group }
|
||||
endElement={ endElement }
|
||||
>
|
||||
<Input
|
||||
{ ...field }
|
||||
autoComplete="off"
|
||||
onBlur={ handleBlur }
|
||||
onChange={ handleChange }
|
||||
value={ value }
|
||||
{ ...inputProps as InputProps }
|
||||
/>
|
||||
</InputGroup>
|
||||
</Field>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(FormFieldColor) as typeof FormFieldColor;
|
||||
@@ -31,7 +31,7 @@ const FormFieldText = <
|
||||
group,
|
||||
inputProps,
|
||||
asComponent,
|
||||
size = 'xl',
|
||||
size = asComponent === 'Textarea' ? '2xl' : 'xl',
|
||||
disabled,
|
||||
...restProps
|
||||
}: Props<FormFields, Name>) => {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
export const COLOR_HEX_REGEXP = /^#[a-f\d]{3,6}$/i;
|
||||
|
||||
export const validator = (value: string | undefined) => {
|
||||
export const validator = (value: unknown) => {
|
||||
if (typeof value !== 'string') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!value || value.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,6 @@ const TokenInfoForm = ({ address, tokenName, application, onSubmit }: Props) =>
|
||||
}
|
||||
|
||||
const fieldProps = {
|
||||
size: 'xl' as const,
|
||||
readOnly: application?.status === 'IN_PROCESS',
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user