index.vue 5.6 KB

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