Skip to content

Commit

Permalink
feat: attendance graph UI changes
Browse files Browse the repository at this point in the history
  • Loading branch information
LuckUVeryX committed Oct 7, 2023
1 parent 76e6aaf commit 40158cb
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 32 deletions.
6 changes: 4 additions & 2 deletions lib/app/views/widgets/neu_container.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class NeuContainer extends StatelessWidget {
const NeuContainer({
this.child,
this.color,
this.border,
this.margin,
this.padding,
this.height,
Expand All @@ -12,12 +13,13 @@ class NeuContainer extends StatelessWidget {
super.key,
});

final Widget? child;
final Color? color;
final BoxBorder? border;
final EdgeInsets? margin;
final EdgeInsets? padding;
final double? height;
final double? width;
final Widget? child;
final bool shadow;

@override
Expand All @@ -29,7 +31,7 @@ class NeuContainer extends StatelessWidget {
padding: padding,
decoration: BoxDecoration(
color: color,
border: Border.all(width: 4),
border: border ?? Border.all(width: 4),
borderRadius: BorderRadius.circular(4),
boxShadow: shadow
? const [BoxShadow(offset: Offset(4, 4), spreadRadius: 1)]
Expand Down
78 changes: 48 additions & 30 deletions lib/modules/attendance/views/widgets/attendance_graph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import 'package:intl/intl.dart' as intl;
class AttendanceGraph extends ConsumerWidget {
const AttendanceGraph({super.key});

static const _crossAxisCount = DateTime.daysPerWeek * 2 + 1;

@override
Widget build(BuildContext context, WidgetRef ref) {
final graphFilter = ref.watch(attendanceGraphFilterControllerProvider);
Expand All @@ -23,33 +25,35 @@ class AttendanceGraph extends ConsumerWidget {
final value = ref.watch(attendanceDayProvider(filter: graphFilter));
return value.when(
data: (attendances) {
// End nicely on a sunday
final earliestDate = (attendances.keys.lastOrNull ?? DateTime.now())
.upcomingSat()
.subtract(const Duration(days: 6));
// Starts nicely on a sunday from the left
final earliestDate =
(attendances.keys.lastOrNull ?? DateTime.now()).stripTime();

return Directionality(
textDirection: TextDirection.rtl,
child: GridView.builder(
padding: const EdgeInsets.only(right: 16),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 8,
crossAxisCount: _crossAxisCount,
crossAxisSpacing: 2,
mainAxisSpacing: 2,
),
itemBuilder: (context, index) {
final row = index ~/ 8;
final idxInRow = index % 8;
final date = upcomingSat.subtract(
Duration(days: index - row - DateTime.daysPerWeek),
);
final row = index ~/ _crossAxisCount;
final idxInRow = index % _crossAxisCount;

// First date displayed is upcomingSat's date.
// We add an additional row on top for Weekday label
final date = upcomingSat
.subtract(Duration(days: index - row - _crossAxisCount + 1));

if (date.isBefore(earliestDate)) return null;

if (idxInRow == DateTime.daysPerWeek) {
// * Month Label
if (idxInRow == _crossAxisCount - 1) {
final datesInRow = <DateTime>[];
for (var i = 0; i < DateTime.daysPerWeek; i++) {
datesInRow.add(date.add(Duration(days: i + 1)));
for (var i = 1; i < _crossAxisCount; i++) {
datesInRow.add(date.add(Duration(days: i)));
}
final firstMonthDate =
datesInRow.firstWhereOrNull((e) => e.day == 1);
Expand All @@ -58,27 +62,32 @@ class AttendanceGraph extends ConsumerWidget {
alignment: Alignment.centerRight,
child: Text(
intl.DateFormat.MMM().format(firstMonthDate),
style: context.textTheme.labelLarge,
style: context.textTheme.labelSmall,
),
);
}
return const Offstage();
}

// Weekday Header
if (index < DateTime.daysPerWeek) {
// * Weekday Header
if (row == 0) {
return Align(
alignment: Alignment.bottomCenter,
child: Text(
intl.DateFormat.E().format(date),
style: context.textTheme.labelLarge,
intl.DateFormat.E().format(date).characters.first,
textAlign: TextAlign.center,
style: context.textTheme.labelSmall,
),
);
}

final dayAttendance = attendances[date] ?? [];
final color = graphFilter.color;
final opacity = max(min(2, dayAttendance.length) / 2, 0.05);
var border = const Border();
if (date == DateTime.now().stripTime()) {
border = Border.all(width: 2);
}

return Tooltip(
message: [
Expand All @@ -90,6 +99,7 @@ class AttendanceGraph extends ConsumerWidget {
showDuration: const Duration(seconds: 3),
child: NeuContainer(
shadow: false,
border: border,
color: color.withOpacity(opacity),
),
);
Expand Down Expand Up @@ -127,20 +137,24 @@ class AttendanceGraph extends ConsumerWidget {
child: GridView.builder(
padding: const EdgeInsets.only(right: 16),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 8,
crossAxisCount: _crossAxisCount,
crossAxisSpacing: 2,
mainAxisSpacing: 2,
),
itemBuilder: (context, index) {
final idxInRow = index % 8;
final row = index ~/ _crossAxisCount;
final idxInRow = index % _crossAxisCount;

final date = upcomingSat.subtract(
Duration(days: index - DateTime.daysPerWeek),
);
if (idxInRow == DateTime.daysPerWeek) {
// First date displayed is upcomingSat's date.
// We add an additional row on top for Weekday label
final date = upcomingSat
.subtract(Duration(days: index - row - _crossAxisCount + 1));

// * Month Label
if (idxInRow == _crossAxisCount - 1) {
final datesInRow = <DateTime>[];
for (var i = 0; i < DateTime.daysPerWeek; i++) {
datesInRow.add(date.add(Duration(days: i + 1)));
for (var i = 1; i < _crossAxisCount; i++) {
datesInRow.add(date.add(Duration(days: i)));
}
final firstMonthDate =
datesInRow.firstWhereOrNull((e) => e.day == 1);
Expand All @@ -149,21 +163,25 @@ class AttendanceGraph extends ConsumerWidget {
alignment: Alignment.centerRight,
child: Text(
intl.DateFormat.MMM().format(firstMonthDate),
style: context.textTheme.labelLarge,
style: context.textTheme.labelSmall,
),
);
}
return const Offstage();
}
if (index < DateTime.daysPerWeek) {

// * Weekday Header
if (row == 0) {
return Align(
alignment: Alignment.bottomCenter,
child: Text(
intl.DateFormat.E().format(date),
style: context.textTheme.labelLarge,
intl.DateFormat.E().format(date).characters.first,
textAlign: TextAlign.center,
style: context.textTheme.labelSmall,
),
);
}

return const ShimmerWidget(
child: NeuContainer(
shadow: false,
Expand Down

0 comments on commit 40158cb

Please sign in to comment.