-
Notifications
You must be signed in to change notification settings - Fork 12
/
grades_view.dart
147 lines (136 loc) · 5.49 KB
/
grades_view.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
// Package imports:
import 'package:ets_api_clients/models.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:stacked/stacked.dart';
// Project imports:
import 'package:notredame/core/constants/router_paths.dart';
import 'package:notredame/core/services/analytics_service.dart';
import 'package:notredame/core/services/navigation_service.dart';
import 'package:notredame/core/viewmodels/grades_viewmodel.dart';
import 'package:notredame/locator.dart';
import 'package:notredame/ui/utils/app_theme.dart';
import 'package:notredame/ui/utils/loading.dart';
import 'package:notredame/ui/widgets/grade_button.dart';
class GradesView extends StatefulWidget {
@override
_GradesViewState createState() => _GradesViewState();
}
class _GradesViewState extends State<GradesView> {
final AnalyticsService _analyticsService = locator<AnalyticsService>();
/// Used to redirect on the dashboard.
final NavigationService _navigationService = locator<NavigationService>();
@override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((Duration duration) {
GradesViewModel.startDiscovery(context);
});
_analyticsService.logEvent("GradesView", "Opened");
}
@override
Widget build(BuildContext context) {
return ViewModelBuilder<GradesViewModel>.reactive(
viewModelBuilder: () => GradesViewModel(intl: AppIntl.of(context)!),
builder: (context, model, child) {
return RefreshIndicator(
onRefresh: () => model.refresh(),
child: Stack(
children: [
// This widget is here to make this widget a Scrollable. Needed
// by the RefreshIndicator
ListView(),
if (model.coursesBySession.isEmpty)
Center(
child: Text(AppIntl.of(context)!.grades_msg_no_grades,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge))
else
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: AnimationLimiter(
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: model.coursesBySession.length,
itemBuilder: (BuildContext context, int index) =>
AnimationConfiguration.staggeredList(
position: index,
duration: const Duration(milliseconds: 750),
child: SlideAnimation(
verticalOffset: 50.0,
child: FadeInAnimation(
child: _buildSessionCourses(
index,
_sessionName(model.sessionOrder[index],
AppIntl.of(context)!),
model.coursesBySession[
model.sessionOrder[index]]!,
model),
),
),
)),
),
),
if (model.isBusy)
buildLoading(isInteractionLimitedWhileLoading: false)
else
const SizedBox()
],
),
);
});
}
/// Build a session which is the name of the session and one [GradeButton] for
/// each [Course] in [courses]
Widget _buildSessionCourses(int index, String sessionName,
List<Course> courses, GradesViewModel model) =>
Padding(
padding: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Text(
sessionName,
style: const TextStyle(
fontSize: 25,
color: AppTheme.etsLightRed,
),
),
IconButton(
icon: const Icon(Icons.today, color: AppTheme.etsDarkGrey),
onPressed: () => _navigationService.pushNamed(
RouterPaths.defaultSchedule,
arguments: model.sessionOrder[index]),
),
],
),
const SizedBox(height: 16.0),
Wrap(
children: courses
.map((course) =>
GradeButton(course, showDiscovery: index == 0))
.toList(),
),
],
),
);
/// Build the complete name of the session for the user local.
String _sessionName(String shortName, AppIntl intl) {
switch (shortName[0]) {
case 'H':
return "${intl.session_winter} ${shortName.substring(1)}";
case 'A':
return "${intl.session_fall} ${shortName.substring(1)}";
case 'É':
return "${intl.session_summer} ${shortName.substring(1)}";
default:
return intl.session_without;
}
}
}