Commit df494854 authored by tom's avatar tom

mobile view for public tag form

parent b3bcc87a
import { IconButton, Icon } from '@chakra-ui/react'; import { IconButton, Icon, Flex } from '@chakra-ui/react';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import type { ControllerRenderProps, Control, FieldError } from 'react-hook-form'; import type { ControllerRenderProps, Control, FieldError } from 'react-hook-form';
import { Controller } from 'react-hook-form'; import { Controller } from 'react-hook-form';
...@@ -17,55 +17,59 @@ interface Props { ...@@ -17,55 +17,59 @@ interface Props {
error?: FieldError; error?: FieldError;
onAddFieldClick: (e: React.SyntheticEvent) => void; onAddFieldClick: (e: React.SyntheticEvent) => void;
onRemoveFieldClick: (index: number) => (e: React.SyntheticEvent) => void; onRemoveFieldClick: (index: number) => (e: React.SyntheticEvent) => void;
size?: string;
} }
const MAX_INPUTS_NUM = 10; const MAX_INPUTS_NUM = 10;
export default function PublicTagFormAction({ control, index, fieldsLength, error, onAddFieldClick, onRemoveFieldClick }: Props) { export default function PublicTagFormAction({ control, index, fieldsLength, error, onAddFieldClick, onRemoveFieldClick, size }: Props) {
const renderAddressInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, `addresses.${ number }.address`>}) => { const renderAddressInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, `addresses.${ number }.address`>}) => {
return ( return (
<AddressInput<Inputs, `addresses.${ number }.address`> <AddressInput<Inputs, `addresses.${ number }.address`>
field={ field } field={ field }
error={ error } error={ error }
size="lg" size={ size }
placeholder="Smart contract / Address (0x...)" placeholder="Smart contract / Address (0x...)"
/> />
); );
}, [ error ]); }, [ error, size ]);
return ( return (
<> <Flex flexDir="column" rowGap={ 5 } alignItems="flex-end">
<Controller <Controller
name={ `addresses.${ index }.address` } name={ `addresses.${ index }.address` }
control={ control } control={ control }
render={ renderAddressInput } render={ renderAddressInput }
rules={{ pattern: ADDRESS_REGEXP }} rules={{ pattern: ADDRESS_REGEXP }}
/> />
{ index === fieldsLength - 1 && fieldsLength < MAX_INPUTS_NUM && ( <Flex
<IconButton columnGap={ 5 }
aria-label="add" position={{ base: 'static', lg: 'absolute' }}
variant="iconBorder" left={{ base: 'auto', lg: 'calc(100% + 20px)' }}
w="30px" h="100%"
h="30px" alignItems="center"
onClick={ onAddFieldClick } >
icon={ <Icon as={ PlusIcon } w="20px" h="20px"/> } { fieldsLength > 1 && (
position="absolute" <IconButton
right={ index === 0 ? '-50px' : '-100px' } aria-label="delete"
top="25px" variant="iconBorder"
/> w="30px"
) } h="30px"
{ fieldsLength > 1 && ( onClick={ onRemoveFieldClick(index) }
<IconButton icon={ <Icon as={ MinusIcon } w="20px" h="20px"/> }
aria-label="delete" />
variant="iconBorder" ) }
w="30px" { index === fieldsLength - 1 && fieldsLength < MAX_INPUTS_NUM && (
h="30px" <IconButton
onClick={ onRemoveFieldClick(index) } aria-label="add"
icon={ <Icon as={ MinusIcon } w="20px" h="20px"/> } variant="iconBorder"
position="absolute" w="30px"
right="-50px" h="30px"
top="25px" onClick={ onAddFieldClick }
/> icon={ <Icon as={ PlusIcon } w="20px" h="20px"/> }
) }</> />
) }
</Flex>
</Flex>
); );
} }
...@@ -12,23 +12,24 @@ const TEXT_INPUT_MAX_LENGTH = 255; ...@@ -12,23 +12,24 @@ const TEXT_INPUT_MAX_LENGTH = 255;
interface Props { interface Props {
control: Control<Inputs>; control: Control<Inputs>;
error?: FieldError; error?: FieldError;
size?: string;
} }
export default function PublicTagFormComment({ control, error }: Props) { export default function PublicTagFormComment({ control, error, size }: Props) {
const renderComment = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'comment'>}) => { const renderComment = useCallback(({ field }: {field: ControllerRenderProps<Inputs, 'comment'>}) => {
return ( return (
<FormControl variant="floating" id={ field.name } size="lg" isRequired> <FormControl variant="floating" id={ field.name } size={ size } isRequired>
<Textarea <Textarea
{ ...field } { ...field }
isInvalid={ Boolean(error) } isInvalid={ Boolean(error) }
size="lg" size={ size }
/> />
<FormLabel> <FormLabel>
{ getPlaceholderWithError('Specify the reason for adding tags and color preference(s)', error?.message) } { getPlaceholderWithError('Specify the reason for adding tags and color preference(s)', error?.message) }
</FormLabel> </FormLabel>
</FormControl> </FormControl>
); );
}, [ error ]); }, [ error, size ]);
return ( return (
<Controller <Controller
......
...@@ -16,6 +16,7 @@ import type { PublicTags, PublicTag, PublicTagNew, PublicTagErrors } from 'types ...@@ -16,6 +16,7 @@ import type { PublicTags, PublicTag, PublicTagNew, PublicTagErrors } from 'types
import type { ErrorType } from 'lib/client/fetch'; import type { ErrorType } from 'lib/client/fetch';
import fetch from 'lib/client/fetch'; import fetch from 'lib/client/fetch';
import getErrorMessage from 'lib/getErrorMessage'; import getErrorMessage from 'lib/getErrorMessage';
import useIsMobile from 'lib/hooks/useIsMobile';
import { EMAIL_REGEXP } from 'lib/validations/email'; import { EMAIL_REGEXP } from 'lib/validations/email';
import FormSubmitAlert from 'ui/shared/FormSubmitAlert'; import FormSubmitAlert from 'ui/shared/FormSubmitAlert';
...@@ -56,6 +57,8 @@ const ADDRESS_INPUT_BUTTONS_WIDTH = 100; ...@@ -56,6 +57,8 @@ const ADDRESS_INPUT_BUTTONS_WIDTH = 100;
const PublicTagsForm = ({ changeToDataScreen, data }: Props) => { const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const isMobile = useIsMobile();
const inputSize = isMobile ? 'md' : 'lg';
const { control, handleSubmit, formState: { errors, isValid }, setError } = useForm<Inputs>({ const { control, handleSubmit, formState: { errors, isValid }, setError } = useForm<Inputs>({
defaultValues: { defaultValues: {
...@@ -149,7 +152,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => { ...@@ -149,7 +152,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
}, [ changeToDataScreen ]); }, [ changeToDataScreen ]);
return ( return (
<Box width={ `calc(100% - ${ ADDRESS_INPUT_BUTTONS_WIDTH }px)` } maxWidth="844px"> <Box width={{ base: 'auto', lg: `calc(100% - ${ ADDRESS_INPUT_BUTTONS_WIDTH }px)` }} maxWidth="844px">
{ isAlertVisible && <Box mb={ 4 }><FormSubmitAlert/></Box> } { isAlertVisible && <Box mb={ 4 }><FormSubmitAlert/></Box> }
<Text size="sm" variant="secondary" paddingBottom={ 5 }>Company info</Text> <Text size="sm" variant="secondary" paddingBottom={ 5 }>Company info</Text>
<Grid templateColumns={{ base: '1fr', lg: '1fr 1fr' }} rowGap={ 4 } columnGap={ 5 }> <Grid templateColumns={{ base: '1fr', lg: '1fr 1fr' }} rowGap={ 4 } columnGap={ 5 }>
...@@ -160,6 +163,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => { ...@@ -160,6 +163,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
label={ placeholders.fullName } label={ placeholders.fullName }
error={ errors.fullName } error={ errors.fullName }
required required
size={ inputSize }
/> />
</GridItem> </GridItem>
<GridItem> <GridItem>
...@@ -168,6 +172,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => { ...@@ -168,6 +172,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
control={ control } control={ control }
label={ placeholders.companyName } label={ placeholders.companyName }
error={ errors.companyName } error={ errors.companyName }
size={ inputSize }
/> />
</GridItem> </GridItem>
<GridItem> <GridItem>
...@@ -178,6 +183,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => { ...@@ -178,6 +183,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
pattern={ EMAIL_REGEXP } pattern={ EMAIL_REGEXP }
error={ errors.email } error={ errors.email }
required required
size={ inputSize }
/> />
</GridItem> </GridItem>
<GridItem> <GridItem>
...@@ -186,10 +192,11 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => { ...@@ -186,10 +192,11 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
control={ control } control={ control }
label={ placeholders.companyUrl } label={ placeholders.companyUrl }
error={ errors?.companyUrl } error={ errors?.companyUrl }
size={ inputSize }
/> />
</GridItem> </GridItem>
</Grid> </Grid>
<Box marginTop={ 4 } marginBottom={ 8 }> <Box marginTop={{ base: 5, lg: 8 }} marginBottom={{ base: 5, lg: 8 }}>
<PublicTagFormAction control={ control }/> <PublicTagFormAction control={ control }/>
</Box> </Box>
<Text size="sm" variant="secondary" marginBottom={ 5 }>Public tags (2 tags maximum, please use &quot;;&quot; as a divider)</Text> <Text size="sm" variant="secondary" marginBottom={ 5 }>Public tags (2 tags maximum, please use &quot;;&quot; as a divider)</Text>
...@@ -199,7 +206,9 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => { ...@@ -199,7 +206,9 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
control={ control } control={ control }
label={ placeholders.tags } label={ placeholders.tags }
error={ errors.tags } error={ errors.tags }
required/> required
size={ inputSize }
/>
</Box> </Box>
{ fields.map((field, index) => { { fields.map((field, index) => {
return ( return (
...@@ -211,12 +220,13 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => { ...@@ -211,12 +220,13 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
fieldsLength={ fields.length } fieldsLength={ fields.length }
onAddFieldClick={ onAddFieldClick } onAddFieldClick={ onAddFieldClick }
onRemoveFieldClick={ onRemoveFieldClick } onRemoveFieldClick={ onRemoveFieldClick }
size={ inputSize }
/> />
</Box> </Box>
); );
}) } }) }
<Box marginBottom={ 8 }> <Box marginBottom={ 8 }>
<PublicTagFormComment control={ control } error={ errors.comment }/> <PublicTagFormComment control={ control } error={ errors.comment } size={ inputSize }/>
</Box> </Box>
<HStack spacing={ 6 }> <HStack spacing={ 6 }>
<Button <Button
......
...@@ -14,6 +14,7 @@ interface Props<TInputs extends FieldValues> { ...@@ -14,6 +14,7 @@ interface Props<TInputs extends FieldValues> {
control: Control<TInputs, object>; control: Control<TInputs, object>;
pattern?: RegExp; pattern?: RegExp;
error?: FieldError; error?: FieldError;
size?: string;
} }
export default function PublicTagsFormInput<Inputs extends FieldValues>({ export default function PublicTagsFormInput<Inputs extends FieldValues>({
...@@ -23,13 +24,14 @@ export default function PublicTagsFormInput<Inputs extends FieldValues>({ ...@@ -23,13 +24,14 @@ export default function PublicTagsFormInput<Inputs extends FieldValues>({
fieldName, fieldName,
pattern, pattern,
error, error,
size,
}: Props<Inputs>) { }: Props<Inputs>) {
const renderInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, typeof fieldName>}) => { const renderInput = useCallback(({ field }: {field: ControllerRenderProps<Inputs, typeof fieldName>}) => {
return ( return (
<FormControl variant="floating" id={ field.name } isRequired={ required } size="lg"> <FormControl variant="floating" id={ field.name } isRequired={ required } size={ size }>
<Input <Input
{ ...field } { ...field }
size="lg" size={ size }
required={ required } required={ required }
isInvalid={ Boolean(error) } isInvalid={ Boolean(error) }
maxLength={ TEXT_INPUT_MAX_LENGTH } maxLength={ TEXT_INPUT_MAX_LENGTH }
...@@ -37,7 +39,7 @@ export default function PublicTagsFormInput<Inputs extends FieldValues>({ ...@@ -37,7 +39,7 @@ export default function PublicTagsFormInput<Inputs extends FieldValues>({
<FormLabel>{ getPlaceholderWithError(label, error?.message) }</FormLabel> <FormLabel>{ getPlaceholderWithError(label, error?.message) }</FormLabel>
</FormControl> </FormControl>
); );
}, [ label, required, error ]); }, [ label, required, error, size ]);
return ( return (
<Controller <Controller
name={ fieldName } name={ fieldName }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment