Skip to content

Commit

Permalink
Step 12.1: Add basic ChatCreationScreen
Browse files Browse the repository at this point in the history
  • Loading branch information
DAB0mB authored and Urigo committed May 20, 2020
1 parent f068cd8 commit bbb1203
Show file tree
Hide file tree
Showing 11 changed files with 296 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import AuthScreen from './components/AuthScreen';
import ChatRoomScreen from './components/ChatRoomScreen';
import ChatsListScreen from './components/ChatsListScreen';
import ChatCreationScreen from './components/ChatCreationScreen';
import AnimatedSwitch from './components/AnimatedSwitch';
import { withAuth } from './services/auth.service';

Expand All @@ -26,6 +27,8 @@ const App: React.FC = () => (
)
)}
/>

<Route exact path="/new-chat" component={withAuth(ChatCreationScreen)} />
</AnimatedSwitch>
<Route exact path="/" render={redirectToChats} />
</BrowserRouter>
Expand Down
26 changes: 26 additions & 0 deletions src/components/ChatCreationScreen/ChatCreationNavbar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createMemoryHistory } from 'history';
import React from 'react';
import { cleanup, render, fireEvent, waitFor } from '@testing-library/react';
import ChatCreationNavbar from './ChatCreationNavbar';

describe('ChatCreationNavbar', () => {
afterEach(cleanup);

it('goes back on arrow click', async () => {
const history = createMemoryHistory();

history.push('/new-chat');

await waitFor(() => expect(history.location.pathname).toEqual('/new-chat'));

{
const { container, getByTestId } = render(
<ChatCreationNavbar history={history} />
);

fireEvent.click(getByTestId('back-button'));

await waitFor(() => expect(history.location.pathname).toEqual('/chats'));
}
});
});
45 changes: 45 additions & 0 deletions src/components/ChatCreationScreen/ChatCreationNavbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
import { Toolbar, Button } from '@material-ui/core';
import React from 'react';
import { useCallback } from 'react';
import styled from 'styled-components';
import { History } from 'history';

const Container = styled(Toolbar)`
display: flex;
background-color: var(--primary-bg);
color: var(--primary-text);
font-size: 20px;
line-height: 40px;
`;

const BackButton = styled(Button)`
svg {
color: var(--primary-text);
}
`;

const Title = styled.div`
flex: 1;
`;

interface ChildComponentProps {
history: History;
}

const ChatCreationNavbar: React.FC<ChildComponentProps> = ({ history }) => {
const navBack = useCallback(() => {
history.replace('/chats');
}, [history]);

return (
<Container>
<BackButton data-testid="back-button" onClick={navBack}>
<ArrowBackIcon />
</BackButton>
<Title>Create Chat</Title>
</Container>
);
};

export default ChatCreationNavbar;
29 changes: 29 additions & 0 deletions src/components/ChatCreationScreen/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import styled from 'styled-components';
import UsersList from '../UsersList';
import ChatCreationNavbar from './ChatCreationNavbar';
import { History } from 'history';

// eslint-disable-next-line
const Container = styled.div`
height: calc(100% - 56px);
overflow-y: overlay;
`;

// eslint-disable-next-line
const StyledUsersList = styled(UsersList)`
height: calc(100% - 56px);
`;

interface ChildComponentProps {
history: History;
}

const ChatCreationScreen: React.FC<ChildComponentProps> = ({ history }) => (
<div>
<ChatCreationNavbar history={history} />
<UsersList />
</div>
);

export default ChatCreationScreen;
29 changes: 29 additions & 0 deletions src/components/ChatsListScreen/AddChatButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { createMemoryHistory } from 'history';
import { ApolloProvider } from '@apollo/react-hooks';
import React from 'react';
import { cleanup, render, fireEvent, waitFor } from '@testing-library/react';
import AddChatButton from './AddChatButton';
import { mockApolloClient } from '../../test-helpers';

describe('AddChatButton', () => {
afterEach(cleanup);

it('goes back on arrow click', async () => {
const history = createMemoryHistory();
const client = mockApolloClient();

{
const { container, getByTestId } = render(
<ApolloProvider client={client}>
<AddChatButton history={history} />
</ApolloProvider>
);

fireEvent.click(getByTestId('new-chat-button'));

await waitFor(() =>
expect(history.location.pathname).toEqual('/new-chat')
);
}
});
});
43 changes: 43 additions & 0 deletions src/components/ChatsListScreen/AddChatButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import Button from '@material-ui/core/Button';
import ChatIcon from '@material-ui/icons/Chat';
import React from 'react';
import styled from 'styled-components';
import { History } from 'history';

