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="flex h-full flex-col justify-between transition-all duration-300 ease-in-out"
|
||||||
:class="isSidebarCollapsed ? 'w-12' : 'w-56'"
|
:class="isSidebarCollapsed ? 'w-12' : 'w-56'"
|
||||||
>
|
>
|
||||||
<div class="flex flex-1 flex-col overflow-hidden">
|
<div>
|
||||||
<UserDropdown class="p-2" :isCollapsed="isSidebarCollapsed" />
|
<UserDropdown class="p-2" :isCollapsed="isSidebarCollapsed" />
|
||||||
<div class="flex flex-col overflow-y-auto">
|
</div>
|
||||||
<SidebarLink
|
<div class="flex-1 overflow-y-auto">
|
||||||
v-for="link in links"
|
<div v-for="view in allViews" :key="view.label">
|
||||||
:icon="link.icon"
|
<div
|
||||||
:label="link.label"
|
v-if="!view.hideLabel && isSidebarCollapsed && view.views?.length"
|
||||||
:to="link.to"
|
class="mx-2 my-2 h-1 border-b"
|
||||||
: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"
|
|
||||||
/>
|
/>
|
||||||
|
<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>
|
||||||
</div>
|
</div>
|
||||||
<SidebarLink
|
<SidebarLink
|
||||||
@ -99,6 +68,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import Section from '@/components/Section.vue'
|
||||||
import EmailIcon from '@/components/Icons/EmailIcon.vue'
|
import EmailIcon from '@/components/Icons/EmailIcon.vue'
|
||||||
import PinIcon from '@/components/Icons/PinIcon.vue'
|
import PinIcon from '@/components/Icons/PinIcon.vue'
|
||||||
import UserDropdown from '@/components/UserDropdown.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 SidebarLink from '@/components/SidebarLink.vue'
|
||||||
import { viewsStore } from '@/stores/views'
|
import { viewsStore } from '@/stores/views'
|
||||||
import { useStorage } from '@vueuse/core'
|
import { useStorage } from '@vueuse/core'
|
||||||
import { h } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const { getPinnedViews, getPublicViews } = viewsStore()
|
const { getPinnedViews, getPublicViews } = viewsStore()
|
||||||
|
const isSidebarCollapsed = useStorage('sidebar_is_collapsed', false)
|
||||||
|
|
||||||
const links = [
|
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) {
|
function getIcon(routeName) {
|
||||||
switch (routeName) {
|
switch (routeName) {
|
||||||
case 'Leads':
|
case 'Leads':
|
||||||
@ -172,6 +177,4 @@ function getIcon(routeName) {
|
|||||||
return PinIcon
|
return PinIcon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSidebarCollapsed = useStorage('sidebar_is_collapsed', false)
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<slot name="header" v-bind="{ opened, open, close, toggle }">
|
<slot name="header" v-bind="{ opened, hide, open, close, toggle }">
|
||||||
<div class="flex items-center justify-between">
|
<div v-if="!hide" class="flex items-center justify-between">
|
||||||
<div
|
<div
|
||||||
class="flex h-7 max-w-fit cursor-pointer items-center gap-2 pl-2 pr-3 text-base font-semibold leading-5"
|
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()"
|
@click="toggle()"
|
||||||
@ -35,6 +35,10 @@ const props = defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
hideLabel: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
isOpened: {
|
isOpened: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
@ -51,5 +55,7 @@ function open() {
|
|||||||
function close() {
|
function close() {
|
||||||
opened.value = false
|
opened.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
let opened = ref(props.isOpened)
|
let opened = ref(props.isOpened)
|
||||||
|
let hide = ref(props.hideLabel)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -11,12 +11,12 @@
|
|||||||
<Tooltip :text="label" placement="right">
|
<Tooltip :text="label" placement="right">
|
||||||
<slot name="icon">
|
<slot name="icon">
|
||||||
<span class="grid h-5 w-6 flex-shrink-0 place-items-center">
|
<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>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<span
|
<span
|
||||||
class="flex-shrink-0 text-base duration-300 ease-in-out"
|
class="flex-shrink-0 text-sm duration-300 ease-in-out"
|
||||||
:class="
|
:class="
|
||||||
isCollapsed
|
isCollapsed
|
||||||
? 'ml-0 w-0 overflow-hidden opacity-0'
|
? 'ml-0 w-0 overflow-hidden opacity-0'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user