LeftMenuLayout.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <template>
  2. <q-drawer
  3. v-model="leftDrawerOpen"
  4. show-if-above
  5. :mini="miniState"
  6. mini-to-overlay
  7. :width="250"
  8. :breakpoint="500"
  9. bordered
  10. class="bg-drawer"
  11. @mouseover="miniState = false"
  12. @mouseout="miniState = true"
  13. >
  14. <q-scroll-area style="height: calc(100vh - 100px)">
  15. <q-list class="column no-wrap" style="height: calc(100vh - 100px)">
  16. <template v-for="menu in menus" :key="menu.name">
  17. <!-- * Single menu -->
  18. <q-item
  19. v-if="menu.type == 'single' && menu.permission"
  20. v-ripple
  21. clickable
  22. :to="{ name: menu.name }"
  23. :disable="menu.disable"
  24. class="text-subtitle1"
  25. exact-active-class="menu-selected"
  26. exact
  27. active-class="menu-selected"
  28. >
  29. <q-item-section avatar>
  30. <q-icon :name="menu.icon" />
  31. </q-item-section>
  32. <q-item-section> {{ menu.title }} </q-item-section>
  33. </q-item>
  34. <q-expansion-item
  35. v-if="menu.type == 'expansive' && menu.permission"
  36. expand-separator
  37. header-class="text-subtitle1"
  38. :icon="menu.icon"
  39. :label="menu.title"
  40. :content-inset-level="0.4"
  41. :disable="menu.disable"
  42. >
  43. <template v-for="children in menu.childrens" :key="children.name">
  44. <q-item
  45. v-if="children.permission"
  46. v-ripple
  47. clickable
  48. :to="{ name: children.name }"
  49. :disable="children.disable"
  50. class="text-subtitle1"
  51. exact-active-class="menu-selected"
  52. >
  53. <q-item-section avatar>
  54. <q-icon :name="children.icon" />
  55. </q-item-section>
  56. <q-item-section> {{ children.title }} </q-item-section>
  57. </q-item>
  58. </template>
  59. </q-expansion-item>
  60. </template>
  61. <q-item
  62. v-ripple
  63. clickable
  64. class="q-mt-auto text-subtitle1"
  65. @click="auth.logout()"
  66. >
  67. <div class="flex">
  68. <q-item-section avatar>
  69. <q-icon name="mdi-logout-variant" color="negative" />
  70. </q-item-section>
  71. <q-item-section> {{ $t("logout") }} </q-item-section>
  72. </div>
  73. </q-item>
  74. </q-list>
  75. </q-scroll-area>
  76. </q-drawer>
  77. </template>
  78. <script setup>
  79. import { ref, onMounted } from "vue";
  80. import { useAuth } from "src/composables/useAuth";
  81. import { permissionStore } from "src/stores/permission";
  82. import { useI18n } from "vue-i18n/dist/vue-i18n";
  83. const auth = useAuth();
  84. const { t } = useI18n();
  85. const leftDrawerOpen = ref(true);
  86. const miniState = ref(true);
  87. const menus = ref([
  88. {
  89. type: "single",
  90. title: t("dashboard"),
  91. name: "DashboardPage",
  92. icon: "mdi-home-variant-outline",
  93. disable: false,
  94. permission: false,
  95. permissionScope: "dashboard",
  96. },
  97. {
  98. type: "expansive",
  99. title: t("registration"),
  100. icon: "mdi-cog-outline",
  101. disable: false,
  102. permission: false,
  103. permissionScope: "config",
  104. childrens: [
  105. {
  106. type: "single",
  107. title: t("users"),
  108. name: "UsuariosPage",
  109. icon: "mdi-account-multiple-outline",
  110. disable: false,
  111. permission: false,
  112. permissionScope: "usuarios",
  113. },
  114. ],
  115. },
  116. ]);
  117. const getMenuAccess = () => {
  118. const { getAccess } = permissionStore();
  119. menus.value = menus.value
  120. .map((menu) => {
  121. if (menu.type === "expansive") {
  122. if (getAccess(menu.permissionScope, "menu")) {
  123. menu.permission = true;
  124. }
  125. menu.childrens = menu.childrens.filter((children) => {
  126. children.permission = getAccess(children.permissionScope, "menu");
  127. return children.permission;
  128. });
  129. return menu.childrens.length > 0 ? menu : null;
  130. } else {
  131. if (menu.componente === "vuePageDashboard") {
  132. menu.permission = true;
  133. } else {
  134. menu.permission = getAccess(menu.permissionScope, "menu");
  135. }
  136. return menu.permission ? menu : null;
  137. }
  138. })
  139. .filter((menu) => menu !== null);
  140. };
  141. onMounted(() => {
  142. getMenuAccess();
  143. });
  144. </script>
  145. <style lang="scss" scoped>
  146. .menu-selected {
  147. color: #385873 !important;
  148. background: rgba(56, 88, 115, 0.15) !important;
  149. .body--light & {
  150. color: #385873 !important;
  151. }
  152. .body--dark & {
  153. color: #5d93bf !important;
  154. }
  155. //sobreescrever comportamento padrao da classe .fit do quasar
  156. .fit {
  157. padding: 0px !important;
  158. }
  159. }
  160. </style>