Skip to content

Commit

Permalink
[FEATURE]: Drawer with members (#523)
Browse files Browse the repository at this point in the history
* feat: add drawer layout to display members list

* feat: add schema to search member form
  • Loading branch information
CatiaAntunes96 authored Oct 28, 2022
1 parent 6b6e4a3 commit 2a26d1b
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 4 deletions.
12 changes: 11 additions & 1 deletion frontend/src/components/Primitives/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ interface InputProps extends StyledInpupProps {
state?: 'default' | 'error' | 'valid';
type: 'text' | 'password' | 'email' | 'number';
placeholder: string;
icon?: 'eye' | 'eyeclosed';
icon?: 'eye' | 'eyeclosed' | 'search';
helperText?: string;
iconPosition?: 'left' | 'right';
forceState?: boolean;
Expand Down Expand Up @@ -230,6 +230,7 @@ const Input: React.FC<InputProps> = ({
const { ref, ...rest } = register(id);

const message = errors[id]?.message;

const value = getValues()[id];
const isValueEmpty = isEmpty(value);

Expand Down Expand Up @@ -283,6 +284,15 @@ const Input: React.FC<InputProps> = ({
}}
/>
)}
{icon === 'search' && (
<Icon
name="search"
css={{
width: '$24',
height: '$24'
}}
/>
)}
</IconWrapper>
)}
<Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useSession } from 'next-auth/react';

import Flex from 'components/Primitives/Flex';
import Text from 'components/Primitives/Text';
import AddMemberBtn from '../AddMemberBtn';
import CardMember from '../CardMember';

const TeamMembersList = () => {
Expand All @@ -15,7 +14,6 @@ const TeamMembersList = () => {
Team Members
</Text>
<CardMember userId={session.user.id} userSAdmin={session.isSAdmin} />
<AddMemberBtn />
</Flex>
) : null;
};
Expand Down
142 changes: 142 additions & 0 deletions frontend/src/components/Teams/CreateTeam/ListMembers/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { Dispatch, SetStateAction, useEffect, useRef } from 'react';
import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { joiResolver } from '@hookform/resolvers/joi';
import { Dialog, DialogClose, DialogTrigger } from '@radix-ui/react-dialog';

import Icon from 'components/icons/Icon';
import Text from 'components/Primitives/Text';
import SchemaAddMemberForm from '../../../../schema/schemaAddMemberForm';
import {
ButtonsContainer,
StyledDialogCloseButton,
StyledDialogContainer,
StyledDialogContent,
StyledDialogOverlay,
StyledDialogTitle
} from '../../../Board/Settings/styles';
import Button from '../../../Primitives/Button';
import Flex from '../../../Primitives/Flex';
import Input from '../../../Primitives/Input';
import { ButtonAddMember } from './styles';

type Props = {
setIsOpen: Dispatch<SetStateAction<boolean>>;
isOpen: boolean;
};

