DEV Community

Kaushik Varanasi
Kaushik Varanasi

Posted on

Building the frontend for Messaging app using Chakra UI

Basic setup

  1. We'll use React.js + ChakraUI for basic UI setup
  2. Rocketgraph to setup the backend


npx create-react-app messaging-app


Enter fullscreen mode Exit fullscreen mode

Install Chakra UI



yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion


Enter fullscreen mode Exit fullscreen mode

Install other necessary libs



yarn add react-router-dom


Enter fullscreen mode Exit fullscreen mode

Head over to rocketgraph and create an account. Then click on "Create Project". Don't worry, it comes with a free trail and no CC required.

Wait for the project to boot and go to the Hasura console.

Skeleton App

Now let's build the basic UI without the actual data/backend.

create src/components directory to hold our components.

In the index.js file, replace it with the following



// src/index.js
import React from "react";
import ReactDOM from "react-dom";
import { ChakraProvider } from '@chakra-ui/react'
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import App from "./App";
import Message from "./components/Message"

ReactDOM.render(
  <React.StrictMode>
    <ChakraProvider>
      <Router>
        <Routes>
          <Route path="/login" />
          <Route path="/signup" />
          <Route path="/messages" element={<Message />} />
          <Route path="/" element={<App />} />
        </Routes>
      </Router>
    </ChakraProvider>
  </React.StrictMode>,
  document.getElementById("root")
);


Enter fullscreen mode Exit fullscreen mode

Now let's create the individual components to show on the app.

Create src/components/Message.js and add the following code.



import React from "react";
import { useSearchParams } from 'react-router-dom';

import { Input } from '@chakra-ui/react'
import { Button, ButtonGroup } from '@chakra-ui/react'
import { Card, CardHeader, CardBody, CardFooter, Heading, Text, Flex, Avatar, Box } from '@chakra-ui/react'


const messages = [
    {
        from: "",
        to: "",
        from_address: "",
        to_address: "",
        message: "View a summary of all your customers over the last month.",
    },
    {
        from: "",
        to: "",
        from_address: "",
        to_address: "",
        message: "View a summary of all your customers over the last month.",
    }
]

export default function DrawerExample() {
    const [searchParams] = useSearchParams();
    console.log(searchParams.get('email')); // โ–ถ URLSearchParams {}
    // currentUser = Cookies.get("user")
    const currentUser = "kaushik@moneysave.io"
    return (
      <>
        <div className="message-body">
            <div className="messages">
                {
                    messages.map((message) => {
                        return (
                            <div className={message.to == currentUser ? "message-received" : "message-sent"} m={4}>
                                <div className="message-text">
                                    <Card>
                                        <CardHeader>
                                            <Flex spacing='4'>
                                            <Flex flex='1' gap='4' alignItems='center' flexWrap='wrap'>
                                                <Avatar name='Segun Adebayo' src='https://bit.ly/sage-adebayo' />

                                                <Box>
                                                <Heading size='sm'>Segun Adebayo</Heading>
                                                <Text>Creator, Chakra UI</Text>
                                                </Box>
                                            </Flex>
                                            </Flex>
                                        </CardHeader>
                                        <CardBody>
                                            <Text>{message.message}</Text>
                                        </CardBody>
                                    </Card>
                                </div>
                            </div>
                        )
                    })
                }


            </div>
            <div className="main-bottom">
                <Input m={2} placeholder='Basic usage' />
                <Button m={2} colorScheme='blue'>Button</Button>
            </div>
        </div>
      </>
    )
}


Enter fullscreen mode Exit fullscreen mode

Here we have created a dummy message component which displays the chat with a user based on the query parameters in the URL. We will discuss this later.
Once we implement the actual functionality, the messages will become live

Image description

And in App.css add the following code:



.App {
  text-align: center;
}

