203 lines
5.6 KiB
Vue
203 lines
5.6 KiB
Vue
<script setup>
|
|
import { computed } from 'vue';
|
|
import { useRoute } from 'vue-router';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { useAuthStore } from '@/features/auth/stores/authStore.js';
|
|
import WorkspaceSelector from './WorkspaceSelector.vue';
|
|
import {
|
|
mdiCogOutline,
|
|
mdiLogin,
|
|
mdiPlus,
|
|
} from '@mdi/js';
|
|
|
|
const props = defineProps({
|
|
showBrand: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
collapseBrand: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
});
|
|
|
|
const route = useRoute();
|
|
const { t } = useI18n();
|
|
const authStore = useAuthStore();
|
|
|
|
const appBarActions = computed(() => {
|
|
if (!authStore.isAuthenticated) {
|
|
return [];
|
|
}
|
|
|
|
switch (route.name) {
|
|
case 'workspace-dashboard':
|
|
case 'content-items':
|
|
return authStore.isManager || authStore.isProvider
|
|
? [{
|
|
key: 'create-content',
|
|
label: t('contentItems.newItem'),
|
|
icon: mdiPlus,
|
|
route: { name: 'content-item-create' },
|
|
}]
|
|
: [];
|
|
case 'campaigns':
|
|
return [{
|
|
key: 'create-campaign',
|
|
label: t('projects.newProject'),
|
|
icon: mdiPlus,
|
|
route: { name: 'campaigns', query: { create: 'true' } },
|
|
}];
|
|
case 'channels':
|
|
return [{
|
|
key: 'create-channel',
|
|
label: t('channels.createTitle'),
|
|
icon: mdiPlus,
|
|
route: { name: 'channels', query: { create: 'true' } },
|
|
}];
|
|
case 'workspace-settings':
|
|
case 'settings-user-information':
|
|
case 'settings-workspaces':
|
|
case 'settings-integrations':
|
|
return [{
|
|
key: 'settings',
|
|
label: t('nav.settings'),
|
|
icon: mdiCogOutline,
|
|
route: { name: 'settings-user-information' },
|
|
}];
|
|
default:
|
|
return [];
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<nav class="side-container">
|
|
<div class="brand-block">
|
|
<router-link
|
|
v-if="showBrand"
|
|
class="brand-link"
|
|
:class="{ 'brand-link-collapsed': collapseBrand }"
|
|
to="/"
|
|
>
|
|
<span class="brand-mark">S</span>
|
|
<div v-if="!collapseBrand">
|
|
<div class="brand-name">Socialize</div>
|
|
<div class="brand-caption">{{ t('nav.brandCaption') }}</div>
|
|
</div>
|
|
</router-link>
|
|
</div>
|
|
|
|
<div class="side-menu">
|
|
<div class="side-menu-items side-menu-left">
|
|
<WorkspaceSelector
|
|
v-if="authStore.isAuthenticated"
|
|
/>
|
|
</div>
|
|
|
|
<div class="side-menu-items side-menu-right">
|
|
<template v-if="!authStore.isAuthenticated">
|
|
<router-link to="/login">
|
|
<button class="menu-item-action">
|
|
<v-icon :icon="mdiLogin" />
|
|
<span class="label">{{ t('nav.signIn') }}</span>
|
|
</button>
|
|
</router-link>
|
|
</template>
|
|
|
|
<router-link
|
|
v-for="action in appBarActions"
|
|
:key="action.key"
|
|
:to="action.route"
|
|
class="menu-action-link"
|
|
>
|
|
<button class="menu-item-action">
|
|
<v-icon :icon="action.icon" />
|
|
<span class="label">{{ action.label }}</span>
|
|
</button>
|
|
</router-link>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.side-container {
|
|
@apply sticky top-0 z-10 flex flex-col gap-4 px-5 py-4 md:flex-row md:items-center md:justify-between;
|
|
background: rgba(255, 250, 242, 0.82);
|
|
backdrop-filter: blur(18px);
|
|
border-bottom: 1px solid rgba(23, 32, 51, 0.08);
|
|
isolation: isolate;
|
|
}
|
|
|
|
.brand-block {
|
|
@apply flex items-center gap-3;
|
|
}
|
|
|
|
.brand-link {
|
|
@apply flex items-center gap-3 no-underline;
|
|
color: inherit;
|
|
}
|
|
|
|
.brand-link-collapsed {
|
|
@apply gap-0;
|
|
}
|
|
|
|
.brand-mark {
|
|
@apply flex h-11 w-11 items-center justify-center rounded-2xl text-lg font-black;
|
|
background: linear-gradient(135deg, #ff8a3d 0%, #ef4444 100%);
|
|
color: #fffaf2;
|
|
}
|
|
|
|
.brand-name {
|
|
@apply text-lg font-black uppercase tracking-[0.18em];
|
|
color: #172033;
|
|
}
|
|
|
|
.brand-caption {
|
|
@apply text-xs uppercase tracking-[0.24em];
|
|
color: #5d6b82;
|
|
}
|
|
|
|
.side-menu {
|
|
@apply flex flex-1 items-center justify-between gap-3;
|
|
}
|
|
|
|
.side-menu-items {
|
|
@apply flex flex-wrap items-center justify-end gap-2;
|
|
overflow: visible;
|
|
}
|
|
|
|
.side-menu-left {
|
|
@apply justify-start;
|
|
}
|
|
|
|
.side-menu-right {
|
|
@apply justify-end;
|
|
}
|
|
|
|
.label {
|
|
@apply hidden text-nowrap md:inline;
|
|
}
|
|
|
|
.menu-item-action {
|
|
@apply flex h-11 items-center gap-3 rounded-full px-4 transition-colors;
|
|
background: rgba(255, 255, 255, 0.8);
|
|
color: #172033;
|
|
border: 1px solid rgba(23, 32, 51, 0.06);
|
|
}
|
|
|
|
.menu-item-action:hover {
|
|
background: #172033;
|
|
color: #fffaf2;
|
|
}
|
|
|
|
.menu-item-action i {
|
|
@apply text-xl;
|
|
}
|
|
|
|
.menu-action-link {
|
|
@apply no-underline;
|
|
}
|
|
</style>
|