Skip to content

Commit

Permalink
Add custom widget for event tile in calendar schedule view (#803)
Browse files Browse the repository at this point in the history
* Add auto resizing text and modal on tap

* Change tile layout and tests

* [BOT] Bump version from 4.21.5+1 to 4.22.0+1

* [BOT] Applying version.

* Fix build error

* Oop

* fix tests maybe

* fix

* fix yes

* [BOT] Update golden files

* [BOT] Update golden files

---------

Co-authored-by: HugoMigner <[email protected]>
Co-authored-by: clubapplets-server <[email protected]>
  • Loading branch information
3 people authored Jun 15, 2023
1 parent fcbfa75 commit 720f91b
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 10 deletions.
3 changes: 3 additions & 0 deletions l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@
"schedule_already_today_toast": "Already showing today's schedule",
"schedule_calendar_from": "From",
"schedule_calendar_to": "To",
"schedule_calendar_from_time": "From",
"schedule_calendar_to_time": "To",
"schedule_calendar_by": "By",
"course_activity_group_a": "Group A",
"course_activity_group_b": "Group B",
"course_activity_group_both": "Both groups",
Expand Down
3 changes: 3 additions & 0 deletions l10n/intl_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
"schedule_already_today_toast": "Déjà sur l'horaire d'aujourd'hui",
"schedule_calendar_from": "Du",
"schedule_calendar_to": "au",
"schedule_calendar_from_time": "De",
"schedule_calendar_to_time": "à",
"schedule_calendar_by": "Par",
"course_activity_group_a": "Groupe A",
"course_activity_group_b": "Groupe B",
"course_activity_group_both": "Les deux groupes",
Expand Down
23 changes: 19 additions & 4 deletions lib/core/viewmodels/schedule_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ class ScheduleViewModel extends FutureViewModel<List<CourseActivity>> {
/// Activities sorted by day
Map<DateTime, List<CourseActivity>> _coursesActivities = {};

/// Courses associated to the student
List<Course> courses;

/// Day currently selected
DateTime selectedDate;

Expand Down Expand Up @@ -116,10 +119,15 @@ class ScheduleViewModel extends FutureViewModel<List<CourseActivity>> {
final courseLocation = eventData.activityLocation == "Non assign"
? "N/A"
: eventData.activityLocation;
final associatedCourses = courses?.where(
(element) => element.acronym == eventData.courseGroup.split('-')[0]);
final associatedCourse =
associatedCourses?.isNotEmpty == true ? associatedCourses.first : null;
return CalendarEventData(
title:
"${eventData.courseGroup.split('-')[0]}\n$courseLocation\n${eventData.activityName}",
description: eventData.courseGroup,
description:
"${eventData.courseGroup};$courseLocation;${eventData.activityName};${associatedCourse?.teacherName}",
date: eventData.startDateTime,
startTime: eventData.startDateTime,
endTime: eventData.endDateTime.subtract(const Duration(minutes: 1)),
Expand Down Expand Up @@ -163,11 +171,18 @@ class ScheduleViewModel extends FutureViewModel<List<CourseActivity>> {
.getCoursesActivities()
// ignore: return_type_invalid_for_catch_error
.catchError(onError)
.then((value) {
if (value != null) {
.then((value1) async {
if (value1 != null) {
// Reload the list of activities
coursesActivities;
calendarEvents = selectedWeekCalendarEvents();
await _courseRepository
.getCourses(fromCacheOnly: true)
.then((value2) {
courses = value2;
});
if (_coursesActivities.isNotEmpty) {
calendarEvents = selectedWeekCalendarEvents();
}
}
_courseRepository
.getScheduleActivities()
Expand Down
17 changes: 13 additions & 4 deletions lib/ui/views/schedule_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import 'package:notredame/core/services/analytics_service.dart';
import 'package:notredame/ui/widgets/base_scaffold.dart';
import 'package:notredame/ui/widgets/course_activity_tile.dart';
import 'package:notredame/ui/widgets/schedule_settings.dart';
import 'package:notredame/ui/widgets/schedule_calendar_tile.dart';

// CONSTANTS
import 'package:notredame/core/constants/preferences_flags.dart';
Expand Down Expand Up @@ -229,7 +230,10 @@ class _ScheduleViewState extends State<ScheduleView>
final locale = AppIntl.of(context).localeName;
return '$from ${date.day} ${DateFormat.MMMM(locale).format(date)} $to ${secondaryDate.day} ${DateFormat.MMMM(locale).format(secondaryDate)}';
},
eventTileBuilder: _buildEventTile,
eventTileBuilder: (date, events, boundary, startDuration,
endDuration) =>
_buildEventTile(
date, events, boundary, startDuration, endDuration, context),
weekDayBuilder: (DateTime date) => _buildWeekDay(date, model),
),
);
Expand All @@ -241,18 +245,23 @@ class _ScheduleViewState extends State<ScheduleView>
Rect boundary,
DateTime startDuration,
DateTime endDuration,
BuildContext context,
) {
if (events.isNotEmpty) {
return calendar_view.RoundedEventTile(
borderRadius: BorderRadius.circular(6.0),
return ScheduleCalendarTile(
title: events[0].title,
description: events[0].description,
start: events[0].startTime,
end: events[0].endTime,
titleStyle: TextStyle(
fontSize: 12,
fontSize: 14,
color: events[0].color.accent,
),
totalEvents: events.length,
padding: const EdgeInsets.all(7.0),
backgroundColor: events[0].color,
borderRadius: BorderRadius.circular(6.0),
buildContext: context,
);
} else {
return Container();
Expand Down
129 changes: 129 additions & 0 deletions lib/ui/widgets/schedule_calendar_tile.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class ScheduleCalendarTile extends StatefulWidget {
final String title;
final String description;
final TextStyle titleStyle;
final int totalEvents;
final EdgeInsets padding;
final Color backgroundColor;
final BorderRadius borderRadius;
final DateTime start;
final DateTime end;
final BuildContext buildContext;

const ScheduleCalendarTile(
{Key key,
this.title,
this.description,
this.titleStyle,
this.totalEvents,
this.padding,
this.backgroundColor,
this.borderRadius,
this.start,
this.end,
this.buildContext})
: super(key: key);

@override
_ScheduleCalendarTileState createState() => _ScheduleCalendarTileState();
}

class _ScheduleCalendarTileState extends State<ScheduleCalendarTile> {
void _showTileInfo() {
final courseInfos = widget.description.split(";");
final courseName = courseInfos[0].split("-")[0];
final courseLocation = courseInfos[1];
final courseType = courseInfos[2];
final teacherName = courseInfos[3];
final startTime =
"${widget.start.hour}:${widget.start.minute.toString().padLeft(2, '0')}";
final endTime =
"${widget.end.hour}:${widget.end.add(const Duration(minutes: 1)).minute.toString().padLeft(2, '0')}";

showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
title: Text(
"$courseName ($courseLocation)",
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
courseType,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
),
),
Text(
"${AppIntl.of(widget.buildContext).schedule_calendar_by} $teacherName",
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
),
),
Text(
"${AppIntl.of(widget.buildContext).schedule_calendar_from_time} $startTime ${AppIntl.of(widget.buildContext).schedule_calendar_to_time} $endTime",
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
),
),
],
),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text(
'Close',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
],
actionsPadding: const EdgeInsets.all(10),
);
},
);
}

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _showTileInfo,
child: Container(
decoration: BoxDecoration(
color: widget.backgroundColor,
borderRadius: widget.borderRadius,
),
padding: widget.padding,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AutoSizeText(
widget.title,
style: widget.titleStyle,
maxLines: 3,
)
],
),
),
);
}
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: The 4th generation of ÉTSMobile, the main gateway between the Éco
# pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 4.22.1+1
version: 4.23.0+1

environment:
sdk: ">=2.10.0 <3.0.0"
Expand Down
42 changes: 42 additions & 0 deletions test/ui/views/schedule_view_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ void main() {
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
Expand Down Expand Up @@ -147,6 +153,12 @@ void main() {
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
Expand All @@ -172,6 +184,12 @@ void main() {
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
Expand Down Expand Up @@ -200,6 +218,12 @@ void main() {
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
Expand All @@ -226,6 +250,12 @@ void main() {
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
Expand Down Expand Up @@ -280,6 +310,12 @@ void main() {
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
SettingsManagerMock.stubGetScheduleSettings(
settingsManager as SettingsManagerMock,
toReturn: settings);
Expand Down Expand Up @@ -329,6 +365,12 @@ void main() {
CourseRepositoryMock.stubGetCoursesActivities(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: true);
CourseRepositoryMock.stubGetCourses(
courseRepository as CourseRepositoryMock,
fromCacheOnly: false);
SettingsManagerMock.stubGetScheduleSettings(
settingsManager as SettingsManagerMock,
toReturn: settings);
Expand Down
Loading

0 comments on commit 720f91b

Please sign in to comment.