.App-logo {
  height: 40vmin;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .App-logo {
    animation: App-logo-spin infinite 20s linear;
  }
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.App-link {
  color: #61dafb;
}

.message-body {
  position: relative;
  height: 100vh;
}
.main-bottom {
  position: absolute;
  bottom: 10px;
  left: 0px;
  width: 100%;
  display: flex;
}

.message-sent {
  padding: 10px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}
.message-received {
  padding: 10px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.message-text {

}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}


Enter fullscreen mode Exit fullscreen mode

In App.js, add the following code



import logo from './logo.svg';
import Profiles from "./components/Profiles"
import './App.css';

function App() {
  return (
    <div className="App">
      <Profiles/>
    </div>
  );
}

export default App;


Enter fullscreen mode Exit fullscreen mode

Now create src/components/Profiles.js



import {
    Heading,
    Avatar,
    Box,
    Center,
    Image,
    Flex,
    Text,
    Stack,
    Button,
    useColorModeValue,
  } from '@chakra-ui/react';

  export default function SocialProfileWithImage() {
    return (
      <Center py={6}>
        <Box
          maxW={'270px'}
          w={'full'}
          bg={useColorModeValue('white', 'gray.800')}
          boxShadow={'2xl'}
          rounded={'md'}
          overflow={'hidden'}>
          <Image
            h={'120px'}
            w={'full'}
            src={
              'https://images.unsplash.com/photo-1612865547334-09cb8cb455da?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80'
            }
            objectFit={'cover'}
          />
          <Flex justify={'center'} mt={-12}>
            <Avatar
              size={'xl'}
              src={
                'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&q=80&fm=jpg&crop=faces&fit=crop&h=200&w=200&ixid=eyJhcHBfaWQiOjE3Nzg0fQ'
              }
              alt={'Author'}
              css={{
                border: '2px solid white',
              }}
            />
          </Flex>

          <Box p={6}>
            <Stack spacing={0} align={'center'} mb={5}>
              <Heading fontSize={'2xl'} fontWeight={500} fontFamily={'body'}>
                John Doe
              </Heading>
              <Text color={'gray.500'}>Frontend Developer</Text>
            </Stack>

            <Button
              w={'full'}
              mt={8}
              bg={useColorModeValue('#151f21', 'gray.900')}
              color={'white'}
              rounded={'md'}
              onClick={() => {window.location = "/messages?email=kaushik@moneysave.io"} }
              _hover={{
                transform: 'translateY(-2px)',
                boxShadow: 'lg',
              }}>
              Message
            </Button>
          </Box>
        </Box>
      </Center>
    );
  }


Enter fullscreen mode Exit fullscreen mode

Now let's create the login and signup pages as follows:

src/components/login.js



import {
    Flex,
    Box,
    FormControl,
    FormLabel,
    Input,
    Checkbox,
    Stack,
    Link,
    Button,
    Heading,
    Text,
    useColorModeValue,
  } from '@chakra-ui/react';

  export default function SimpleCard() {
    return (
      <Flex
        minH={'100vh'}
        align={'center'}
        justify={'center'}
        bg={useColorModeValue('gray.50', 'gray.800')}>
        <Stack spacing={8} mx={'auto'} maxW={'lg'} py={12} px={6}>
          <Stack align={'center'}>
            <Heading fontSize={'4xl'}>Sign in to your account</Heading>
            <Text fontSize={'lg'} color={'gray.600'}>
              to enjoy all of our cool <Link color={'blue.400'}>features</Link> โœŒ๏ธ
            </Text>
          </Stack>
          <Box
            rounded={'lg'}
            bg={useColorModeValue('white', 'gray.700')}
            boxShadow={'lg'}
            p={8}>
            <Stack spacing={4}>
              <FormControl id="email">
                <FormLabel>Email address</FormLabel>
                <Input type="email" />
              </FormControl>
              <FormControl id="password">
                <FormLabel>Password</FormLabel>
                <Input type="password" />
              </FormControl>
              <Stack spacing={10}>
                <Stack
                  direction={{ base: 'column', sm: 'row' }}
                  align={'start'}
                  justify={'space-between'}>
                  <Checkbox>Remember me</Checkbox>
                  <Link color={'blue.400'}>Forgot password?</Link>
                </Stack>
                <Button
                  bg={'blue.400'}
                  color={'white'}
                  _hover={{
                    bg: 'blue.500',
                  }}>
                  Sign in
                </Button>
              </Stack>
            </Stack>
          </Box>
        </Stack>
      </Flex>
    );
  }


Enter fullscreen mode Exit fullscreen mode

src/components/signup.js



import {
    Flex,
    Box,
    FormControl,
    FormLabel,
    Input,
    Checkbox,
    Stack,
    Link,
    Button,
    Heading,
    Text,
    useColorModeValue,
  } from '@chakra-ui/react';

  export default function SimpleCard() {
    return (
      <Flex
        minH={'100vh'}
        align={'center'}
        justify={'center'}
        bg={useColorModeValue('gray.50', 'gray.800')}>
        <Stack spacing={8} mx={'auto'} maxW={'lg'} py={12} px={6}>
          <Stack align={'center'}>
            <Heading fontSize={'4xl'}>Create your account</Heading>
            <Text fontSize={'lg'} color={'gray.600'}>
              to enjoy all of our cool <Link color={'blue.400'}>features</Link> โœŒ๏ธ
            </Text>
          </Stack>
          <Box
            rounded={'lg'}
            bg={useColorModeValue('white', 'gray.700')}
            boxShadow={'lg'}
            p={8}>
            <Stack spacing={4}>
              <FormControl id="email">
                <FormLabel>Email address</FormLabel>
                <Input type="email" />
              </FormControl>
              <FormControl id="password">
                <FormLabel>Password</FormLabel>
                <Input type="password" />
              </FormControl>
              <Stack spacing={10}>
                <Stack
                  direction={{ base: 'column', sm: 'row' }}
                  align={'start'}
                  justify={'space-between'}>
                  <Checkbox>Remember me</Checkbox>
                  <Link color={'blue.400'}>Forgot password?</Link>
                </Stack>
                <Button
                  bg={'blue.400'}
                  color={'white'}
                  _hover={{
                    bg: 'blue.500',
                  }}>
                  Sign in
                </Button>
              </Stack>
            </Stack>
          </Box>
        </Stack>
      </Flex>
    );
  }


Enter fullscreen mode Exit fullscreen mode

Great, now we finished setting up the skeleton of the front-end of the application. Now we need to inject data into this via the backend. Let's create the backend. Head over to the next article in the series.

Top comments (0)