104 lines
3.1 KiB
Vue
104 lines
3.1 KiB
Vue
<template>
|
|
<v-app>
|
|
<div class="shell-container">
|
|
<app-bar
|
|
:show-brand="true"
|
|
:collapse-brand="showsAppSidebar && !isSidebarExpanded"
|
|
/>
|
|
|
|
<div
|
|
class="shell-main"
|
|
:class="{ 'shell-main-app': showsAppSidebar }"
|
|
>
|
|
<template v-if="showsAppSidebar">
|
|
<div class="shell-sidebar-wrap">
|
|
<app-sidebar :is-expanded="isSidebarExpanded" />
|
|
|
|
<button
|
|
class="sidebar-boundary-toggle"
|
|
type="button"
|
|
@click="isSidebarExpanded = !isSidebarExpanded"
|
|
>
|
|
<v-icon :icon="isSidebarExpanded ? mdiChevronLeft : mdiChevronRight" />
|
|
</button>
|
|
</div>
|
|
</template>
|
|
|
|
<div class="shell-view">
|
|
<router-view></router-view>
|
|
</div>
|
|
</div>
|
|
|
|
<FeedbackFloatingButton v-if="showsAppSidebar" />
|
|
</div>
|
|
</v-app>
|
|
</template>
|
|
|
|
<script async setup>
|
|
import { computed, ref, watch } from 'vue';
|
|
import { useRoute } from 'vue-router';
|
|
import { useAuthStore } from '@/features/auth/stores/authStore.js';
|
|
import { mdiChevronLeft, mdiChevronRight } from '@mdi/js';
|
|
import AppBar from '@/layouts/main/AppBar.vue';
|
|
import AppSidebar from '@/layouts/main/AppSidebar.vue';
|
|
import FeedbackFloatingButton from '@/features/feedback/components/FeedbackFloatingButton.vue';
|
|
|
|
const route = useRoute();
|
|
const authStore = useAuthStore();
|
|
const isSidebarExpanded = ref(true);
|
|
|
|
const showsAppSidebar = computed(() =>
|
|
authStore.isAuthenticated && route.path.startsWith('/app')
|
|
);
|
|
|
|
watch(showsAppSidebar, value => {
|
|
if (!value) {
|
|
isSidebarExpanded.value = true;
|
|
return;
|
|
}
|
|
|
|
isSidebarExpanded.value = true;
|
|
}, { immediate: true });
|
|
</script>
|
|
|
|
<style scoped>
|
|
.shell-container {
|
|
@apply min-h-screen flex flex-col;
|
|
@apply w-full font-sans;
|
|
background:
|
|
radial-gradient(circle at top left, rgba(255, 174, 94, 0.18), transparent 28%),
|
|
radial-gradient(circle at top right, rgba(52, 211, 153, 0.16), transparent 24%),
|
|
linear-gradient(180deg, #fffaf2 0%, #f6efe2 100%);
|
|
color: #172033;
|
|
}
|
|
|
|
.shell-main {
|
|
@apply relative flex flex-1 flex-col;
|
|
}
|
|
|
|
.shell-main-app {
|
|
@apply md:flex-row md:items-start;
|
|
}
|
|
|
|
.shell-sidebar-wrap {
|
|
@apply relative flex-shrink-0;
|
|
}
|
|
|
|
.sidebar-boundary-toggle {
|
|
@apply absolute left-full top-8 z-10 flex h-10 w-10 -translate-x-1/2 items-center justify-center rounded-full border transition-colors;
|
|
background: rgba(255, 250, 242, 0.98);
|
|
border-color: rgba(23, 32, 51, 0.12);
|
|
color: #44516a;
|
|
box-shadow: 0 12px 28px rgba(23, 32, 51, 0.12);
|
|
}
|
|
|
|
.sidebar-boundary-toggle:hover {
|
|
background: #172033;
|
|
color: #fffaf2;
|
|
}
|
|
|
|
.shell-view {
|
|
@apply flex min-w-0 flex-1;
|
|
}
|
|
</style>
|