const ListMembers = ({ isOpen, setIsOpen }: Props) => {
// References
const dialogContainerRef = useRef<HTMLSpanElement>(null);
const submitBtnRef = useRef<HTMLButtonElement | null>(null);

// Method to close dialog and reset switches state
const handleClose = () => {
setIsOpen(false);
};

const methods = useForm<{ search: string }>({
mode: 'onBlur',
reValidateMode: 'onBlur',
defaultValues: {
search: ''
},
resolver: joiResolver(SchemaAddMemberForm)
});

const searchMember = useWatch({
control: methods.control,
name: 'search'
});

/**
* Use Effect to submit the board settings form when press enter key
* (Note: Radix Dialog close when pressing enter)
*/
useEffect(() => {
const element = dialogContainerRef?.current;

const keyDownHandler = (event: KeyboardEvent) => {
if (event.key === 'Enter') {
event.preventDefault();

if (submitBtnRef.current) {
submitBtnRef.current.click();
}
}
};

element?.addEventListener('keydown', keyDownHandler);

return () => element?.removeEventListener('keydown', keyDownHandler);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<StyledDialogContainer ref={dialogContainerRef}>
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild>
<ButtonAddMember>
<Icon css={{ width: '$16', height: '$16' }} name="plus" />{' '}
<Text
css={{
ml: '$10',
fontSize: '$14',
lineHeight: '$18',
fontWeight: '700'
}}
>
Add new member
</Text>
</ButtonAddMember>
</DialogTrigger>
<StyledDialogOverlay />
<StyledDialogContent>
<StyledDialogTitle>
<Text heading="4">Add team members</Text>
<DialogClose asChild>
<StyledDialogCloseButton isIcon size="lg">
<Icon css={{ color: '$primary400' }} name="close" size={24} />
</StyledDialogCloseButton>
</DialogClose>
</StyledDialogTitle>
<FormProvider {...methods}>
<Flex css={{ padding: '$24 $32 $40' }} direction="column" gap={16}>
<Input
currentValue={searchMember}
icon="search"
iconPosition="left"
id="search"
maxChars="30"
placeholder="Search member"
state="default"
type="text"
/>
</Flex>
<Text css={{ display: 'block', px: '$32', py: '$10' }} heading="4">
Teams
</Text>
<ButtonsContainer gap={24} justify="end">
<Button
css={{ margin: '0 $24 0 auto', padding: '$16 $24' }}
variant="primaryOutline"
onClick={handleClose}
>
Cancel
</Button>
<Button
css={{ marginRight: '$32', padding: '$16 $24' }}
ref={submitBtnRef}
type="submit"
variant="primary"
>
Save
</Button>
</ButtonsContainer>
</FormProvider>
</StyledDialogContent>
</Dialog>
</StyledDialogContainer>
);
};

export { ListMembers };
17 changes: 17 additions & 0 deletions frontend/src/components/Teams/CreateTeam/ListMembers/styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { styled } from '../../../../styles/stitches/stitches.config';

const ButtonAddMember = styled('button', {
color: 'black',
display: 'flex',
alignItems: 'center',
backgroundColor: 'transparent',
border: 0,
fontSize: '13px',
'&:hover': {
cursor: 'pointer',
textDecoration: 'underline'
},
marginTop: '10px'
});

export { ButtonAddMember };
6 changes: 5 additions & 1 deletion frontend/src/pages/teams/new.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback } from 'react';
import { useCallback, useState } from 'react';
import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { NextPage } from 'next';
import { useRouter } from 'next/router';
Expand All @@ -8,6 +8,7 @@ import Icon from '../../components/icons/Icon';
import Button from '../../components/Primitives/Button';
import Text from '../../components/Primitives/Text';
import TeamsMembersList from '../../components/Teams/CreateTeam/ListCardsMembers';
import { ListMembers } from '../../components/Teams/CreateTeam/ListMembers';
import TeamName from '../../components/Teams/CreateTeam/TeamName';
import TipBar from '../../components/Teams/CreateTeam/TipBar';
import SchemaCreateTeam from '../../schema/schemaCreateTeamForm';
Expand All @@ -24,6 +25,8 @@ import {
const NewTeam: NextPage = () => {
const router = useRouter();

const [isOpen, setIsOpen] = useState(false);

const methods = useForm<{ text: string }>({
mode: 'onBlur',
reValidateMode: 'onBlur',
Expand Down Expand Up @@ -60,6 +63,7 @@ const NewTeam: NextPage = () => {
<FormProvider {...methods}>
<TeamName teamName={teamName} />
<TeamsMembersList />
<ListMembers isOpen={isOpen} setIsOpen={setIsOpen} />
</FormProvider>
</InnerContent>
<ButtonsContainer gap="24" justify="end">
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/schema/schemaAddMemberForm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Joi from 'joi';

const SchemaAddMemberForm = Joi.object({
search: Joi.string().optional().trim().max(30).messages({
'string.max': 'Maximum of 30 characters'
})
});

export default SchemaAddMemberForm;

0 comments on commit 2a26d1b

Please sign in to comment.