index.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. <template>
  2. <div
  3. v-if="!timetable"
  4. class="w-full h-full flex items-center justify-center show"
  5. >
  6. <ILoader class="w-16 h-16 text-foreground" />
  7. </div>
  8. <div
  9. v-else
  10. class="flex flex-col gap-2 show py-4 h-full"
  11. >
  12. <div
  13. v-if="week"
  14. class="grid grid-cols-3 place-items-center mb-5"
  15. >
  16. <img
  17. v-if="week.current_week !== week.previous_week && week.previous_week !== 0"
  18. :src="`/icons/chevron-left-alt.svg`"
  19. class="w-8 h-8 hover:opacity-100 duration-150 cursor-pointer"
  20. :alt="'chevron-left-alt'"
  21. @click="previousWeek"
  22. >
  23. <div v-else />
  24. <p class="text-2xl font-semibold text-center">
  25. Неделя {{ week.current_week }}
  26. </p>
  27. <img
  28. :src="`/icons/chevron-left-alt.svg`"
  29. class="w-8 h-8 rotate-180 hover:opacity-100 duration-150 cursor-pointer"
  30. :alt="'chevron-left-alt'"
  31. @click="nextWeek"
  32. >
  33. </div>
  34. <template v-if="hasLessons">
  35. <div
  36. v-for="(day, dayIdx) in timetable.days"
  37. :key="day.title"
  38. class="flex flex-col items-center"
  39. >
  40. <h1
  41. class="text-2xl font-semibold"
  42. v-text="getDayOfWeek(day.title)"
  43. />
  44. <p
  45. v-if="day.start"
  46. class="mt-0.5 text-sm opacity-50"
  47. v-text="`${day.start} - ${day.end} (~ ${day.hours} ${getHourWord(day.hours)})`"
  48. />
  49. <div
  50. v-else
  51. class="mt-2"
  52. />
  53. <section
  54. v-for="(lesson, lessonIdx) in day.lessons"
  55. :key="lessonIdx"
  56. class="w-full my-2 px-5 flex items-center justify-between"
  57. >
  58. <div class="flex items-center gap-3">
  59. <p
  60. class="text-3xl font-semibold opacity-60"
  61. v-text="lesson.number"
  62. />
  63. <div class="flex flex-col text-sm text-center">
  64. <div v-text="lesson.start" />
  65. <div class="w-full h-[1px] bg-foreground" />
  66. <div v-text="lesson.end" />
  67. </div>
  68. </div>
  69. <div class="text-sm text-center font-semibold w-52 sm:w-full">
  70. <p v-text="fixLessonTitle(lesson.title)" />
  71. <p
  72. v-if="lesson.teacher"
  73. class="opacity-50"
  74. v-text="lesson.teacher"
  75. />
  76. <p
  77. v-if="lesson.group"
  78. class="opacity-50"
  79. v-text="lesson.group"
  80. />
  81. </div>
  82. <div
  83. class="flex flex-col text-sm w-20 text-right"
  84. v-text="lesson.classroom"
  85. />
  86. </section>
  87. <div
  88. v-if="dayIdx !== timetable.days.length - 1"
  89. class="h-[1px] bg-foreground w-11/12 opacity-30"
  90. />
  91. </div>
  92. </template>
  93. <div
  94. v-else
  95. class="w-full h-full flex items-center justify-center"
  96. >
  97. <p class="text-2xl font-semibold text-center">
  98. Пары отсутствуют 🥳
  99. </p>
  100. </div>
  101. </div>
  102. </template>
  103. <script setup lang="ts">
  104. import { useHeader } from '~/store/useHeader'
  105. import { useUser } from '~/store/useUser'
  106. definePageMeta({
  107. name: 'Расписание',
  108. middleware: ['user-only'],
  109. })
  110. const { $api } = useNuxtApp()
  111. const user = useUser()
  112. const router = useRouter()
  113. const header = useHeader()
  114. const timetable = ref(null)
  115. const week = ref(null)
  116. async function nextWeek() {
  117. await updateTimetable(week.value.next_week)
  118. }
  119. async function previousWeek() {
  120. await updateTimetable(week.value.previous_week)
  121. }
  122. const hasLessons = computed(() => timetable.value.days.length > 0)
  123. watch(week, (val) => {
  124. console.log(val)
  125. })
  126. if (
  127. !(
  128. Object.hasOwn(user.data, 'is_student')
  129. || Object.hasOwn(user.data, 'branch_id')
  130. )
  131. ) {
  132. router.push('/setup/branch')
  133. }
  134. function fixLessonTitle(title: string) {
  135. return title[title.length - 1] === ','
  136. ? title
  137. .split('')
  138. .slice(0, title.length - 1)
  139. .join('')
  140. : title
  141. }
  142. function getHourWord(n: number): string {
  143. const absN = Math.abs(n)
  144. const mod10 = absN % 10
  145. const mod100 = absN % 100
  146. if (mod10 === 1 && mod100 !== 11) {
  147. return 'час'
  148. }
  149. else if (mod10 >= 2 && mod10 <= 4 && !(mod100 >= 12 && mod100 <= 14)) {
  150. return 'часа'
  151. }
  152. else {
  153. return 'часов'
  154. }
  155. }
  156. async function updateTimetable(numberOfWeek?: number) {
  157. timetable.value = null
  158. timetable.value = await $api.timetable.getTimetable(
  159. user.data.branch_id,
  160. user.data.group_id,
  161. numberOfWeek,
  162. )
  163. week.value = {
  164. next_week: timetable.value.next_week,
  165. previous_week: timetable.value.previous_week,
  166. current_week: timetable.value.current_week,
  167. }
  168. }
  169. function getDayOfWeek(name: string) {
  170. switch (name) {
  171. case 'ПН':
  172. return 'Понедельник'
  173. case 'ВТ':
  174. return 'Вторник'
  175. case 'СР':
  176. return 'Среда'
  177. case 'ЧТ':
  178. return 'Четверг'
  179. case 'ПТ':
  180. return 'Пятница'
  181. case 'СБ':
  182. return 'Суббота'
  183. case 'ВС':
  184. return 'Воскресенье'
  185. default:
  186. return name
  187. }
  188. }
  189. onMounted(async () => {
  190. if (user.data.is_student) {
  191. if (!Object.hasOwn(user.data, 'group_id')) {
  192. router.push('/timetable/group')
  193. }
  194. else {
  195. await updateTimetable()
  196. }
  197. }
  198. else {
  199. if (!Object.hasOwn(user.data, 'teacher_id')) {
  200. router.push('/timetable/teacher')
  201. }
  202. else {
  203. timetable.value = await $api.timetable.getTeacherTimetable(user.data.branch_id, user.data.teacher_id)
  204. }
  205. }
  206. })
  207. header.setAdditionalMenu(
  208. user.data.is_student
  209. ? [
  210. {
  211. name: 'Выбрать группу',
  212. icon: 'pencil',
  213. action: () => router.push('/timetable/group'),
  214. },
  215. {
  216. name: 'Занятость кабинетов',
  217. icon: 'calendar',
  218. action: () => router.push('/timetable/auditories'),
  219. },
  220. ]
  221. : [
  222. {
  223. name: 'Выбрать преподавателя',
  224. icon: 'pencil',
  225. action: () => router.push('/timetable/teacher'),
  226. },
  227. {
  228. name: 'Занятость кабинетов',
  229. icon: 'calendar',
  230. action: () => router.push('/timetable/auditories'),
  231. },
  232. ],
  233. )
  234. </script>