index.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <template>
  2. <div
  3. v-if="store.isRendered"
  4. ref="sideBarEl"
  5. class="w-screen h-screen fixed top-0 left-0 z-30"
  6. >
  7. <div
  8. :class="store.isVisible ? 'bg-opacity-70' : 'bg-opacity-0'"
  9. class="w-full h-full bg-black animate__animated animate__faster animate__fadeIn duration-500"
  10. @click="store.hide"
  11. />
  12. <div
  13. :class="
  14. store.isVisible
  15. ? 'animate__animated animate__faster animate__slideInLeft'
  16. : 'animate__animated animate__faster animate__slideOutLeft'
  17. "
  18. class="absolute top-0 min-w-[330px] h-full bg-background-100 p-4"
  19. :style="`left: -${translateTo}px`"
  20. >
  21. <div
  22. class="w-full h-full flex flex-col gap-[10px] show transition-all"
  23. :class="store.isVisible ? 'opacity-100' : 'opacity-0'"
  24. >
  25. <div class="flex items-center gap-4 mb-4">
  26. <img
  27. v-if="info"
  28. :src="info.user_info.image"
  29. class="w-[72px] h-[72px] rounded-full show"
  30. >
  31. <div
  32. v-else
  33. class="w-[72px] h-[72px] rounded-full loading"
  34. />
  35. <div class="w-fit flex flex-col text-foreground">
  36. <h1
  37. v-if="info"
  38. class="text-2xl show"
  39. v-text="info.user_info.name"
  40. />
  41. <div
  42. v-else
  43. class="w-48 h-8 rounded-md loading"
  44. />
  45. <div class="flex justify-between opacity-60">
  46. <template v-if="info">
  47. <h3
  48. class="show"
  49. v-text="info.main_info.Группа"
  50. />
  51. <h3
  52. class="show"
  53. v-text="info.courses[0].title"
  54. />
  55. </template>
  56. <template v-else>
  57. <div
  58. class="h-6 w-16 mt-2 rounded-md loading"
  59. />
  60. <div
  61. class="h-6 w-16 mt-2 rounded-md loading"
  62. />
  63. </template>
  64. </div>
  65. </div>
  66. </div>
  67. <div class="w-full bg-foreground opacity-25 h-[1px]" />
  68. <div class="flex flex-col divide-y-[1px] divide-background-200">
  69. <NuxtLink
  70. v-for="(link, idx) in links"
  71. :key="idx"
  72. :to="link.route"
  73. @click="store.hide()"
  74. >
  75. <BaseSideBarElement
  76. :type="link.icon"
  77. :text="link.name"
  78. :color="useRouter().currentRoute.value.path === link.route ? '#FF4646' : '#EDE8D8'"
  79. />
  80. </NuxtLink>
  81. </div>
  82. <div class="flex-auto flex flex-col justify-end divide-y-[1px] divide-background-200">
  83. <div class="w-full bg-foreground opacity-25 h-[1px]" />
  84. <!-- <NuxtLink
  85. to="/settings"
  86. @click="store.hide()"
  87. >
  88. <BaseSideBarElement
  89. type="cog"
  90. text="Настройки"
  91. :color="useRouter().currentRoute.value.path === '/settings' ? '#FF4646' : '#EDE8D8'"
  92. />
  93. </NuxtLink> -->
  94. <NuxtLink
  95. to="/about"
  96. @click="store.hide()"
  97. >
  98. <BaseSideBarElement
  99. type="alert-circle"
  100. text="О программе"
  101. :color="useRouter().currentRoute.value.path === '/about' ? '#FF4646' : '#EDE8D8'"
  102. />
  103. </NuxtLink>
  104. <BaseSideBarElement
  105. type="logout"
  106. text="Выйти из аккаунта"
  107. color="#EDE8D8"
  108. @click="user.logout()"
  109. />
  110. </div>
  111. </div>
  112. </div>
  113. </div>
  114. </template>
  115. <script setup lang="ts">
  116. import { useSwipe } from '@vueuse/core'
  117. import { ApiModules } from '~/repository/api'
  118. import { useSideBar } from '~/store/useSideBar'
  119. import { useUser } from '~/store/useUser'
  120. const store = useSideBar()
  121. const sideBarEl = ref(null)
  122. const translateTo = ref(null)
  123. const { direction } = useSwipe(sideBarEl, {
  124. onSwipeEnd() {
  125. if (direction.value === 'left') store.hide()
  126. },
  127. })
  128. const user = useUser()
  129. const links = ref<{
  130. name: string
  131. icon: 'home' | 'license' | 'calendar' | 'mail' | 'bell' | 'photo' | 'chart'
  132. route: string
  133. }[]>([
  134. {
  135. name: 'Новости',
  136. icon: 'home',
  137. route: '/news',
  138. },
  139. {
  140. name: 'Блог',
  141. icon: 'license',
  142. route: '/blog',
  143. },
  144. {
  145. name: 'Расписание',
  146. icon: 'calendar',
  147. route: '/timetable',
  148. },
  149. // {
  150. // name: 'Сообщения',
  151. // icon: 'mail',
  152. // route: '/messenger',
  153. // },
  154. // {
  155. // name: 'Уведомления',
  156. // icon: 'bell',
  157. // route: '/notifications',
  158. // },
  159. // {
  160. // name: 'Галерея',
  161. // icon: 'photo',
  162. // route: '/gallery',
  163. // },
  164. // {
  165. // name: 'Оценки',
  166. // icon: 'chart',
  167. // route: '/marks',
  168. // },
  169. ])
  170. const info = ref()
  171. onMounted(
  172. async () =>
  173. (info.value = await ApiModules.user.getInfo(user.$state.data.access_token)),
  174. )
  175. </script>