Building Simple CRM with Vue: Crafting Layouts and Navigation
Tags: vue, javascript, webdev, tutorial
Published: 2024-02-28 13:04:21


![Building Simple CRM with Vue: Crafting Layouts and Navigation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fi97549w5rtxa157khyn.jpg)

> Check [this post](https://webcraft-notes.com/blog/building-simple-crm-with-vue-crafting-layouts) in [my web notes](https://webcraft-notes.com/)!

Now that we've successfully completed the [preliminary installations](https://webcraft-notes.com/blog/building-simple-crm-with-vue-getting-started), it's time to embark on the exciting journey of building our CRM with Vue. The question is, where do we begin? The answer lies in the fundamentals — navigation, headers, and layouts. These essential elements will form the cornerstone of our main "Dashboard" page, seamlessly integrated into our router configuration. Let's outline a concise plan to guide us through the next steps:
### 1.Layouts: Unveiling the What, Why, and How:
Delve into the significance of layouts – what purpose they serve, why they matter, and how to craft them effectively.
### 2. Initiate the "Dashboard" Page:
Start by creating the foundational "Dashboard" page, setting the stage for our CRM's central hub.
### 3. CRM Navigation: Crafting a Sidebar:
Explore the intricacies of CRM navigation, focusing on the creation of a user-friendly sidebar.

As we progress through each step, we'll unravel the art of crafting layouts and navigation in Vue, ensuring a robust foundation for our Simple CRM. Stay tuned for practical insights and step-by-step guidance as we navigate the world of Vue.js development.

### 1. Layouts: What and Why do We Need Layouts?
A layout in web development refers to the structural arrangement of visual elements on a webpage, defining the positioning and organization of content. It establishes the overall framework, including the placement of headers, footers, navigation bars, and other components, ensuring a cohesive and user-friendly design.

In simple words, a layout is a web page background where we position all elements. For example with our simple CRM, we will need two layouts: the first or main layout for all our pages which will contain a header, sidebar, menu, and maybe a footer; the second one, an empty layout for the login page and maybe a 404 page.
#### 1.1 How to add layout to Vue project?
It will be clearer when we create and use layouts in practice. So let's do it:

Inside our project create a "layouts" folder and a "MainLayout.vue" file. It will be the layout for our main app pages, so we need to add "Header" for start, and "RouterView" (the place where our 'children' routes will be rendering). Also, inside the "components" folder create another folder "navigation" and add a "Header" file with some empty template. That's it:
```
<template>
    <main>
        <Header />
        <RouterView />
    </main>
</template>

<script>
import { RouterView } from 'vue-router';
import Header from '@/components/navigation/Header.vue';

export default {
    name: 'MainLayout',
    components: {
        Header,
    }
};
</script>
```
Now, we need to update our main "App.vue" file. Remove "Router" because all routes control is inside the layout and import our "MainLayout" into the App component.
```
<template>
  <MainLayout />
</template>

<script>
import MainLayout from '@/layouts/MainLayout.vue';
export default {
  name: 'App',
  components: {
    MainLayout
  }
}
</script>
```
We need to improve our route configurations, we will add the first route and nested routes as its children.
```
import { createRouter, createWebHistory } from 'vue-router';
import Dashboard from '../views/Dashboard.vue';

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      children: [
        {
          path: '',
          component: Dashboard,
        },
      ]
    },
  ]
})

export default router
```
If you need to get more details about "Vue Router" you can check [my articles](https://webcraft-notes.com/blog/vue-basis-navigating-through-your-app-withhl=uk#) about that.

Now, we can launch our development server (npm run dev) and check the result:
![How to add layout to Vue project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lgz62aw0qa7vbkujhhat.png)
I know it is not a pretty page and it could be unclear why we needed those layouts, just wait till the login page creation.
### 2. Initiate the "Dashboard" Page
In this part, we will create and fill with some cards our first "Dashboard" page. Typically dashboard page shows common data about client business or statistics. For that reason, I'm offering you to create a "Cards" component inside the "ui" folder and copy [typical card variants](https://vuetifyjs.com/en/components/cards/#variants) from Vuetify. Then just import that component into our "Dashboard".

Also, I could not watch on that empty page, and added some styles. Here is the result:
![Initiate the "Dashboard" Page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zydey73jk5jwzqhqbs79.png)
If you are lazy a little bit like me, you can use "UI Verse" ready-to-use components and color palettes, if not leave that page empty, and let's go to our next more interesting section. 
### 3. CRM Navigation: Crafting a Sidebar
There are two popular types of navigation: header navigation and sidebar. Let's add both of them. 

First, we will add a small dropdown menu for the profile button in the header section. Open the "[menu](https://vuetifyjs.com/en/components/menus/#location)" section in Vuetify documentation copy code from the "dropdown location" part into a separate component and import it inside our "Header" component.

Also, we will use the "v-avatar" component from the "[Avatar](https://vuetifyjs.com/en/components/avatars/)" section to show the user avatar. Put v-avatar, and user name inside our v-btn component so that if the user clicks on his avatar or name our app will show a menu (profile, sign out...).
```
<template>
    <div class="text-center d-flex align-center justify-center mr-5 header__profile">
        <v-menu :location="'bottom'">
            <template v-slot:activator="{ props }">
                <v-btn
                    variant="text"
                    color="white"
                    class="text-none"
                    dark
                    v-bind="props"
                >
                    <v-avatar color="surface-variant" size="32"></v-avatar>
                    <span class="ml-2 mr-1">Oleh</span>
                    <v-icon size="x-small" icon="fas fa-chevron-down" class="ml-2" />
                </v-btn>
            </template>
            <v-list>
                <v-list-item
                    v-for="(item, index) in items"
                    :key="index"
                >
                    <v-list-item-title>{{ item.title }}</v-list-item-title>
                </v-list-item>
            </v-list>
        </v-menu>
    </div>
</template>
<script>
  export default {
    data: () => ({
      items: [
        { title: 'Click Me' },
        { title: 'Click Me' },
        { title: 'Click Me' },
        { title: 'Click Me 2' },
      ]
    }),
  }
</script>
```
Let's check the header view:
![CRM Navigation: Crafting a Sidebar](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0vq4flovwspw1zok9se7.png)
Great, and one more part: sidebar. Luckily for us, vuetify also has a solution for this type of task.

In the"[Navigation drawers](https://vuetifyjs.com/en/components/navigation-drawers)" section there are different sidebar examples that we can use. I like the "[Rail variant](https://vuetifyjs.com/en/components/navigation-drawers/#rail-variant)" the most, so I'll add this menu version to our Simple CRM project. As we did before, simply copy the template and script into a separate Sidebar component inside the navigation folder. We already have an avatar on Header so let's replace it with a bars icon.
```
<template>
    <v-card>
        <v-layout>
            <v-navigation-drawer
                class="background-color"
                v-model="drawer"
                :rail="rail"
                permanent
                @click="rail = false"
            >
            <v-list-item
                class="ml-2 mt-2"
                nav
            >
                <v-list-item-title v-if="!rail" class="text-h6">Sherman CRM</v-list-item-title>
                <template v-if="!rail" v-slot:append>
                    <v-btn
                        variant="text"
                        icon="fas fa-chevron-left"
                        @click.stop="rail = !rail"
                    ></v-btn>
                </template>
                <v-btn
                    v-if="rail"
                    variant="text"
                    icon="fas fa-bars"
                    @click.stop="rail = !rail"
                ></v-btn>
            </v-list-item>
    
            <v-list density="compact" nav>
                <v-list-item prepend-icon="fas fa-chart-line" title="Dashboard" value="dashboard"></v-list-item>
            </v-list>
            </v-navigation-drawer>
        </v-layout>
    </v-card>
</template>
```
We have a rail variable that contains information about the sidebar state. To make our Layout related to the sidebar (when the sidebar is opened - the page width should be decreased) we will add a simple watcher that will send rail variable state into the layout.
```
watch: {
    rail: {
        handler() {
            this.$emit('rail', this.rail);
        }
    }
}
```
We will update the MainLayout component to respond to that rail state and change its width.
```
<nav>
    <Sidebar @rail="rail = $event" />
</nav>
<main>
    <Header />
    <div :class="{ 'main__content': true, 'main__content--rail': !rail }">
        <RouterView />
    </div>
</main>
```
Awesome! Much better, here is the result.
![Main Dashboard page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ivv3jn4dxo6icwntg09y.png)
In this comprehensive guide, we initiated the construction of a Simple CRM with Vue, focusing on the pivotal elements of layouts and navigation. Beginning with an overview of the project's fundamentals, we delved into the creation of the main "Dashboard" page and the significance of crafting user-friendly layouts. The post further explored the intricacies of CRM navigation, showcasing the implementation of a sidebar and header with dropdown functionality. Practical examples, code snippets, and seamless integration of Vuetify components enriched the learning experience. As we continue through the Vue.js development journey, stay tuned for more insights and step-by-step guidance.