1+ // Dart imports:
2+ import 'dart:math' ;
3+
14// Flutter imports:
25import 'package:flutter/material.dart' ;
36
@@ -28,7 +31,11 @@ class GradesDetailsView extends StatefulWidget {
2831
2932class _GradesDetailsViewState extends State <GradesDetailsView > with TickerProviderStateMixin {
3033 late AnimationController _controller;
34+ late AnimationController _ignoredEvaluationsAnimationController;
3135 bool _completed = false ;
36+ final GlobalKey _expansionTileKey = GlobalKey ();
37+ late Animation <double > _rotateAnimation;
38+ bool _isIgnoredEvaluationsExpanded = false ;
3239
3340 @override
3441 void initState () {
@@ -42,6 +49,25 @@ class _GradesDetailsViewState extends State<GradesDetailsView> with TickerProvid
4249 });
4350 }
4451 });
52+
53+ _ignoredEvaluationsAnimationController = AnimationController (
54+ vsync: this ,
55+ duration: const Duration (milliseconds: 200 ),
56+ value: 1.0 ,
57+ );
58+ _ignoredEvaluationsAnimationController.forward ();
59+
60+ _rotateAnimation = Tween (
61+ begin: pi,
62+ end: 0.0 ,
63+ ).animate (CurvedAnimation (parent: _ignoredEvaluationsAnimationController, curve: Curves .easeIn));
64+ }
65+
66+ @override
67+ void dispose () {
68+ _controller.dispose ();
69+ _ignoredEvaluationsAnimationController.dispose ();
70+ super .dispose ();
4571 }
4672
4773 @override
@@ -229,12 +255,15 @@ class _GradesDetailsViewState extends State<GradesDetailsView> with TickerProvid
229255 const SizedBox (height: 8.0 ),
230256 Column (
231257 children: < Widget > [
232- for (final CourseEvaluation evaluation in model.course.summary ? .evaluations ?? [] )
258+ for (final CourseEvaluation evaluation in model.nonIgnoredEvaluations )
233259 GradeEvaluationTile (
234260 evaluation,
235261 completed: _completed,
236262 key: Key ("GradeEvaluationTile_${evaluation .title }" ),
237263 ),
264+ if (model.ignoredEvaluations.isNotEmpty) ...[
265+ _buildIgnoredEvaluationsExpansionTile (model.ignoredEvaluations),
266+ ],
238267 const SizedBox (height: 24 ),
239268 ],
240269 ),
@@ -314,4 +343,61 @@ class _GradesDetailsViewState extends State<GradesDetailsView> with TickerProvid
314343 ),
315344 );
316345 }
346+
347+ Widget _buildIgnoredEvaluationsExpansionTile (List <CourseEvaluation > ignoredEvaluations) {
348+ return Theme (
349+ data: Theme .of (context).copyWith (dividerColor: Colors .transparent),
350+ child: ExpansionTile (
351+ key: _expansionTileKey,
352+ onExpansionChanged: (value) {
353+ _isIgnoredEvaluationsExpanded = ! _isIgnoredEvaluationsExpanded;
354+ if (value) {
355+ _ignoredEvaluationsAnimationController.reverse (from: pi);
356+ _scrollToSelectedContent (expansionTileKey: _expansionTileKey);
357+ } else {
358+ _ignoredEvaluationsAnimationController.forward (from: 0.0 );
359+ }
360+ },
361+ trailing: AnimatedBuilder (
362+ animation: _rotateAnimation,
363+ builder: (BuildContext context, Widget ? child) {
364+ return Transform .rotate (
365+ angle: _rotateAnimation.value,
366+ child: const Icon (Icons .keyboard_arrow_down_sharp, color: AppPalette .etsLightRed),
367+ );
368+ },
369+ child: const Icon (Icons .keyboard_arrow_down_sharp, color: AppPalette .etsLightRed),
370+ ),
371+ tilePadding: EdgeInsets .only (left: 8.0 , right: 28 ),
372+ title: Row (
373+ children: [
374+ Text (
375+ AppIntl .of (context)! .ignored_evaluations_section_title (ignoredEvaluations.length),
376+ style: Theme .of (context).textTheme.titleMedium,
377+ ),
378+ ],
379+ ),
380+ children: [
381+ Padding (
382+ padding: const EdgeInsets .fromLTRB (8.0 , 0.0 , 8.0 , 8.0 ),
383+ child: Text (AppIntl .of (context)! .ignored_evaluations_section_description_text),
384+ ),
385+ for (final CourseEvaluation evaluation in ignoredEvaluations)
386+ GradeEvaluationTile (evaluation, completed: _completed, key: Key ("GradeEvaluationTile_${evaluation .title }" )),
387+ const SizedBox (height: 24 ),
388+ ],
389+ ),
390+ );
391+ }
392+
393+ void _scrollToSelectedContent ({required GlobalKey expansionTileKey}) {
394+ final keyContext = expansionTileKey.currentContext;
395+ if (keyContext != null ) {
396+ Future .delayed (Duration (milliseconds: 200 )).then ((value) {
397+ if (keyContext.mounted) {
398+ Scrollable .ensureVisible (keyContext, duration: Duration (milliseconds: 200 ));
399+ }
400+ });
401+ }
402+ }
317403}
0 commit comments