fix: build the layout with sidebar and navigation links
This commit is contained in:
parent
4c6ae54615
commit
54f298e54c
@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html class="h-full" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Frappe CRM</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<body class="h-full">
|
||||
<div id="app" class="h-full"></div>
|
||||
<div id="modals"></div>
|
||||
<div id="popovers"></div>
|
||||
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<DesktopLayout>
|
||||
<router-view />
|
||||
</div>
|
||||
</DesktopLayout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import DesktopLayout from '@/components/DesktopLayout.vue'
|
||||
</script>
|
||||
|
||||
65
frontend/src/components/AppSidebar.vue
Normal file
65
frontend/src/components/AppSidebar.vue
Normal file
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div class="inline-flex h-full flex-col border-r w-[220px]">
|
||||
<div class="flex p-2">
|
||||
<h1 class="text-xl px-3 py-2">Frappe CRM</h1>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<nav class="space-y-0.5 px-2">
|
||||
<div v-for="link in navigations" :key="link.name">
|
||||
<router-link
|
||||
custom
|
||||
:to="link.route"
|
||||
v-slot="{ href, isActive, navigate }"
|
||||
>
|
||||
<a
|
||||
:href="href"
|
||||
@click="navigate"
|
||||
class="flex items-center rounded px-2 py-1 text-gray-800 transition-all duration-300 ease-in-out"
|
||||
:class="[isActive ? 'bg-gray-100 hover:bg-gray-200' : 'hover:bg-gray-50']"
|
||||
>
|
||||
<div class="flex w-full items-center space-x-2">
|
||||
<span class="grid h-5 w-6 place-items-center">
|
||||
<component
|
||||
:is="link.icon"
|
||||
class="h-4.5 w-4.5 text-gray-700"
|
||||
/>
|
||||
</span>
|
||||
<span class="text-base">{{ link.name }}</span>
|
||||
</div>
|
||||
</a>
|
||||
</router-link>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import LeadsIcon from './Icons/LeadsIcon.vue'
|
||||
import DealsIcon from './Icons/DealsIcon.vue'
|
||||
import InboxIcon from './Icons/InboxIcon.vue'
|
||||
import DashboardIcon from './Icons/DashboardIcon.vue'
|
||||
|
||||
const navigations = [
|
||||
{
|
||||
name: 'Inbox',
|
||||
icon: InboxIcon,
|
||||
route: { name: 'Inbox' },
|
||||
},
|
||||
{
|
||||
name: 'Leads',
|
||||
icon: LeadsIcon,
|
||||
route: { name: 'Leads' },
|
||||
},
|
||||
{
|
||||
name: 'Deals',
|
||||
icon: DealsIcon,
|
||||
route: { name: 'Deals' },
|
||||
},
|
||||
{
|
||||
name: 'Dashboard',
|
||||
icon: DashboardIcon,
|
||||
route: { name: 'Dashboard' },
|
||||
},
|
||||
]
|
||||
</script>
|
||||
13
frontend/src/components/DesktopLayout.vue
Normal file
13
frontend/src/components/DesktopLayout.vue
Normal file
@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div class="flex h-full">
|
||||
<div>
|
||||
<AppSidebar />
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import AppSidebar from './AppSidebar.vue'
|
||||
</script>
|
||||
19
frontend/src/components/Icons/DashboardIcon.vue
Normal file
19
frontend/src/components/Icons/DashboardIcon.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.25"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-layout-grid"
|
||||
>
|
||||
<rect width="7" height="7" x="3" y="3" rx="1" />
|
||||
<rect width="7" height="7" x="14" y="3" rx="1" />
|
||||
<rect width="7" height="7" x="14" y="14" rx="1" />
|
||||
<rect width="7" height="7" x="3" y="14" rx="1" />
|
||||
</svg>
|
||||
</template>
|
||||
10
frontend/src/components/Icons/DealsIcon.vue
Normal file
10
frontend/src/components/Icons/DealsIcon.vue
Normal file
@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none">
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M9.23906 2.91049c.12084-.14098.35185-.05552.35185.13016v4.18662h5.47429c.1708 0 .263.20043.1518.33016L8.76094 15.0895c-.12084.141-.35185.0555-.35185-.1302v-4.1866H2.93484c-.17087 0-.26305-.2004-.15185-.3301l6.45607-7.53211Z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
16
frontend/src/components/Icons/InboxIcon.vue
Normal file
16
frontend/src/components/Icons/InboxIcon.vue
Normal file
@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M3.90178 4.84522C4.17516 4.03047 4.93848 3.48145 5.79788 3.48145H12.2015C13.061 3.48145 13.8243 4.03052 14.0977 4.84532L15.5044 9.03864H13.3465C12.6518 9.03864 12.0136 9.42111 11.686 10.0337C11.5324 10.321 11.2331 10.5003 10.9074 10.5003H7.39048C6.99595 10.5003 6.62635 10.3074 6.40081 9.98364C5.98829 9.39155 5.31228 9.03864 4.59065 9.03864H2.49471L3.90178 4.84522ZM2.29956 10.0386V12.9386C2.29956 13.767 2.97113 14.4386 3.79956 14.4386H14.1996C15.028 14.4386 15.6996 13.767 15.6996 12.9386V10.0386H13.3465C13.0208 10.0386 12.7215 10.218 12.5678 10.5052C12.2403 11.1178 11.602 11.5003 10.9074 11.5003H7.39048C6.66886 11.5003 5.99284 11.1474 5.58032 10.5553C5.35478 10.2316 4.98519 10.0386 4.59065 10.0386H2.29956ZM5.79788 2.48145C4.50879 2.48145 3.3638 3.30497 2.95372 4.52711L1.37748 9.22471C1.32588 9.37851 1.29956 9.53966 1.29956 9.70188V12.9386C1.29956 14.3193 2.41885 15.4386 3.79956 15.4386H14.1996C15.5803 15.4386 16.6996 14.3193 16.6996 12.9386V9.70185C16.6996 9.53965 16.6733 9.37853 16.6217 9.22476L15.0457 4.52726C14.6357 3.30505 13.4907 2.48145 12.2015 2.48145H5.79788Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
21
frontend/src/components/Icons/LeadsIcon.vue
Normal file
21
frontend/src/components/Icons/LeadsIcon.vue
Normal file
@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12.6562 13.7812H13.5725H15.052C16.1315 13.7812 16.9335 12.7815 16.6993 11.7277L16.6179 11.3616C16.2748 9.81742 14.9051 8.71875 13.3233 8.71875H10.8629C10.4404 8.71875 10.033 8.79714 9.65626 8.94148C9.4976 9.00227 9.34438 9.07475 9.19775 9.158"
|
||||
stroke="currentColor"
|
||||
/>
|
||||
<circle cx="6.46875" cy="6.1875" r="2.03125" stroke="currentColor" />
|
||||
<circle cx="12.375" cy="4.78125" r="1.75" stroke="currentColor" />
|
||||
<path
|
||||
d="M2.0092 12.7555C2.31423 11.3828 3.53167 10.4062 4.93776 10.4062H7.99974C9.40583 10.4062 10.6233 11.3828 10.9283 12.7555L11.1256 13.6434C11.3338 14.5801 10.6209 15.4688 9.66133 15.4688H3.27617C2.31655 15.4688 1.60372 14.5801 1.81189 13.6434L2.0092 12.7555Z"
|
||||
fill="white"
|
||||
stroke="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
9
frontend/src/pages/Dashboard.vue
Normal file
9
frontend/src/pages/Dashboard.vue
Normal file
@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div class="px-6 py-4 font-semibold text-xl">
|
||||
<h1>{{ title }}</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
let title = 'Dashboard'
|
||||
</script>
|
||||
9
frontend/src/pages/Deals.vue
Normal file
9
frontend/src/pages/Deals.vue
Normal file
@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div class="px-6 py-4 font-semibold text-xl">
|
||||
<h1>{{ title }}</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
let title = 'Deals'
|
||||
</script>
|
||||
@ -1,9 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>{{ app_name }}</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
let app_name = 'Frappe CRM'
|
||||
</script>
|
||||
9
frontend/src/pages/Inbox.vue
Normal file
9
frontend/src/pages/Inbox.vue
Normal file
@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div class="px-6 py-4 font-semibold text-xl">
|
||||
<h1>{{ title }}</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
let title = 'Inbox'
|
||||
</script>
|
||||
9
frontend/src/pages/Leads.vue
Normal file
9
frontend/src/pages/Leads.vue
Normal file
@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div class="px-6 py-4 font-semibold text-xl">
|
||||
<h1>{{ title }}</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
let title = 'Leads'
|
||||
</script>
|
||||
@ -3,13 +3,32 @@ import { createRouter, createWebHistory } from 'vue-router'
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
component: () => import('@/pages/Home.vue'),
|
||||
redirect: '/leads',
|
||||
},
|
||||
{
|
||||
path: '/leads',
|
||||
name: 'Leads',
|
||||
component: () => import('@/pages/Leads.vue'),
|
||||
},
|
||||
{
|
||||
path: '/deals',
|
||||
name: 'Deals',
|
||||
component: () => import('@/pages/Deals.vue'),
|
||||
},
|
||||
{
|
||||
path: '/inbox',
|
||||
name: 'Inbox',
|
||||
component: () => import('@/pages/Inbox.vue'),
|
||||
},
|
||||
{
|
||||
path: '/dashboard',
|
||||
name: 'Dashboard',
|
||||
component: () => import('@/pages/Dashboard.vue'),
|
||||
},
|
||||
]
|
||||
|
||||
let router = createRouter({
|
||||
history: createWebHistory('/frontend'),
|
||||
history: createWebHistory('/crm'),
|
||||
routes,
|
||||
})
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user