MainLayout.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <template>
  2. <q-layout class="relative" view="hHh lpR fFf">
  3. <LeftMenuLayout v-if="!$q.screen.lt.sm" />
  4. <LeftMenuLayoutMobile v-else v-model="leftDrawerOpen" />
  5. <q-header v-if="$q.screen.lt.sm" class="bg-transparent q-pa-sm">
  6. <q-toolbar
  7. class="flex justify-between bg-surface"
  8. style="border-radius: 6px !important"
  9. >
  10. <q-btn dense flat @click="toggleLeftDrawer">
  11. <q-icon name="menu" :color="$q.dark.isActive ? 'white' : 'black'" />
  12. </q-btn>
  13. <q-btn dense flat>
  14. <img
  15. :src="someAvatar()"
  16. alt="avatar"
  17. style="width: 20px; height: 20px; border-radius: 50%"
  18. />
  19. <q-menu anchor="center right" self="top start">
  20. <q-list class="column no-wrap overflow-hidden">
  21. <q-item
  22. v-ripple
  23. v-close-popup
  24. clickable
  25. :to="{ name: 'ProfilePage' }"
  26. exact
  27. exact-active-class="menu-selected"
  28. >
  29. <div class="flex">
  30. <q-item-section avatar>
  31. <q-icon
  32. name="account_circle"
  33. color="primary"
  34. style="font-size: 18px"
  35. />
  36. </q-item-section>
  37. <q-item-section>{{
  38. $t("user.profile.singular")
  39. }}</q-item-section>
  40. </div>
  41. </q-item>
  42. <q-item v-ripple clickable @click="logoutFn">
  43. <div class="flex">
  44. <q-item-section avatar>
  45. <q-icon
  46. name="logout"
  47. color="negative"
  48. style="font-size: 18px"
  49. />
  50. </q-item-section>
  51. <q-item-section>{{ $t("auth.logout") }}</q-item-section>
  52. </div>
  53. </q-item>
  54. </q-list>
  55. </q-menu>
  56. </q-btn>
  57. </q-toolbar>
  58. </q-header>
  59. <q-page-container>
  60. <q-page>
  61. <q-scroll-area
  62. ref="scrollAreaRef"
  63. :style="
  64. $q.screen.lt.sm
  65. ? 'height: calc(100dvh - 68px - env(safe-area-inset-top)) !important;'
  66. : 'height: calc(100dvh - env(safe-area-inset-top)) !important;'
  67. "
  68. >
  69. <router-view v-slot="{ Component }">
  70. <Transition mode="out-in">
  71. <component
  72. :is="Component"
  73. style="padding: 20px !important; padding-right: 10px !important"
  74. :style="$q.screen.lt.sm ? 'padding-left: 10px !important;' : ''"
  75. />
  76. </Transition>
  77. </router-view>
  78. </q-scroll-area>
  79. </q-page>
  80. </q-page-container>
  81. </q-layout>
  82. </template>
  83. <script setup>
  84. import { ref, useTemplateRef, watch } from "vue";
  85. import { useRoute } from "vue-router";
  86. import { useAuth } from "src/composables/useAuth";
  87. import { useRouter } from "vue-router";
  88. import LeftMenuLayout from "src/components/layout/LeftMenuLayout.vue";
  89. import LeftMenuLayoutMobile from "src/components/layout/LeftMenuLayoutMobile.vue";
  90. defineOptions({
  91. name: "MainLayout",
  92. });
  93. const { logout } = useAuth();
  94. const route = useRoute();
  95. const leftDrawerOpen = ref(false);
  96. const scrollAreaRef = useTemplateRef("scrollAreaRef");
  97. const router = useRouter();
  98. let oldValue = route.path;
  99. const someAvatar = () => {
  100. return "https://cdn.quasar.dev/img/avatar4.jpg";
  101. };
  102. const logoutFn = async () => {
  103. await logout();
  104. router.push({ name: "LoginPage" });
  105. };
  106. const toggleLeftDrawer = () => {
  107. leftDrawerOpen.value = !leftDrawerOpen.value;
  108. };
  109. watch(route, (value) => {
  110. if (oldValue.path != value.path) {
  111. scrollAreaRef.value.setScrollPosition("vertical", 0, 0);
  112. scrollAreaRef.value.setScrollPosition("horizontal", 0, 0);
  113. }
  114. oldValue = value.path;
  115. });
  116. </script>
  117. <style scoped>
  118. .v-enter-active {
  119. opacity: 1;
  120. transition: all 0.15s ease-in;
  121. }
  122. .v-leave-active {
  123. opacity: 1;
  124. transition: all 0.15s ease-out;
  125. }
  126. .v-enter-from,
  127. .v-leave-to {
  128. opacity: 0;
  129. transition: all 0.15s ease-in;
  130. }
  131. .v-leave-to {
  132. transition: all 0.15s ease-out;
  133. }
  134. </style>