added rounded expansion tile (fixed absence bug)

This commit is contained in:
Kima 2023-08-26 13:50:03 +02:00
parent 568d4cb769
commit 2d11c45972
6 changed files with 180 additions and 65 deletions

View File

@ -12,7 +12,8 @@ import 'package:filcnaplo_mobile_ui/common/widgets/lesson/changed_lesson_tile.da
import 'package:filcnaplo/utils/format.dart'; import 'package:filcnaplo/utils/format.dart';
// difference.inDays is not reliable // difference.inDays is not reliable
bool _sameDate(DateTime a, DateTime b) => (a.year == b.year && a.month == b.month && a.day == b.day); bool _sameDate(DateTime a, DateTime b) =>
(a.year == b.year && a.month == b.month && a.day == b.day);
List<Widget> sortDateWidgets( List<Widget> sortDateWidgets(
BuildContext context, { BuildContext context, {
@ -35,13 +36,16 @@ List<Widget> sortDateWidgets(
if (message.conversationId != null) { if (message.conversationId != null) {
convMessages.add(w); convMessages.add(w);
Conversation conv = conversations.firstWhere((e) => e.id == message.conversationId, orElse: () => Conversation(id: message.conversationId!)); Conversation conv = conversations.firstWhere(
(e) => e.id == message.conversationId,
orElse: () => Conversation(id: message.conversationId!));
conv.add(message); conv.add(message);
if (conv.messages.length == 1) conversations.add(conv); if (conv.messages.length == 1) conversations.add(conv);
} }
if (conversations.any((c) => c.id == message.messageId)) { if (conversations.any((c) => c.id == message.messageId)) {
Conversation conv = conversations.firstWhere((e) => e.id == message.messageId); Conversation conv =
conversations.firstWhere((e) => e.id == message.messageId);
convMessages.add(w); convMessages.add(w);
conv.add(message); conv.add(message);
} }
@ -87,26 +91,41 @@ List<Widget> sortDateWidgets(
// Group Absence Tiles // Group Absence Tiles
List<DateWidget> absenceTileWidgets = elements.where((element) { List<DateWidget> absenceTileWidgets = elements.where((element) {
return element.widget is AbsenceViewable && (element.widget as AbsenceViewable).absence.delay == 0; return element.widget is AbsenceViewable &&
(element.widget as AbsenceViewable).absence.delay == 0;
}).toList(); }).toList();
List<AbsenceViewable> absenceTiles = absenceTileWidgets.map((e) => e.widget as AbsenceViewable).toList(); List<AbsenceViewable> absenceTiles =
absenceTileWidgets.map((e) => e.widget as AbsenceViewable).toList();
if (absenceTiles.length > 1) { if (absenceTiles.length > 1) {
elements.removeWhere((element) => element.widget.runtimeType == AbsenceViewable && (element.widget as AbsenceViewable).absence.delay == 0); elements.removeWhere((element) =>
element.widget.runtimeType == AbsenceViewable &&
(element.widget as AbsenceViewable).absence.delay == 0);
if (elements.isEmpty) { if (elements.isEmpty) {
cst = false; cst = false;
} }
elements.add(DateWidget( elements.add(
widget: AbsenceGroupTile(absenceTiles, showDate: !cst), DateWidget(
widget: AbsenceGroupTile(
absenceTiles,
showDate: !cst,
padding: const EdgeInsets.symmetric(horizontal: 6.0),
),
date: absenceTileWidgets.first.date, date: absenceTileWidgets.first.date,
key: "${absenceTileWidgets.first.date.millisecondsSinceEpoch}-absence-group")); key:
"${absenceTileWidgets.first.date.millisecondsSinceEpoch}-absence-group"),
);
} }
// Bring Lesson Tiles to front & sort by index asc // Bring Lesson Tiles to front & sort by index asc
List<DateWidget> lessonTiles = elements.where((element) { List<DateWidget> lessonTiles = elements.where((element) {
return element.widget.runtimeType == ChangedLessonTile; return element.widget.runtimeType == ChangedLessonTile;
}).toList(); }).toList();
lessonTiles.sort((a, b) => (a.widget as ChangedLessonTile).lesson.lessonIndex.compareTo((b.widget as ChangedLessonTile).lesson.lessonIndex)); lessonTiles.sort((a, b) => (a.widget as ChangedLessonTile)
elements.removeWhere((element) => element.widget.runtimeType == ChangedLessonTile); .lesson
.lessonIndex
.compareTo((b.widget as ChangedLessonTile).lesson.lessonIndex));
elements.removeWhere(
(element) => element.widget.runtimeType == ChangedLessonTile);
elements.insertAll(0, lessonTiles); elements.insertAll(0, lessonTiles);
final date = (elements + absenceTileWidgets).first.date; final date = (elements + absenceTileWidgets).first.date;
@ -122,7 +141,8 @@ List<Widget> sortDateWidgets(
spawnIsolate: false, spawnIsolate: false,
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, animation, item, index) => filterItemBuilder(context, animation, item.widget, index), itemBuilder: (context, animation, item, index) =>
filterItemBuilder(context, animation, item.widget, index),
items: elements, items: elements,
), ),
), ),
@ -131,9 +151,12 @@ List<Widget> sortDateWidgets(
} }
final nh = DateTime.now(); final nh = DateTime.now();
final now = DateTime(nh.year, nh.month, nh.day).subtract(const Duration(seconds: 1)); final now =
DateTime(nh.year, nh.month, nh.day).subtract(const Duration(seconds: 1));
if (showDivider && items.any((i) => i.date.isBefore(now)) && items.any((i) => i.date.isAfter(now))) { if (showDivider &&
items.any((i) => i.date.isBefore(now)) &&
items.any((i) => i.date.isAfter(now))) {
items.add( items.add(
DateWidget( DateWidget(
date: now, date: now,
@ -153,7 +176,9 @@ List<Widget> sortDateWidgets(
} }
// Sort future dates asc, past dates desc // Sort future dates asc, past dates desc
items.sort((a, b) => (a.date.isAfter(now) && b.date.isAfter(now) ? 1 : -1) * a.date.compareTo(b.date)); items.sort((a, b) =>
(a.date.isAfter(now) && b.date.isAfter(now) ? 1 : -1) *
a.date.compareTo(b.date));
return items.map((e) => e.widget).toList(); return items.map((e) => e.widget).toList();
} }

View File

@ -35,7 +35,8 @@ class SubjectAbsence {
List<Absence> absences; List<Absence> absences;
double percentage; double percentage;
SubjectAbsence({required this.subject, this.absences = const [], this.percentage = 0.0}); SubjectAbsence(
{required this.subject, this.absences = const [], this.percentage = 0.0});
} }
class AbsencesPage extends StatefulWidget { class AbsencesPage extends StatefulWidget {
@ -45,7 +46,8 @@ class AbsencesPage extends StatefulWidget {
_AbsencesPageState createState() => _AbsencesPageState(); _AbsencesPageState createState() => _AbsencesPageState();
} }
class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMixin { class _AbsencesPageState extends State<AbsencesPage>
with TickerProviderStateMixin {
late UserProvider user; late UserProvider user;
late AbsenceProvider absenceProvider; late AbsenceProvider absenceProvider;
late TimetableProvider timetableProvider; late TimetableProvider timetableProvider;
@ -65,7 +67,9 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
for (final lesson in timetableProvider.getWeek(Week.current()) ?? []) { for (final lesson in timetableProvider.getWeek(Week.current()) ?? []) {
if (!lesson.isEmpty && lesson.subject.id != '' && lesson.lessonYearIndex != null) { if (!lesson.isEmpty &&
lesson.subject.id != '' &&
lesson.lessonYearIndex != null) {
_lessonCount.update( _lessonCount.update(
lesson.subject, lesson.subject,
(value) { (value) {
@ -89,25 +93,30 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
if (absence.delay != 0) continue; if (absence.delay != 0) continue;
if (!_absences.containsKey(absence.subject)) { if (!_absences.containsKey(absence.subject)) {
_absences[absence.subject] = SubjectAbsence(subject: absence.subject, absences: [absence]); _absences[absence.subject] =
SubjectAbsence(subject: absence.subject, absences: [absence]);
} else { } else {
_absences[absence.subject]?.absences.add(absence); _absences[absence.subject]?.absences.add(absence);
} }
} }
_absences.forEach((subject, absence) { _absences.forEach((subject, absence) {
final absentLessonsOfSubject = absenceProvider.absences.where((e) => e.subject == subject && e.delay == 0).length; final absentLessonsOfSubject = absenceProvider.absences
.where((e) => e.subject == subject && e.delay == 0)
.length;
final totalLessonsOfSubject = _lessonCount[subject]?.lessonYearIndex ?? 0; final totalLessonsOfSubject = _lessonCount[subject]?.lessonYearIndex ?? 0;
double absentLessonsOfSubjectPercentage; double absentLessonsOfSubjectPercentage;
if (absentLessonsOfSubject <= totalLessonsOfSubject) { if (absentLessonsOfSubject <= totalLessonsOfSubject) {
absentLessonsOfSubjectPercentage = absentLessonsOfSubject / totalLessonsOfSubject * 100; absentLessonsOfSubjectPercentage =
absentLessonsOfSubject / totalLessonsOfSubject * 100;
} else { } else {
absentLessonsOfSubjectPercentage = -1; absentLessonsOfSubjectPercentage = -1;
} }
_absences[subject]?.percentage = absentLessonsOfSubjectPercentage.clamp(-1, 100.0); _absences[subject]?.percentage =
absentLessonsOfSubjectPercentage.clamp(-1, 100.0);
}); });
absences = _absences.values.toList(); absences = _absences.values.toList();
@ -131,7 +140,8 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
body: Padding( body: Padding(
padding: const EdgeInsets.only(top: 12.0), padding: const EdgeInsets.only(top: 12.0),
child: NestedScrollView( child: NestedScrollView(
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), physics: const BouncingScrollPhysics(
parent: AlwaysScrollableScrollPhysics()),
headerSliverBuilder: (context, _) => [ headerSliverBuilder: (context, _) => [
SliverAppBar( SliverAppBar(
pinned: true, pinned: true,
@ -145,7 +155,10 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
padding: const EdgeInsets.only(left: 8.0), padding: const EdgeInsets.only(left: 8.0),
child: Text( child: Text(
"Absences".i18n, "Absences".i18n,
style: TextStyle(color: AppColors.of(context).text, fontSize: 32.0, fontWeight: FontWeight.bold), style: TextStyle(
color: AppColors.of(context).text,
fontSize: 32.0,
fontWeight: FontWeight.bold),
), ),
), ),
bottom: FilterBar(items: [ bottom: FilterBar(items: [
@ -158,7 +171,8 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
body: TabBarView( body: TabBarView(
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
controller: _tabController, controller: _tabController,
children: List.generate(3, (index) => filterViewBuilder(context, index))), children: List.generate(
3, (index) => filterViewBuilder(context, index))),
), ),
), ),
); );
@ -174,10 +188,17 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
widget: AbsenceSubjectTile( widget: AbsenceSubjectTile(
a.subject, a.subject,
percentage: a.percentage, percentage: a.percentage,
excused: a.absences.where((a) => a.state == Justification.excused).length, excused: a.absences
unexcused: a.absences.where((a) => a.state == Justification.unexcused).length, .where((a) => a.state == Justification.excused)
pending: a.absences.where((a) => a.state == Justification.pending).length, .length,
onTap: () => AbsenceSubjectView.show(a.subject, a.absences, context: context), unexcused: a.absences
.where((a) => a.state == Justification.unexcused)
.length,
pending: a.absences
.where((a) => a.state == Justification.pending)
.length,
onTap: () => AbsenceSubjectView.show(a.subject, a.absences,
context: context),
), ),
)); ));
} }
@ -187,14 +208,17 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
if (absence.delay != 0) { if (absence.delay != 0) {
items.add(DateWidget( items.add(DateWidget(
date: absence.date, date: absence.date,
widget: AbsenceViewable(absence, padding: EdgeInsets.zero), widget: AbsenceViewable(
)); absence,
padding: EdgeInsets.zero,
)));
} }
} }
break; break;
case AbsenceFilter.misses: case AbsenceFilter.misses:
for (var note in noteProvider.notes) { for (var note in noteProvider.notes) {
if (note.type?.name == "HaziFeladatHiany" || note.type?.name == "Felszereleshiany") { if (note.type?.name == "HaziFeladatHiany" ||
note.type?.name == "Felszereleshiany") {
items.add(DateWidget( items.add(DateWidget(
date: note.date, date: note.date,
widget: MissTile(note), widget: MissTile(note),
@ -232,10 +256,15 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
showDialog( showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)), shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0)),
title: Text("attention".i18n), title: Text("attention".i18n),
content: Text("attention_body".i18n), content: Text("attention_body".i18n),
actions: [ActionButton(label: "Ok", onTap: () => Navigator.of(context).pop())], actions: [
ActionButton(
label: "Ok",
onTap: () => Navigator.of(context).pop())
],
), ),
); );
}, },
@ -262,7 +291,10 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
); );
}, },
child: Column( child: Column(
children: getFilterWidgets(AbsenceFilter.values[activeData]).map((e) => e.widget).cast<Widget>().toList(), children: getFilterWidgets(AbsenceFilter.values[activeData])
.map((e) => e.widget)
.cast<Widget>()
.toList(),
), ),
), ),
), ),
@ -284,7 +316,8 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
itemCount: max(filterWidgets.length + (activeData <= 1 ? 1 : 0), 1), itemCount: max(filterWidgets.length + (activeData <= 1 ? 1 : 0), 1),
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (filterWidgets.isNotEmpty) { if (filterWidgets.isNotEmpty) {
if ((index == 0 && activeData == 1) || (index == 0 && activeData == 0)) { if ((index == 0 && activeData == 1) ||
(index == 0 && activeData == 0)) {
int value1 = 0; int value1 = 0;
int value2 = 0; int value2 = 0;
String title1 = ""; String title1 = "";
@ -292,18 +325,26 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
String suffix = ""; String suffix = "";
if (activeData == AbsenceFilter.absences.index) { if (activeData == AbsenceFilter.absences.index) {
value1 = absenceProvider.absences.where((e) => e.delay == 0 && e.state == Justification.excused).length; value1 = absenceProvider.absences
value2 = absenceProvider.absences.where((e) => e.delay == 0 && e.state == Justification.unexcused).length; .where((e) =>
e.delay == 0 && e.state == Justification.excused)
.length;
value2 = absenceProvider.absences
.where((e) =>
e.delay == 0 && e.state == Justification.unexcused)
.length;
title1 = "stat_1".i18n; title1 = "stat_1".i18n;
title2 = "stat_2".i18n; title2 = "stat_2".i18n;
suffix = " " + "hr".i18n; suffix = " " + "hr".i18n;
} else if (activeData == AbsenceFilter.delays.index) { } else if (activeData == AbsenceFilter.delays.index) {
value1 = absenceProvider.absences value1 = absenceProvider.absences
.where((e) => e.delay != 0 && e.state == Justification.excused) .where((e) =>
e.delay != 0 && e.state == Justification.excused)
.map((e) => e.delay) .map((e) => e.delay)
.fold(0, (a, b) => a + b); .fold(0, (a, b) => a + b);
value2 = absenceProvider.absences value2 = absenceProvider.absences
.where((e) => e.delay != 0 && e.state == Justification.unexcused) .where((e) =>
e.delay != 0 && e.state == Justification.unexcused)
.map((e) => e.delay) .map((e) => e.delay)
.fold(0, (a, b) => a + b); .fold(0, (a, b) => a + b);
title1 = "stat_3".i18n; title1 = "stat_3".i18n;
@ -312,7 +353,8 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
} }
return Padding( return Padding(
padding: const EdgeInsets.only(bottom: 24.0, left: 24.0, right: 24.0), padding: const EdgeInsets.only(
bottom: 24.0, left: 24.0, right: 24.0),
child: Row(children: [ child: Row(children: [
Expanded( Expanded(
child: StatisticsTile( child: StatisticsTile(
@ -348,7 +390,8 @@ class _AbsencesPageState extends State<AbsencesPage> with TickerProviderStateMix
} }
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0), padding:
const EdgeInsets.symmetric(horizontal: 24.0, vertical: 6.0),
child: filterWidgets[index - (activeData <= 1 ? 1 : 0)], child: filterWidgets[index - (activeData <= 1 ? 1 : 0)],
); );
} else { } else {

View File

@ -9,7 +9,9 @@ import 'package:provider/provider.dart';
import 'absence_tile.i18n.dart'; import 'absence_tile.i18n.dart';
class AbsenceTile extends StatelessWidget { class AbsenceTile extends StatelessWidget {
const AbsenceTile(this.absence, {Key? key, this.onTap, this.elevation = 0.0, this.padding}) : super(key: key); const AbsenceTile(this.absence,
{Key? key, this.onTap, this.elevation = 0.0, this.padding})
: super(key: key);
final Absence absence; final Absence absence;
final void Function()? onTap; final void Function()? onTap;
@ -37,39 +39,61 @@ class AbsenceTile extends StatelessWidget {
child: Material( child: Material(
type: MaterialType.transparency, type: MaterialType.transparency,
child: Padding( child: Padding(
padding: padding ?? (group ? EdgeInsets.zero : const EdgeInsets.symmetric(horizontal: 8.0)), padding: padding ??
(group
? EdgeInsets.zero
: const EdgeInsets.symmetric(
horizontal: 8.0,
)),
child: ListTile( child: ListTile(
onTap: onTap, onTap: onTap,
visualDensity: VisualDensity.compact, visualDensity: VisualDensity.compact,
dense: group, dense: group,
contentPadding: const EdgeInsets.only(left: 8.0, right: 12.0), contentPadding: const EdgeInsets.only(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(!group ? 14.0 : 12.0)), left: 14.0, right: 12.0, top: 2.0, bottom: 2.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(!group ? 14.0 : 12.0)),
leading: Container( leading: Container(
width: 44.0, width: 44.0,
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: !group ? color.withOpacity(.25) : null, color: !group ? color.withOpacity(.25) : null,
), ),
child: Center(child: Icon(justificationIcon(absence.state), color: color)), child: Center(
child: Icon(justificationIcon(absence.state), color: color)),
), ),
title: !group title: !group
? Text.rich(TextSpan( ? Text.rich(TextSpan(
text: "${absence.delay == 0 ? "" : absence.delay}", text: "${absence.delay == 0 ? "" : absence.delay}",
style: const TextStyle(fontWeight: FontWeight.w700, fontSize: 15.5), style: const TextStyle(
fontWeight: FontWeight.w700, fontSize: 15.5),
children: [ children: [
TextSpan( TextSpan(
text: absence.delay == 0 text: absence.delay == 0
? justificationName(absence.state).fill(["absence".i18n]).capital() ? justificationName(absence.state)
: 'minute'.plural(absence.delay) + justificationName(absence.state).fill(["delay".i18n]), .fill(["absence".i18n]).capital()
: 'minute'.plural(absence.delay) +
justificationName(absence.state)
.fill(["delay".i18n]),
style: const TextStyle(fontWeight: FontWeight.w600), style: const TextStyle(fontWeight: FontWeight.w600),
), ),
], ],
)) ))
: Text( : Text(
(absence.lessonIndex != null ? "${absence.lessonIndex}. " : "") + (absence.subject.renamedTo ?? absence.subject.name.capital()), (absence.lessonIndex != null
? "${absence.lessonIndex}. "
: "") +
(absence.subject.renamedTo ??
absence.subject.name.capital()),
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.w500, fontSize: 14.0, fontStyle: absence.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null), style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 14.0,
fontStyle: absence.subject.isRenamed &&
settingsProvider.renamedSubjectsItalics
? FontStyle.italic
: null),
), ),
subtitle: !group subtitle: !group
? Text( ? Text(
@ -77,7 +101,12 @@ class AbsenceTile extends StatelessWidget {
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
// DateFormat("MM. dd. (EEEEE)", I18n.of(context).locale.toString()).format(absence.date), // DateFormat("MM. dd. (EEEEE)", I18n.of(context).locale.toString()).format(absence.date),
style: TextStyle(fontWeight: FontWeight.w500, fontStyle: absence.subject.isRenamed && settingsProvider.renamedSubjectsItalics ? FontStyle.italic : null), style: TextStyle(
fontWeight: FontWeight.w500,
fontStyle: absence.subject.isRenamed &&
settingsProvider.renamedSubjectsItalics
? FontStyle.italic
: null),
) )
: null, : null,
), ),
@ -97,7 +126,8 @@ class AbsenceTile extends StatelessWidget {
} }
} }
static Color justificationColor(Justification state, {required BuildContext context}) { static Color justificationColor(Justification state,
{required BuildContext context}) {
switch (state) { switch (state) {
case Justification.excused: case Justification.excused:
return AppColors.of(context).green; return AppColors.of(context).green;

View File

@ -5,6 +5,8 @@ import 'package:filcnaplo_mobile_ui/common/widgets/absence_group/absence_group_c
import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_tile.dart'; import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_tile.dart';
import 'package:filcnaplo/utils/format.dart'; import 'package:filcnaplo/utils/format.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:rounded_expansion_tile/rounded_expansion_tile.dart';
import 'absence_group_tile.i18n.dart'; import 'absence_group_tile.i18n.dart';
class AbsenceGroupTile extends StatelessWidget { class AbsenceGroupTile extends StatelessWidget {
@ -30,13 +32,17 @@ class AbsenceGroupTile extends StatelessWidget {
child: Material( child: Material(
type: MaterialType.transparency, type: MaterialType.transparency,
child: Padding( child: Padding(
padding: padding ?? const EdgeInsets.symmetric(horizontal: 8.0), padding: padding ??
const EdgeInsets.symmetric(horizontal: 0.0, vertical: 0.0),
child: AbsenceGroupContainer( child: AbsenceGroupContainer(
child: ExpansionTile( child: RoundedExpansionTile(
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)), borderRadius: BorderRadius.circular(10)),
tilePadding: const EdgeInsets.symmetric(horizontal: 8.0), childrenPadding: const EdgeInsets.symmetric(horizontal: 8.0),
backgroundColor: Colors.transparent, tileColor: Colors.transparent,
duration: const Duration(milliseconds: 250),
trailingDuration: 0.5,
trailing: const Icon(FeatherIcons.chevronDown),
leading: Container( leading: Container(
width: 44.0, width: 44.0,
height: 44.0, height: 44.0,

View File

@ -19,14 +19,18 @@ import 'package:filcnaplo_mobile_ui/common/widgets/absence/absence_view.i18n.dar
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class AbsenceSubjectView extends StatelessWidget { class AbsenceSubjectView extends StatelessWidget {
const AbsenceSubjectView(this.subject, {Key? key, this.absences = const []}) : super(key: key); const AbsenceSubjectView(this.subject, {Key? key, this.absences = const []})
: super(key: key);
final Subject subject; final Subject subject;
final List<Absence> absences; final List<Absence> absences;
static void show(Subject subject, List<Absence> absences, {required BuildContext context}) { static void show(Subject subject, List<Absence> absences,
{required BuildContext context}) {
Navigator.of(context, rootNavigator: true) Navigator.of(context, rootNavigator: true)
.push<Absence>(CupertinoPageRoute(builder: (context) => AbsenceSubjectView(subject, absences: absences))) .push<Absence>(CupertinoPageRoute(
builder: (context) =>
AbsenceSubjectView(subject, absences: absences)))
.then((value) { .then((value) {
if (value == null) return; if (value == null) return;
@ -36,7 +40,8 @@ class AbsenceSubjectView extends StatelessWidget {
TimetablePage.jump(context, lesson: lesson); TimetablePage.jump(context, lesson: lesson);
} else { } else {
ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar( ScaffoldMessenger.of(context).showSnackBar(CustomSnackBar(
content: Text("Cannot find lesson".i18n, style: const TextStyle(color: Colors.white)), content: Text("Cannot find lesson".i18n,
style: const TextStyle(color: Colors.white)),
backgroundColor: AppColors.of(context).red, backgroundColor: AppColors.of(context).red,
context: context, context: context,
)); ));
@ -54,7 +59,10 @@ class AbsenceSubjectView extends StatelessWidget {
date: a.date, date: a.date,
)) ))
.toList(); .toList();
List<Widget> absenceTiles = sortDateWidgets(context, dateWidgets: dateWidgets, padding: EdgeInsets.zero, hasShadow: true); List<Widget> absenceTiles = sortDateWidgets(context,
dateWidgets: dateWidgets,
padding: const EdgeInsets.symmetric(vertical: 6.0),
hasShadow: true);
SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context); SettingsProvider settingsProvider = Provider.of<SettingsProvider>(context);

View File

@ -43,6 +43,9 @@ dependencies:
dotted_border: ^2.0.0+3 dotted_border: ^2.0.0+3
screenshot: ^2.1.0 screenshot: ^2.1.0
image_gallery_saver: ^2.0.2 image_gallery_saver: ^2.0.2
rounded_expansion_tile:
git:
url: https://github.com/kimaah/rounded_expansion_tile.git
dev_dependencies: dev_dependencies:
flutter_lints: ^1.0.0 flutter_lints: ^1.0.0