Files
social-media/frontend/src/layouts/main/AppBar.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>