|
1 | 1 | <template> |
2 | 2 | <div class="timetable"> |
3 | | - <div class = 'container'> |
4 | | - <div class='info'>{{this.timetable.number}} группа</div> |
5 | | - <ul> |
6 | | - <EventRow |
7 | | - v-for= "lesson of this.timetable.events" :key='lesson.id' :lesson="lesson" |
8 | | - /> |
| 3 | + <div v-if="!this.loaded" class="lds-dual-ring"></div> |
| 4 | + <div v-else class='container'> |
| 5 | + <div class='info'>{{ this.timetable.number }} группа</div> |
| 6 | + <div class="no-events" v-if="!this.timetable.events.length">мероприятия отсутствуют</div> |
| 7 | + <ul v-else> |
| 8 | + <EventRow v-for="lesson of this.timetable.events" :key='lesson.id' :lesson="lesson" /> |
9 | 9 | </ul> |
| 10 | + |
10 | 11 | </div> |
11 | 12 | </div> |
12 | 13 | </template> |
|
15 | 16 | import EventRow from '@/components/EventRow.vue' |
16 | 17 | export default { |
17 | 18 | name: "Timetable", |
18 | | - |
| 19 | +
|
19 | 20 | mounted() { |
20 | 21 | this.groupId = localStorage.getItem('timetable-group-id'); |
21 | 22 | this.$store.commit("changePage", this.pageId); |
22 | | - this.loadTimetableOnDate(this.$store.state.date) |
| 23 | + this.loadTimetableOnDate(this.$store.state.date) |
23 | 24 | }, |
24 | 25 | data() { |
25 | 26 | return { |
| 27 | + loaded: true, |
26 | 28 | pageId: 1, |
27 | 29 | groupId: null, |
28 | | - timetable: [], |
| 30 | + timetable: { events: [] }, |
29 | 31 | }; |
30 | 32 | }, |
31 | 33 | computed: { |
32 | 34 | choosenDate() { |
33 | | - return this.$store.state.date |
| 35 | + return this.$store.state.date |
34 | 36 | } |
35 | 37 | }, |
36 | 38 | watch: { |
37 | 39 | choosenDate(newValue) { |
38 | 40 | this.loadTimetableOnDate(newValue) |
39 | 41 | } |
40 | 42 | }, |
41 | | - components:{ |
| 43 | + components: { |
42 | 44 | EventRow: EventRow, |
43 | 45 | }, |
44 | | - methods:{ |
| 46 | + methods: { |
45 | 47 | loadTimetableOnDate(date) { |
| 48 | + this.loaded = false; |
46 | 49 | var time_start = new Date(date); |
47 | | - var time_end = new Date(); |
| 50 | + time_start.setHours(time_start.getHours() - date.getTimezoneOffset()/60) |
| 51 | + console.log(time_start.toISOString()) |
| 52 | + var time_end = new Date(time_start); |
48 | 53 | time_end.setDate(time_start.getDate() + 1) |
49 | 54 | var url = new URL(`${process.env.VUE_APP_API_TIMETABLE}/timetable/group/${this.groupId}`), |
50 | | - params = {start: time_start.toISOString().slice(0,10), end: time_end.toISOString().slice(0,10)} |
| 55 | + params = { start: time_start.toISOString().slice(0, 10), end: time_end.toISOString().slice(0, 10) } |
51 | 56 | Object.keys(params).forEach(key => url.searchParams.append(key, params[key])) |
52 | 57 | fetch(url) |
53 | 58 | .then(response => response.json()) |
54 | 59 | .then(json => { |
55 | | - this.timetable = json |
| 60 | + this.timetable = json; |
| 61 | + this.loaded = true; |
56 | 62 | }) |
57 | 63 | } |
58 | 64 | } |
59 | 65 | }; |
60 | 66 | </script> |
61 | 67 |
|
62 | 68 | <style scoped> |
63 | | - ul{ |
64 | | - display: flex; |
65 | | - flex-direction: column; |
66 | | - align-items: flex-start; |
67 | | - padding: 10px; |
68 | | - gap: 10px; |
69 | | - width:auto; |
70 | | - } |
71 | | - .timetable{ |
72 | | - display: flex; |
73 | | - flex-direction: column; |
74 | | - align-items: flex-start; |
75 | | - padding: 10px; |
76 | | - gap: 10px; |
77 | | - width:auto; |
78 | | - padding-top: 66px; |
79 | | - } |
80 | | - .info{ |
81 | | - height: 20px; |
82 | | - font-family: 'Roboto'; |
83 | | - font-style: normal; |
84 | | - font-weight: 700; |
85 | | - font-size: 16px; |
86 | | - line-height: 16px; |
87 | | - /* identical to box height, or 100% */ |
| 69 | +ul { |
| 70 | + display: flex; |
| 71 | + flex-direction: column; |
| 72 | + align-items: flex-start; |
| 73 | + padding: 10px; |
| 74 | + gap: 10px; |
| 75 | + width: auto; |
| 76 | +} |
| 77 | +
|
| 78 | +.no-events { |
| 79 | + margin-top: auto; |
| 80 | + margin-bottom: auto; |
| 81 | + align-self: center; |
| 82 | + justify-self: center; |
| 83 | + text-align: center; |
| 84 | + font-size: 24px; |
| 85 | + font-weight: 700; |
| 86 | + color: lightgray; |
| 87 | + text-transform: uppercase; |
88 | 88 |
|
89 | | - letter-spacing: 0.4px; |
| 89 | +} |
90 | 90 |
|
91 | | - color: #000000; |
| 91 | +.container { |
| 92 | + display: flex; |
| 93 | + flex-direction: column; |
| 94 | + justify-content: start; |
| 95 | + height: 100%; |
| 96 | + gap: 10px; |
| 97 | +} |
92 | 98 |
|
| 99 | +.timetable { |
| 100 | + padding: 10px; |
| 101 | + padding-top: 66px; |
| 102 | + display: flex; |
| 103 | + flex-direction: column; |
| 104 | + justify-content: center; |
| 105 | + align-items: center; |
| 106 | + height: calc(100vh - 56px); |
| 107 | + width: auto; |
| 108 | + overflow: scroll; |
| 109 | +} |
93 | 110 |
|
94 | | - /* Inside auto layout */ |
| 111 | +.info { |
| 112 | + height: 20px; |
| 113 | + font-family: 'Roboto'; |
| 114 | + font-style: normal; |
| 115 | + font-weight: 700; |
| 116 | + font-size: 16px; |
| 117 | + line-height: 16px; |
| 118 | + letter-spacing: 0.4px; |
| 119 | + color: #000000; |
| 120 | + flex: none; |
| 121 | + order: 0; |
| 122 | + align-self: stretch; |
| 123 | + flex-grow: 0; |
| 124 | +} |
| 125 | +
|
| 126 | +.lds-dual-ring { |
| 127 | + display: inline-block; |
| 128 | + width: 80px; |
| 129 | + height: 80px; |
| 130 | +} |
| 131 | +
|
| 132 | +.lds-dual-ring:after { |
| 133 | + content: " "; |
| 134 | + display: block; |
| 135 | + width: 64px; |
| 136 | + height: 64px; |
| 137 | + margin: 8px; |
| 138 | + border-radius: 50%; |
| 139 | + border: 6px solid lightgray; |
| 140 | + border-color: lightgray transparent lightgray transparent; |
| 141 | + animation: lds-dual-ring 1.2s linear infinite; |
| 142 | +} |
| 143 | +
|
| 144 | +@keyframes lds-dual-ring { |
| 145 | + 0% { |
| 146 | + transform: rotate(0deg); |
| 147 | + } |
95 | 148 |
|
96 | | - flex: none; |
97 | | - order: 0; |
98 | | - align-self: stretch; |
99 | | - flex-grow: 0; |
| 149 | + 100% { |
| 150 | + transform: rotate(360deg); |
100 | 151 | } |
| 152 | +} |
101 | 153 | </style> |
0 commit comments