refactor: app sidebar
This commit is contained in:
parent
9ffe08a13b
commit
ffe24b9c0d
@ -3,81 +3,50 @@
|
||||
class="flex h-full flex-col justify-between transition-all duration-300 ease-in-out"
|
||||
:class="isSidebarCollapsed ? 'w-12' : 'w-56'"
|
||||
>
|
||||
<div class="flex flex-1 flex-col overflow-hidden">
|
||||
<div>
|
||||
<UserDropdown class="p-2" :isCollapsed="isSidebarCollapsed" />
|
||||
<div class="flex flex-col overflow-y-auto">
|
||||
<SidebarLink
|
||||
v-for="link in links"
|
||||
:icon="link.icon"
|
||||
:label="link.label"
|
||||
:to="link.to"
|
||||
:isCollapsed="isSidebarCollapsed"
|
||||
class="mx-2 my-0.5"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="isSidebarCollapsed && getPublicViews().length"
|
||||
class="mx-2 my-2 h-1 border-b"
|
||||
/>
|
||||
<div
|
||||
v-if="getPublicViews().length"
|
||||
class="px-3 text-base text-gray-600 transition-all duration-300 ease-in-out"
|
||||
:class="
|
||||
isSidebarCollapsed
|
||||
? 'ml-0 h-0 overflow-hidden opacity-0'
|
||||
: 'ml-2 h-7 w-auto opacity-100 mt-4'
|
||||
"
|
||||
>
|
||||
Public Views
|
||||
</div>
|
||||
<div v-if="getPublicViews().length" class="flex flex-col overflow-y-auto">
|
||||
<SidebarLink
|
||||
v-for="publicView in getPublicViews()"
|
||||
:icon="
|
||||
h(getIcon(publicView.route_name), {
|
||||
class: 'h-4.5 w-4.5 text-gray-700',
|
||||
})
|
||||
"
|
||||
:label="publicView.label"
|
||||
:to="{
|
||||
name: publicView.route_name,
|
||||
query: { view: publicView.name },
|
||||
}"
|
||||
:isCollapsed="isSidebarCollapsed"
|
||||
class="mx-2 my-0.5"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="isSidebarCollapsed && getPinnedViews().length"
|
||||
class="mx-2 my-2 h-1 border-b"
|
||||
/>
|
||||
<div
|
||||
v-if="getPinnedViews().length"
|
||||
class="px-3 text-base text-gray-600 transition-all duration-300 ease-in-out"
|
||||
:class="
|
||||
isSidebarCollapsed
|
||||
? 'ml-0 h-0 overflow-hidden opacity-0'
|
||||
: 'ml-2 h-7 w-auto opacity-100 mt-4'
|
||||
"
|
||||
>
|
||||
Pinned Views
|
||||
</div>
|
||||
<div v-if="getPinnedViews().length" class="flex flex-col overflow-y-auto">
|
||||
<SidebarLink
|
||||
v-for="pinnedView in getPinnedViews()"
|
||||
:icon="
|
||||
h(getIcon(pinnedView.route_name), {
|
||||
class: 'h-4.5 w-4.5 text-gray-700',
|
||||
})
|
||||
"
|
||||
:label="pinnedView.label"
|
||||
:to="{
|
||||
name: pinnedView.route_name,
|
||||
query: { view: pinnedView.name },
|
||||
}"
|
||||
:isCollapsed="isSidebarCollapsed"
|
||||
class="mx-2 my-0.5"
|
||||
</div>
|
||||
<div class="flex-1 overflow-y-auto">
|
||||
<div v-for="view in allViews" :key="view.label">
|
||||
<div
|
||||
v-if="!view.hideLabel && isSidebarCollapsed && view.views?.length"
|
||||
class="mx-2 my-2 h-1 border-b"
|
||||
/>
|
||||
<Section
|
||||
:label="view.name"
|
||||
:hideLabel="view.hideLabel"
|
||||
:isOpened="view.opened"
|
||||
>
|
||||
<template #header="{ opened, hide, toggle }">
|
||||
<div
|
||||
v-if="!hide"
|
||||
class="flex cursor-pointer gap-1.5 px-1 text-sm font-medium text-gray-600 transition-all duration-300 ease-in-out"
|
||||
:class="
|
||||
isSidebarCollapsed
|
||||
? 'ml-0 h-0 overflow-hidden opacity-0'
|
||||
: 'ml-2 mt-4 h-7 w-auto opacity-100'
|
||||
"
|
||||
@click="toggle()"
|
||||
>
|
||||
<FeatherIcon
|
||||
name="chevron-right"
|
||||
class="h-4 text-gray-900 transition-all duration-300 ease-in-out"
|
||||
:class="{ 'rotate-90': opened }"
|
||||
/>
|
||||
{{ view.name }}
|
||||
</div>
|
||||
</template>
|
||||
<nav class="flex flex-col">
|
||||
<SidebarLink
|
||||
v-for="link in view.views"
|
||||
:icon="link.icon"
|
||||
:label="link.label"
|
||||
:to="link.to"
|
||||
:isCollapsed="isSidebarCollapsed"
|
||||
class="mx-2 my-0.5"
|
||||
/>
|
||||
</nav>
|
||||
</Section>
|
||||
</div>
|
||||
</div>
|
||||
<SidebarLink
|
||||
@ -99,6 +68,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Section from '@/components/Section.vue'
|
||||
import EmailIcon from '@/components/Icons/EmailIcon.vue'
|
||||
import PinIcon from '@/components/Icons/PinIcon.vue'
|
||||
import UserDropdown from '@/components/UserDropdown.vue'
|
||||
@ -112,9 +82,10 @@ import CollapseSidebar from '@/components/Icons/CollapseSidebar.vue'
|
||||
import SidebarLink from '@/components/SidebarLink.vue'
|
||||
import { viewsStore } from '@/stores/views'
|
||||
import { useStorage } from '@vueuse/core'
|
||||
import { h } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const { getPinnedViews, getPublicViews } = viewsStore()
|
||||
const isSidebarCollapsed = useStorage('sidebar_is_collapsed', false)
|
||||
|
||||
const links = [
|
||||
{
|
||||
@ -154,6 +125,40 @@ const links = [
|
||||
},
|
||||
]
|
||||
|
||||
const allViews = computed(() => {
|
||||
return [
|
||||
{
|
||||
name: 'All Views',
|
||||
hideLabel: true,
|
||||
opened: true,
|
||||
views: links,
|
||||
},
|
||||
{
|
||||
name: 'PULIC VIEWS',
|
||||
opened: true,
|
||||
views: parseView(getPublicViews()),
|
||||
},
|
||||
{
|
||||
name: 'PINNED VIEWS',
|
||||
opened: true,
|
||||
views: parseView(getPinnedViews()),
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
function parseView(views) {
|
||||
return views.map((view) => {
|
||||
return {
|
||||
label: view.label,
|
||||
icon: getIcon(view.route_name),
|
||||
to: {
|
||||
name: view.route_name,
|
||||
query: { view: view.name },
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getIcon(routeName) {
|
||||
switch (routeName) {
|
||||
case 'Leads':
|
||||
@ -172,6 +177,4 @@ function getIcon(routeName) {
|
||||
return PinIcon
|
||||
}
|
||||
}
|
||||
|
||||
const isSidebarCollapsed = useStorage('sidebar_is_collapsed', false)
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<slot name="header" v-bind="{ opened, open, close, toggle }">
|
||||
<div class="flex items-center justify-between">
|
||||
<slot name="header" v-bind="{ opened, hide, open, close, toggle }">
|
||||
<div v-if="!hide" class="flex items-center justify-between">
|
||||
<div
|
||||
class="flex h-7 max-w-fit cursor-pointer items-center gap-2 pl-2 pr-3 text-base font-semibold leading-5"
|
||||
@click="toggle()"
|
||||
@ -35,6 +35,10 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
hideLabel: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isOpened: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
@ -51,5 +55,7 @@ function open() {
|
||||
function close() {
|
||||
opened.value = false
|
||||
}
|
||||
|
||||
let opened = ref(props.isOpened)
|
||||
let hide = ref(props.hideLabel)
|
||||
</script>
|
||||
|
||||
@ -11,12 +11,12 @@
|
||||
<Tooltip :text="label" placement="right">
|
||||
<slot name="icon">
|
||||
<span class="grid h-5 w-6 flex-shrink-0 place-items-center">
|
||||
<component :is="icon" class="h-4.5 w-4.5 text-gray-700" />
|
||||
<component :is="icon" class="h-4 w-4 text-gray-700" />
|
||||
</span>
|
||||
</slot>
|
||||
</Tooltip>
|
||||
<span
|
||||
class="flex-shrink-0 text-base duration-300 ease-in-out"
|
||||
class="flex-shrink-0 text-sm duration-300 ease-in-out"
|
||||
:class="
|
||||
isCollapsed
|
||||
? 'ml-0 w-0 overflow-hidden opacity-0'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user