11<template >
22 <div class =" timetable" >
33 <div v-if =" !this.loaded" class =" lds-dual-ring" ></div >
4- <div v-else class =' container' >
5- <div class =' info' >{{ this.groupInfo.number }} группа</div >
6- <div class =" no-events" v-if =" !this.timetable.length" >пары отсутствуют</div >
4+ <div v-else class =" container" >
5+ <div class =" info" >{{ this.groupInfo.number }} группа</div >
6+ <div class =" no-events" v-if =" !this.timetable.length" >
7+ пары отсутствуют
8+ </div >
79 <ul v-else >
8- <EventRow v-for =" lesson of this.timetable" :key =' lesson.id' :lesson =" lesson" />
10+ <EventRow
11+ v-for =" lesson of this.timetable"
12+ :key =" lesson.id"
13+ :lesson =" lesson"
14+ />
915 </ul >
10-
1116 </div >
1217 </div >
1318</template >
1419
1520<script >
16- import EventRow from ' @/components/EventRow.vue'
21+ import EventRow from " @/components/EventRow.vue" ;
22+ import retry from " @/utils/Retrying.js" ;
23+ import { fetchTimetable } from " @/utils/FetchTimetable.js" ;
24+ import { getMonday , getMidnight , isToday } from " @/utils/Dates.js" ;
25+
1726export default {
1827 name: " Timetable" ,
1928 data () {
@@ -22,78 +31,132 @@ export default {
2231 pageId: 1 ,
2332 date: new Date (),
2433 groupId: null ,
25- groupInfo: { number: ' ' },
26- timetable: []
34+ groupInfo: { number: " " },
35+ timetable: [],
2736 };
2837 },
2938 components: {
3039 EventRow: EventRow,
3140 },
3241 methods: {
3342 loadGroupInfo () {
34- var url = new URL (` ${ process .env .VUE_APP_API_TIMETABLE } /timetable/group/${ this .groupId } ` );
35- fetch (url).then (response => response .json ())
36- .then (json => {
37- this .groupInfo = json;
38- })
43+ // Loading from cache if exists
44+ try {
45+ this .groupInfo = JSON .parse (
46+ localStorage .getItem (" timetable-group-info" ) || ' {"number": ""}'
47+ );
48+ } catch (err) {
49+ console .log (" Can not take group info from cache" , err);
50+ }
51+
52+ // Loading from internet else
53+ try {
54+ fetch (
55+ ` ${ process .env .VUE_APP_API_TIMETABLE } /timetable/group/${ this .groupId } `
56+ )
57+ .then ((response ) => response .json ())
58+ .then ((json ) => {
59+ this .groupInfo = json;
60+ localStorage .setItem (" timetable-group-info" , JSON .stringify (json));
61+ });
62+ } catch (error) {
63+ console .error (" Failed to load group info" );
64+ }
3965 },
4066 loadTimetableOnDate (date ) {
41- var time_start = new Date (date);
42- time_start .setHours (time_start .getHours () - date .getTimezoneOffset () / 60 )
67+ var time_start = getMidnight (date);
4368 var time_end = new Date (time_start);
44- time_end .setDate (time_start .getDate () + 1 )
45- var url = new URL (` ${ process .env .VUE_APP_API_TIMETABLE } /timetable/event/` ),
46- params = {
47- start: time_start .toISOString ().slice (0 , 10 ),
48- end: time_end .toISOString ().slice (0 , 10 ),
49- limit: 0 ,
50- offset: 0 ,
51- group_id: this .groupId
52- }
53- Object .keys (params).forEach (key => url .searchParams .append (key, params[key]))
54- this .loaded = false ;
55- fetch (url).then (response => response .json ())
56- .then (json => {
57- this .timetable = json .items ;
58- this .loaded = true ;
59- })
69+ time_end .setDate (time_start .getDate () + 1 );
70+
71+ // Quering events from internet, trying 5 times with 1sec between
72+ try {
73+ retry (
74+ () =>
75+ fetchTimetable (time_start, time_end, this .groupId ).then ((json ) => {
76+ this .timetable = json .items ;
77+ this .loaded = true ;
78+ console .log (" Loaded from internet" );
79+ }),
80+ 5 ,
81+ 1000
82+ );
83+ } catch (error) {
84+ console .log (" Can not load from internet" , error);
85+ }
6086
87+ // Loading from cache if exists
88+ let cached = JSON .parse (localStorage .getItem (" timetable-cache" ) || " []" );
89+ cached = cached .filter ((value ) =>
90+ isToday (Date .parse (value .start_ts ), date)
91+ );
92+ console .log (cached);
93+ if (! this .loaded && cached .length > 0 ) {
94+ this .timetable = cached;
95+ this .loaded = true ;
96+ console .log (` Loaded ${ cached .length } events from cache` );
97+ }
98+ },
99+ loadTimetableCache () {
100+ console .log (" Caching timetable" );
101+ // Загружает текущую неделю + следующую в кэш
102+ var time_start = getMonday (new Date ());
103+ var time_end = new Date (time_start);
104+ time_end .setDate (time_start .getDate () + 14 );
105+ retry (
106+ // Повтори загрузку недели трижды с интервалом 10 секунд
107+ () =>
108+ fetchTimetable (time_start, time_end, this .groupId ).then ((json ) => {
109+ localStorage .setItem (" timetable-cache" , JSON .stringify (json .items ));
110+ console .log (` Cached ${ json .items .length } items` );
111+ }),
112+ 3 ,
113+ 10000
114+ );
61115 },
62116 swipeEventHandler (e ) {
63- var nextDate = new Date (this .date )
64- if (e .detail .dir == ' left' )
65- nextDate .setDate (this .date .getDate () + 1 );
66- if (e .detail .dir == ' right' )
67- nextDate .setDate (this .date .getDate () - 1 );
68- document .dispatchEvent (new CustomEvent (' change-main-date' , { detail: { date: nextDate } }));
69- }
70-
117+ var nextDate = new Date (this .date );
118+ if (e .detail .dir == " left" ) nextDate .setDate (this .date .getDate () + 1 );
119+ if (e .detail .dir == " right" ) nextDate .setDate (this .date .getDate () - 1 );
120+ document .dispatchEvent (
121+ new CustomEvent (" change-main-date" , { detail: { date: nextDate } })
122+ );
123+ },
124+ },
125+ watch: {
126+ date (newDate ) {
127+ this .loaded = false ;
128+ // 5 раз с интервалом в 1 секунду попробуй скачать расписание
129+ this .loadTimetableOnDate (newDate);
130+ },
71131 },
72132 beforeMount () {
73- document .dispatchEvent (new CustomEvent (" change-page" , { detail: this .pageId }));
74- document .addEventListener (' change-date' , (e ) => {
75- this .date = e .detail .date ;
76- this .loadTimetableOnDate (this .date );
77- });
78-
133+ document .dispatchEvent (
134+ new CustomEvent (" change-page" , { detail: this .pageId })
135+ );
136+ document .addEventListener (
137+ " change-date" ,
138+ (e ) => (this .date = e .detail .date )
139+ );
79140 },
80- updated (){
81- document .dispatchEvent (new CustomEvent (" change-page" , { detail: this .pageId }));
141+ updated () {
142+ document .dispatchEvent (
143+ new CustomEvent (" change-page" , { detail: this .pageId })
144+ );
82145 },
83146 mounted () {
84- this .groupId = localStorage .getItem (' timetable-group-id' );
147+ this .groupId = localStorage .getItem (" timetable-group-id" );
85148 this .loadGroupInfo ();
86- document .dispatchEvent (new CustomEvent (' sync-date' ))
149+ document .dispatchEvent (new CustomEvent (" sync-date" ));
87150 // обработка свайпов
88151 document .addEventListener (" swipe" , this .swipeEventHandler );
152+
153+ // Загружаем кэш в память
154+ this .loadTimetableCache ();
89155 },
90- beforeUnmount (){
156+ beforeUnmount () {
91157 document .removeEventListener (" swipe" , this .swipeEventHandler );
92- console .log (' removed' );
93- }
94-
158+ },
95159};
96-
97160 </script >
98161
99162<style scoped>
116179 font-weight : 700 ;
117180 color : lightgray ;
118181 text-transform : uppercase ;
119-
120182}
121183
122184.container {
141203
142204.info {
143205 height : 20px ;
144- font-family : ' Roboto' ;
206+ font-family : " Roboto" ;
145207 font-style : normal ;
146208 font-weight : 700 ;
147209 font-size : 16px ;
0 commit comments