const Container = styled.div`
position: fixed;
right: 10px;
bottom: 10px;
button {
min-width: 50px;
width: 50px;
height: 50px;
border-radius: 999px;
background-color: var(--secondary-bg);
color: white;
}
`;
interface ChildComponentProps {
history: History;
}

const AddChatButton: React.FC<ChildComponentProps> = ({ history }) => {
const onClick = () => {
history.push('/new-chat');
};

return (
<Container>
<Button
data-testid="new-chat-button"
variant="contained"
color="secondary"
onClick={onClick}>
<ChatIcon />
</Button>
</Container>
);
};

export default AddChatButton;
2 changes: 2 additions & 0 deletions src/components/ChatsListScreen/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import ChatsNavbar from './ChatsNavbar';
import ChatsList from './ChatsList';
import styled from 'styled-components';
import { History } from 'history';
import AddChatButton from './AddChatButton';

const Container = styled.div`
height: 100vh;
Expand All @@ -16,6 +17,7 @@ const ChatsListScreen: React.FC<ChatsListScreenProps> = ({ history }) => (
<Container>
<ChatsNavbar history={history} />
<ChatsList history={history} />
<AddChatButton history={history} />
</Container>
);

Expand Down
45 changes: 45 additions & 0 deletions src/components/UsersList.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import { ApolloProvider } from '@apollo/react-hooks';
import { cleanup, render, waitFor, screen } from '@testing-library/react';
import { mockApolloClient } from '../test-helpers';
import UsersList, { UsersListQuery } from './UsersList';

describe('UsersList', () => {
afterEach(cleanup);

it('renders fetched users data', async () => {
const client = mockApolloClient([
{
request: { query: UsersListQuery },
result: {
data: {
users: [
{
__typename: 'User',
id: 1,
name: 'Charles Dickhead',
picture: 'https://localhost:4000/dick.jpg',
},
],
},
},
},
]);

{
const { container, getByTestId } = render(
<ApolloProvider client={client}>
<UsersList />
</ApolloProvider>
);

await waitFor(() => screen.getByTestId('name'));

expect(getByTestId('name')).toHaveTextContent('Charles Dickhead');
expect(getByTestId('picture')).toHaveAttribute(
'src',
'https://localhost:4000/dick.jpg'
);
}
});
});
64 changes: 64 additions & 0 deletions src/components/UsersList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import MaterialList from '@material-ui/core/List';
import MaterialItem from '@material-ui/core/ListItem';
import gql from 'graphql-tag';
import React from 'react';
import styled from 'styled-components';
import * as fragments from '../graphql/fragments';
import { useUsersListQuery } from '../graphql/types';

const ActualList = styled(MaterialList)`
padding: 0;
`;

const UserItem = styled(MaterialItem)`
position: relative;
padding: 7.5px 15px;
display: flex;
cursor: pinter;
`;

const ProfilePicture = styled.img`
height: 50px;
width: 50px;
object-fit: cover;
border-radius: 50%;
`;

const Name = styled.div`
padding-left: 15px;
font-weight: bold;
`;

export const UsersListQuery = gql`
query UsersList {
users {
...User
}
}
${fragments.user}
`;

const UsersList: React.FC = () => {
const { data, loading: loadingUsers } = useUsersListQuery();

if (data === undefined) return null;
const users = data.users;

return (
<ActualList>
{!loadingUsers &&
users.map((user) => (
<UserItem key={user.id} button>
{user !== null && user.picture !== null && (
<React.Fragment>
<ProfilePicture data-testid="picture" src={user.picture} />
<Name data-testid="name">{user.name}</Name>
</React.Fragment>
)}
</UserItem>
))}
</ActualList>
);
};

export default UsersList;
1 change: 1 addition & 0 deletions src/graphql/fragments/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as chat } from './chat.fragment';
export { default as fullChat } from './fullChat.fragment';
export { default as message } from './message.fragment';
export { default as user } from './user.fragment';
9 changes: 9 additions & 0 deletions src/graphql/fragments/user.fragment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import gql from 'graphql-tag';

export default gql`
fragment User on User {
id
name
picture
}
`;

0 comments on commit bbb1203

Please sign in to comment.